geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bschucha...@apache.org
Subject [35/50] [abbrv] incubator-geode git commit: GEODE-143: logging must not cause cached values to be deserialized
Date Mon, 27 Jul 2015 23:19:58 GMT
GEODE-143: logging must not cause cached values to be deserialized

A more powerful StringUtils.forceToString now exists that will also
print out the elements of arrays. It used to just to a toString on the
array which only shows the array identity. The new code will (by default)
show the first 16 element values and after that say how many more the array
had that are not shown. If you set the sys prop StringUtils.MAX_ARRAY_ELEMENTS_TO_CONVERT
you can change the default of 16.


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

Branch: refs/heads/feature/GEODE-77
Commit: aeafb0151c28d397961a64bf9e8f9541dcb508ed
Parents: 7f72d8d
Author: Darrel Schneider <dschneider@pivotal.io>
Authored: Wed Jul 22 17:05:53 2015 -0700
Committer: Darrel Schneider <dschneider@pivotal.io>
Committed: Thu Jul 23 14:07:33 2015 -0700

----------------------------------------------------------------------
 .../internal/cache/AbstractRegionEntry.java     |   2 +-
 .../gemfire/internal/cache/EntryEventImpl.java  |   8 +-
 .../gemfire/internal/lang/StringUtils.java      | 364 ++++++++++++++++++-
 .../offheap/OffHeapCachedDeserializable.java    |   7 +-
 .../cache/ChunkValueWrapperJUnitTest.java       |   2 +-
 .../internal/lang/StringUtilsJUnitTest.java     |  33 ++
 6 files changed, 406 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/aeafb015/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/AbstractRegionEntry.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/AbstractRegionEntry.java
b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/AbstractRegionEntry.java
index 809996b..e67666a 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/AbstractRegionEntry.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/AbstractRegionEntry.java
@@ -1647,7 +1647,7 @@ public abstract class AbstractRegionEntry implements RegionEntry,
       event.setVersionTag(tag);
       if (logger.isDebugEnabled()) {
         logger.debug("generated tag {}; key={}; oldvalue={} newvalue={} client={} region={};
rvv={}", tag,
-            event.getKey(), event.getOldValue(), event.getNewValue(),
+            event.getKey(), event.getOldValueStringForm(), event.getNewValueStringForm(),
             (event.getContext() == null? "none" : event.getContext().getDistributedMember().getName()),
             region.getFullPath(), region.getVersionVector());
       }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/aeafb015/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 25466da..ed39106 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
@@ -13,7 +13,6 @@ import java.io.DataInput;
 import java.io.DataInputStream;
 import java.io.DataOutput;
 import java.io.IOException;
-
 import org.apache.logging.log4j.Logger;
 
 import com.gemstone.gemfire.CopyHelper;
@@ -1126,6 +1125,13 @@ public class EntryEventImpl
     return null;
   }
 
