You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2015/11/13 01:45:20 UTC

[1/3] incubator-geode git commit: GEODE-545: fix race in testCustomEntryIdleReset

Repository: incubator-geode
Updated Branches:
  refs/heads/develop 8b04c3d7f -> 781bd8d74


GEODE-545: fix race in testCustomEntryIdleReset


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/355a2d35
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/355a2d35
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/355a2d35

Branch: refs/heads/develop
Commit: 355a2d35df846b675e25f05d797f9787bd77042a
Parents: 8b04c3d
Author: Darrel Schneider <ds...@pivotal.io>
Authored: Thu Nov 12 16:07:56 2015 -0800
Committer: Darrel Schneider <ds...@pivotal.io>
Committed: Thu Nov 12 16:13:23 2015 -0800

----------------------------------------------------------------------
 .../gemfire/cache30/RegionTestCase.java         | 54 +++++++-------------
 1 file changed, 18 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/355a2d35/gemfire-core/src/test/java/com/gemstone/gemfire/cache30/RegionTestCase.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/cache30/RegionTestCase.java b/gemfire-core/src/test/java/com/gemstone/gemfire/cache30/RegionTestCase.java
index 35be2d0..0bc0ec0 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/cache30/RegionTestCase.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/cache30/RegionTestCase.java
@@ -3457,7 +3457,7 @@ public abstract class RegionTestCase extends CacheTestCase {
   public void testCustomEntryIdleReset() {
 
     final String name = this.getUniqueName();
-    final int timeout = 200; // ms
+    final int timeout = 200*1000; // ms
     final String key1 = "KEY1";
     final String value = "VALUE";
     
@@ -3475,55 +3475,37 @@ public abstract class RegionTestCase extends CacheTestCase {
     factory.addCacheListener(list);
     RegionAttributes attrs = factory.create();
     
-    Region region = null;
     System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
     try {
-      region = createRegion(name, attrs);
+      LocalRegion region = (LocalRegion) createRegion(name, attrs);
 
     // DebuggerSupport.waitForJavaDebugger(getLogWriter(), "Set breakpoint in invalidate");
     ExpiryTask.suspendExpiration();
-    Region.Entry entry = null;
-    long tilt;
     try {
       region.create(key1, value);
-      tilt = System.currentTimeMillis() + timeout;
       assertTrue(list.waitForInvocation(5000));
-      entry = region.getEntry(key1);
+      Region.Entry entry = region.getEntry(key1);
       assertNotNull(entry.getValue());
-    } 
-    finally {
-      ExpiryTask.permitExpiration();
-    }
-    
-    pause(timeout / 2);
-    long now = System.currentTimeMillis();
-    if (entry.getValue() == null && now < tilt) {
-      fail("Entry invalidated " + (tilt - now) + " ms prematurely");
-    }
-    region.get(key1); // touch again
-    
-    waitForInvalidate(entry, tilt);
-
-    // Do it again with a put (I guess)
-    ExpiryTask.suspendExpiration();
-    try {
+      EntryExpiryTask eet = region.getEntryExpiryTask(key1);
+      final long createExpiryTime = eet.getExpirationTime();
+      waitForExpiryClockToChange(region);
+      region.get(key1);
+      assertSame(eet, region.getEntryExpiryTask(key1));
+      final long getExpiryTime = eet.getExpirationTime();
+      if (getExpiryTime - createExpiryTime <= 0L) {
+        fail("get did not reset the expiration time. createExpiryTime=" + createExpiryTime + " getExpiryTime=" + getExpiryTime);
+      }
+      waitForExpiryClockToChange(region);
       region.put(key1, value);
-      tilt = System.currentTimeMillis() + timeout;
-      entry = region.getEntry(key1);
-      assertNotNull(entry.getValue());
+      assertSame(eet, region.getEntryExpiryTask(key1));
+      final long putExpiryTime = eet.getExpirationTime();
+      if (putExpiryTime - getExpiryTime <= 0L) {
+        fail("put did not reset the expiration time. getExpiryTime=" + getExpiryTime + " putExpiryTime=" + putExpiryTime);
+      }
     } 
     finally {
       ExpiryTask.permitExpiration();
     }
-    
-    pause(timeout / 2);
-    now = System.currentTimeMillis();
-    if (entry.getValue() == null && now < tilt) {
-      fail("entry invalidated " + (tilt - now) + " ms prematurely");
-    }
-    region.put(key1, value); // touch
-    
-    waitForInvalidate(entry, tilt);
     } 
     finally {
       System.getProperties().remove(LocalRegion.EXPIRY_MS_PROPERTY);


[2/3] incubator-geode git commit: GEODE-427: add more test logging

Posted by ds...@apache.org.
GEODE-427: add more test logging


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/5118ad08
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/5118ad08
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/5118ad08

Branch: refs/heads/develop
Commit: 5118ad08ea5882c46fd2238aa08183db84c6f880
Parents: 355a2d3
Author: Darrel Schneider <ds...@pivotal.io>
Authored: Thu Nov 12 16:18:06 2015 -0800
Committer: Darrel Schneider <ds...@pivotal.io>
Committed: Thu Nov 12 16:18:06 2015 -0800

----------------------------------------------------------------------
 .../cache/management/MemoryThresholdsDUnitTest.java     | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5118ad08/gemfire-core/src/test/java/com/gemstone/gemfire/cache/management/MemoryThresholdsDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/cache/management/MemoryThresholdsDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/cache/management/MemoryThresholdsDUnitTest.java
index 1d1ada3..4edab28 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/cache/management/MemoryThresholdsDUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/cache/management/MemoryThresholdsDUnitTest.java
@@ -409,7 +409,7 @@ public class MemoryThresholdsDUnitTest extends ClientServerTestCase {
     registerTestMemoryThresholdListener(server2);
 
     //NORMAL -> CRITICAL
-    server2.invoke(new SerializableCallable() {
+    server2.invoke(new SerializableCallable("NORMAL->CRITICAL") {
       public Object call() throws Exception {
         GemFireCacheImpl gfCache = (GemFireCacheImpl)getCache();
         getCache().getLoggerI18n().fine(addExpectedExString);
@@ -428,7 +428,7 @@ public class MemoryThresholdsDUnitTest extends ClientServerTestCase {
     verifyListenerValue(server1, MemoryState.NORMAL, 0, true);;
 
     //CRITICAL -> EVICTION
-    server2.invoke(new SerializableCallable() {
+    server2.invoke(new SerializableCallable("CRITICAL->EVICTION") {
       public Object call() throws Exception {
         GemFireCacheImpl gfCache = (GemFireCacheImpl)getCache();
         getCache().getLoggerI18n().fine(addExpectedBelow);
@@ -445,7 +445,7 @@ public class MemoryThresholdsDUnitTest extends ClientServerTestCase {
     verifyListenerValue(server1, MemoryState.NORMAL, 0, true);;
     
     //EVICTION -> EVICTION
-    server2.invoke(new SerializableCallable() {
+    server2.invoke(new SerializableCallable("EVICTION->EVICTION") {
       public Object call() throws Exception {
         GemFireCacheImpl gfCache = (GemFireCacheImpl)getCache();
         gfCache.getResourceManager().getHeapMonitor().updateStateAndSendEvent(840);
@@ -460,7 +460,7 @@ public class MemoryThresholdsDUnitTest extends ClientServerTestCase {
     verifyListenerValue(server1, MemoryState.NORMAL, 0, true);
 
     //EVICTION -> NORMAL
-    server2.invoke(new SerializableCallable() {
+    server2.invoke(new SerializableCallable("EVICTION->NORMAL") {
       public Object call() throws Exception {
         GemFireCacheImpl gfCache = (GemFireCacheImpl)getCache();
         gfCache.getResourceManager().getHeapMonitor().updateStateAndSendEvent(750);
@@ -477,7 +477,7 @@ public class MemoryThresholdsDUnitTest extends ClientServerTestCase {
     
     this.getLogWriter().info("before NORMAL->CRITICAL->NORMAL");
     //NORMAL -> EVICTION -> NORMAL
-    server2.invoke(new SerializableCallable() {
+    server2.invoke(new SerializableCallable("NORMAL->CRITICAL->NORMAL") {
       public Object call() throws Exception {
         GemFireCacheImpl gfCache = (GemFireCacheImpl)getCache();
         gfCache.getResourceManager().getHeapMonitor().updateStateAndSendEvent(950);
@@ -495,7 +495,7 @@ public class MemoryThresholdsDUnitTest extends ClientServerTestCase {
     verifyListenerValue(server1, MemoryState.NORMAL, 2, true);
     
     //NORMAL -> EVICTION
-    server2.invoke(new SerializableCallable() {
+    server2.invoke(new SerializableCallable("NORMAL->EVICTION") {
       public Object call() throws Exception {
         GemFireCacheImpl gfCache = (GemFireCacheImpl)getCache();
         gfCache.getResourceManager().getHeapMonitor().updateStateAndSendEvent(850);


[3/3] incubator-geode git commit: GEODE-539: remove XD off-heap artifacts

Posted by ds...@apache.org.
GEODE-539: remove XD off-heap artifacts

The OffHeapReference interface has been removed.
Use the StoredObject interface instead.

The XD SRC_TYPE constants have been renamed to
unused and a comment added explaining why we might
want to keep the SRC_TYPE/ChunkType feature around
for future off-heap extensions.


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/781bd8d7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/781bd8d7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/781bd8d7

Branch: refs/heads/develop
Commit: 781bd8d74e4ffcfbb12b286dd7a582a1de586f78
Parents: 5118ad0
Author: Darrel Schneider <ds...@pivotal.io>
Authored: Thu Nov 12 16:24:40 2015 -0800
Committer: Darrel Schneider <ds...@pivotal.io>
Committed: Thu Nov 12 16:35:54 2015 -0800

----------------------------------------------------------------------
 .../gemfire/internal/cache/EntryEventImpl.java  |  1 -
 .../gemfire/internal/offheap/OffHeapHelper.java |  4 +-
 .../internal/offheap/OffHeapReference.java      | 72 --------------------
 .../offheap/SimpleMemoryAllocatorImpl.java      | 28 +++++---
 .../gemfire/internal/offheap/StoredObject.java  | 42 +++++++++++-
 5 files changed, 63 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/781bd8d7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/EntryEventImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/EntryEventImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/EntryEventImpl.java
index b7fbf1e..0786a69 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/EntryEventImpl.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/EntryEventImpl.java
@@ -73,7 +73,6 @@ import com.gemstone.gemfire.internal.logging.LogService;
 import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
 import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
 import com.gemstone.gemfire.internal.offheap.OffHeapHelper;
-import com.gemstone.gemfire.internal.offheap.OffHeapReference;
 import com.gemstone.gemfire.internal.offheap.OffHeapRegionEntryHelper;
 import com.gemstone.gemfire.internal.offheap.Releasable;
 import com.gemstone.gemfire.internal.offheap.SimpleMemoryAllocatorImpl;

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/781bd8d7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapHelper.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapHelper.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapHelper.java
index 3d62fdf..b5677cd 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapHelper.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapHelper.java
@@ -37,8 +37,8 @@ public class OffHeapHelper {
    * Note even if o is sqlf off-heap byte[] or byte[][] the heap form will be created.
    */
   public static Object getHeapForm(Object o) {
-    if (o instanceof OffHeapReference) {
-      return ((OffHeapReference) o).getValueAsDeserializedHeapObject();
+    if (o instanceof StoredObject) {
+      return ((StoredObject) o).getValueAsDeserializedHeapObject();
     } else {
       return o;
     }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/781bd8d7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapReference.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapReference.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapReference.java
deleted file mode 100644
index 1507273..0000000
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapReference.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gemstone.gemfire.internal.offheap;
-
-import com.gemstone.gemfire.internal.Sendable;
-import com.gemstone.gemfire.internal.offheap.annotations.Retained;
-
-/**
- * Instances of this interface are references to off-heap.
- * Note: this interface is part of building the odbc drivers. Any classes or interfaces it references
- * need to be added to SQLFire.xml -sqlf-odbc-java-list.
- * Because of odbc we do not want this interface to extend CachedDeserializable because it pulls in too many of the GemFire code base.
- * 
- * @author darrel
- * @since 9.0
- */
-public interface OffHeapReference extends Releasable, Sendable {
-
-  /**
-   * Call to indicate that this object's memory is in use by the caller.
-   * The memory will stay allocated until {@link #release()} is called.
-   * It is ok for a thread other than the one that called this method to call release.
-   * This method is called implicitly at the time the chunk is allocated.
-   * Note: @Retained tells you that "this" is retained by this method.
-   * 
-   * @throws IllegalStateException if the max ref count is exceeded.
-   * @return true if we are able to retain this chunk; false if we need to retry
-   */
-  @Retained
-  public boolean retain();
-
-  /**
-   * Returns true if the value stored in this memory chunk is a serialized object. Returns false if it is a byte array.
-   */
-  public boolean isSerialized();
-
-  /**
-   * Returns true if the value stored in this memory chunk is compressed. Returns false if it is uncompressed.
-   */
-  public boolean isCompressed();
-
-  /**
-   * Returns the data stored in this object as a deserialized heap object.
-   * If it is not serialized then the result will be a byte[].
-   * Otherwise the deserialized heap form of the stored object is returned.
-   * @return the data stored in this object as a deserialized heap object.
-   */
-  public Object getValueAsDeserializedHeapObject();
-
-  /**
-   * Returns the data stored in this object as a heap byte array.
-   * If it is not serialized then the result will only contain the raw bytes stored in this object.
-   * Otherwise the serialized heap form of the stored object is returned.
-   * @return the data stored in this object as a heap byte array.
-   */
-  public byte[] getValueAsHeapByteArray();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/781bd8d7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
index a38daa6..c800335 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/SimpleMemoryAllocatorImpl.java
@@ -1729,15 +1729,27 @@ public final class SimpleMemoryAllocatorImpl implements MemoryAllocator, MemoryI
     final static long FILL_PATTERN = 0x3c3c3c3c3c3c3c3cL;
     final static byte FILL_BYTE = 0x3c;
     
-    public final static int SRC_TYPE_NO_LOB_NO_DELTA = 0 << SRC_TYPE_SHIFT;
-    public final static int SRC_TYPE_WITH_LOBS = 1 << SRC_TYPE_SHIFT;
-    public final static int SRC_TYPE_WITH_SINGLE_DELTA = 2 << SRC_TYPE_SHIFT;
-    public final static int SRC_TYPE_WITH_MULTIPLE_DELTAS = 3 << SRC_TYPE_SHIFT;
-    //public final static int SRC_TYPE_IS_LOB = 4 << SRC_TYPE_SHIFT;
+    // The 8 bits reserved for SRC_TYPE are basically no longer used.
+    // So we could free up these 8 bits for some other use or we could
+    // keep them for future extensions.
+    // If we ever want to allocate other "types" into a chunk of off-heap
+    // memory then the SRC_TYPE would be the way to go.
+    // For example we may want to allocate the memory for the off-heap
+    // RegionEntry in off-heap memory without it being of type GFE.
+    // When it is of type GFE then it either needs to be the bytes
+    // of a byte array or it needs to be a serialized java object.
+    // For the RegionEntry we may want all the primitive fields of
+    // the entry at certain offsets in the off-heap memory so we could
+    // access them directly in native byte format (i.e. no serialization).
+    // Note that for every SRC_TYPE we should have a ChunkType subclass.
+    public final static int SRC_TYPE_UNUSED0 = 0 << SRC_TYPE_SHIFT;
+    public final static int SRC_TYPE_UNUSED1 = 1 << SRC_TYPE_SHIFT;
+    public final static int SRC_TYPE_UNUSED2 = 2 << SRC_TYPE_SHIFT;
+    public final static int SRC_TYPE_UNUSED3 = 3 << SRC_TYPE_SHIFT;
     public final static int SRC_TYPE_GFE = 4 << SRC_TYPE_SHIFT;
-    public final static int SRC_TYPE_UNUSED1 = 5 << SRC_TYPE_SHIFT;
-    public final static int SRC_TYPE_UNUSED2 = 6 << SRC_TYPE_SHIFT;
-    public final static int SRC_TYPE_UNUSED3 = 7 << SRC_TYPE_SHIFT;
+    public final static int SRC_TYPE_UNUSED5 = 5 << SRC_TYPE_SHIFT;
+    public final static int SRC_TYPE_UNUSED6 = 6 << SRC_TYPE_SHIFT;
+    public final static int SRC_TYPE_UNUSED7 = 7 << SRC_TYPE_SHIFT;
     
     protected Chunk(long memoryAddress, int chunkSize, ChunkType chunkType) {
       validateAddressAndSize(memoryAddress, chunkSize);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/781bd8d7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/StoredObject.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/StoredObject.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/StoredObject.java
index 083c5ff..4d93a07 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/StoredObject.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/StoredObject.java
@@ -19,7 +19,9 @@ package com.gemstone.gemfire.internal.offheap;
 import java.io.DataOutput;
 import java.io.IOException;
 
+import com.gemstone.gemfire.internal.Sendable;
 import com.gemstone.gemfire.internal.cache.CachedDeserializable;
+import com.gemstone.gemfire.internal.offheap.annotations.Retained;
 
 /**
  * Represents an object stored in the cache.
@@ -29,7 +31,45 @@ import com.gemstone.gemfire.internal.cache.CachedDeserializable;
  * @author darrel
  * @since 9.0
  */
-public interface StoredObject extends OffHeapReference, CachedDeserializable {
+public interface StoredObject extends Releasable, Sendable, CachedDeserializable {
+  /**
+   * Call to indicate that this object's memory is in use by the caller.
+   * The memory will stay allocated until {@link #release()} is called.
+   * It is ok for a thread other than the one that called this method to call release.
+   * This method is called implicitly at the time the chunk is allocated.
+   * Note: @Retained tells you that "this" is retained by this method.
+   * 
+   * @throws IllegalStateException if the max ref count is exceeded.
+   * @return true if we are able to retain this chunk; false if we need to retry
+   */
+  @Retained
+  public boolean retain();
+
+  /**
+   * Returns true if the value stored in this memory chunk is a serialized object. Returns false if it is a byte array.
+   */
+  public boolean isSerialized();
+
+  /**
+   * Returns true if the value stored in this memory chunk is compressed. Returns false if it is uncompressed.
+   */
+  public boolean isCompressed();
+
+  /**
+   * Returns the data stored in this object as a deserialized heap object.
+   * If it is not serialized then the result will be a byte[].
+   * Otherwise the deserialized heap form of the stored object is returned.
+   * @return the data stored in this object as a deserialized heap object.
+   */
+  public Object getValueAsDeserializedHeapObject();
+
+  /**
+   * Returns the data stored in this object as a heap byte array.
+   * If it is not serialized then the result will only contain the raw bytes stored in this object.
+   * Otherwise the serialized heap form of the stored object is returned.
+   * @return the data stored in this object as a heap byte array.
+   */
+  public byte[] getValueAsHeapByteArray();
   /**
    * Take all the bytes in the object and write them to the data output as a byte array.
    * If the StoredObject is not serialized then its raw byte array is sent.