+  public final String getNewValueStringForm() {
+    return StringUtils.forceToString(basicGetNewValue());
+  }
+  public final String getOldValueStringForm() {
+    return StringUtils.forceToString(basicGetOldValue());
+  }
+  
   protected boolean applyDelta(boolean throwOnNullOldValue)
       throws EntryNotFoundException {
     if (this.newValue != null || this.delta == null) {

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/aeafb015/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/StringUtils.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/StringUtils.java
b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/StringUtils.java
index f5a467c..3aa6f13 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/StringUtils.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/StringUtils.java
@@ -9,6 +9,9 @@
 
 package com.gemstone.gemfire.internal.lang;
 
+import com.gemstone.gemfire.internal.cache.CachedDeserializable;
+import com.gemstone.gemfire.internal.cache.Token;
+
 /**
  * The StringUtils is an abstract utility class for working with and invoking operations
on String literals.
  * <p/>
@@ -329,6 +332,8 @@ public abstract class StringUtils {
     return buffer.toString();
   }
 
+  private static final int MAX_ARRAY_ELEMENTS_TO_CONVERT = Integer.getInteger("StringUtils.MAX_ARRAY_ELEMENTS_TO_CONVERT",
16);
+  
   /**
    * Used to convert the given object to a String. If anything goes wrong in this conversion
    * put some info about what went wrong on the result string but do not throw an exception.
@@ -337,10 +342,367 @@ public abstract class StringUtils {
    */
   public static String forceToString(Object o) {
     try {
-      return o.toString();
+      return objectToString(o, true, MAX_ARRAY_ELEMENTS_TO_CONVERT);
     } catch (RuntimeException ex) {
       return "Conversion to a string failed because " + ex;
     }
   }
+  
+  /**
+   * Convert an object to a string and return it.
+   * Handled CacheDeserializables without having them change the form they store.
+   * If deserialization is needed and fails then the string contains a message saying so
instead of throwing an exception.
+   * @param o the object to convert to a string
+   * @param convertArrayContents if true then the contents of the array will be in the string;
otherwise just the array identity
+   * @param maxArrayElements if convertArrayContents is true then this parameter limits how
many array elements are converted to the string.
+   *                         After the last converted element "and NNN more" is used to indicate
the number of elements not converted.
+   */
+  public static String objectToString(Object o, boolean convertArrayContents, int maxArrayElements)
{
+    if (o == null || o == Token.NOT_AVAILABLE) {
+      return "null";
+    } else if (o instanceof CachedDeserializable) {
+      CachedDeserializable cd = (CachedDeserializable)o;
+      return cd.getStringForm();
+    } else if (convertArrayContents && o.getClass().isArray()) {
+      Class<?> eClass = o.getClass();
+      if (eClass == byte[].class) {
+        return arrayToString((byte[])o, maxArrayElements);
+      } else if (eClass == boolean[].class) {
+        return arrayToString((boolean[])o, maxArrayElements);
+      } else if (eClass == char[].class) {
+        return arrayToString((char[])o, maxArrayElements);
+      } else if (eClass == short[].class) {
+        return arrayToString((short[])o, maxArrayElements);
+      } else if (eClass == int[].class) {
+        return arrayToString((int[])o, maxArrayElements);
+      } else if (eClass == long[].class) {
+        return arrayToString((long[])o, maxArrayElements);
+      } else if (eClass == float[].class) {
+        return arrayToString((float[])o, maxArrayElements);
+      } else if (eClass == double[].class) {
+        return arrayToString((double[])o, maxArrayElements);
+      } else {
+        return arrayToString((Object[]) o, maxArrayElements);
+      }
+    } else {
+      return o.toString();
+    }
+  }
+  
+  private static String arrayToString(Object[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    Class componentType = a.getClass().getComponentType();
+    if (iMax == -1) {
+      return componentType.getSimpleName() + "[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append(componentType.getSimpleName());
+    b.append('[');
+    for (int i = 0; ; i++) {
+      b.append(String.valueOf(a[i]));
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
 
+  private static String arrayToString(boolean[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "boolean[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("boolean[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
+
+  private static String arrayToString(byte[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "byte[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("byte[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
+
+  private static String arrayToString(char[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "char[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("char[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
+
+  private static String arrayToString(short[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "short[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("short[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
+
+  private static String arrayToString(int[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "int[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("int[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
+
+  private static String arrayToString(long[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "long[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("long[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
+
+  private static String arrayToString(float[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "float[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("float[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
+
+  private static String arrayToString(double[] a, int maxArrayElements) {
+    if (maxArrayElements < 0) {
+      maxArrayElements = 0;
+    }
+    if (a == null) {
+      return "null";
+    }
+    int iMax = a.length;
+    if (iMax > maxArrayElements) {
+      iMax = maxArrayElements;
+    }
+    iMax--;
+    if (iMax == -1) {
+      return "double[]";
+    }
+    StringBuilder b = new StringBuilder();
+    b.append("double[");
+    for (int i = 0; ; i++) {
+      b.append(a[i]);
+      if (i == iMax) {
+        int skipCount = a.length - maxArrayElements;
+        if (skipCount > 0) {
+          if (i > 0) {
+            b.append(", ");
+          }
+          b.append("and ");
+          b.append(skipCount);
+          b.append(" more");
+        }
+        return b.append(']').toString();
+      }
+      b.append(", ");
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/aeafb015/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapCachedDeserializable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapCachedDeserializable.java
b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapCachedDeserializable.java
index abba827..764a051 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapCachedDeserializable.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapCachedDeserializable.java
@@ -55,12 +55,7 @@ public abstract class OffHeapCachedDeserializable implements MemoryChunkWithRefC
   @Override
   public String getStringForm() {
     try {
-      Object o = getDeserializedForReading();
-      if (o instanceof byte[]) {
-        return Arrays.toString((byte[]) o);
-      } else {
-        return StringUtils.forceToString(o);
-      }
+      return StringUtils.forceToString(getDeserializedForReading());
     } catch (RuntimeException ex) {
       return "Could not convert object to string because " + ex;
     }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/aeafb015/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
index 229719f..234a534 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/ChunkValueWrapperJUnitTest.java
@@ -58,7 +58,7 @@ public class ChunkValueWrapperJUnitTest {
   
   @Test
   public void testGetBytesAsString() {
-    assertEquals("[0, 0, 0, 0, 0, 0, 0, 0]", createChunkValueWrapper(new byte[8], false).getBytesAsString());
+    assertEquals("byte[0, 0, 0, 0, 0, 0, 0, 0]", createChunkValueWrapper(new byte[8], false).getBytesAsString());
   }
   
   @Test

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/aeafb015/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/StringUtilsJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/StringUtilsJUnitTest.java
b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/StringUtilsJUnitTest.java
index 1420fbd..242f79a 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/StringUtilsJUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/StringUtilsJUnitTest.java
@@ -9,9 +9,16 @@ package com.gemstone.gemfire.internal.lang;
 
 import static org.junit.Assert.*;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.internal.cache.CachedDeserializable;
+import com.gemstone.gemfire.internal.cache.CachedDeserializableFactory;
 import com.gemstone.gemfire.test.junit.categories.UnitTest;
 
 /**
@@ -305,5 +312,31 @@ public class StringUtilsJUnitTest {
     assertNotNull(actualLine);
     assertEquals(expectedLine, actualLine);
   }
+  
+  @Test
+  public void testForceToString() throws IOException {
+    assertEquals("null", StringUtils.forceToString(null));
+    assertEquals("Object[][]", StringUtils.forceToString(new Object[0][0]));
+    assertEquals("byte[1, 2]", StringUtils.forceToString(new byte[]{1,2}));
+    assertEquals("int[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]", StringUtils.forceToString(new
int[]{1,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}));
+    assertEquals("long[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, and 1 more]",
StringUtils.forceToString(new long[]{1,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17}));
+    assertEquals("short[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, and 2 more]",
StringUtils.forceToString(new short[]{1,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18}));
+    assertEquals("char[1, 2, 3]", StringUtils.forceToString(new char[]{'1','2','3'}));
+    assertEquals("boolean[true, false]", StringUtils.forceToString(new boolean[]{true, false}));
+    assertEquals("float[1.0]", StringUtils.forceToString(new float[]{1.0f}));
+    assertEquals("double[1.0, 2.0]", StringUtils.forceToString(new double[]{1.0, 2.0}));
+    assertEquals("String[start, middle, end]", StringUtils.forceToString(new String[]{"start",
"middle", "end"}));
+    // make sure CacheDeserializables do not get deserialized when getting their string form
+    Object v = "value";
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    DataOutputStream dos = new DataOutputStream(baos);
+    DataSerializer.writeObject(v, dos);
+    dos.flush();
+    byte[] valueBytes = baos.toByteArray();
+    CachedDeserializable cd = CachedDeserializableFactory.create(valueBytes);
+    assertSame(valueBytes, cd.getValue());
+    assertEquals("value", StringUtils.forceToString(cd));
+    assertSame(valueBytes, cd.getValue());
+  }
 
 }


Mime
View raw message