You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by mm...@apache.org on 2021/02/08 21:56:09 UTC

[geode-native] branch develop updated: GEODE-8562: Use standard .NET types in .NET ClassAsKey Example (#742)

This is an automated email from the ASF dual-hosted git repository.

mmartell pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode-native.git


The following commit(s) were added to refs/heads/develop by this push:
     new 453324b  GEODE-8562: Use standard .NET types in .NET ClassAsKey Example (#742)
453324b is described below

commit 453324b7460c575424b8cb96878b1e4118ff7bd4
Author: Michael Martell <mm...@pivotal.io>
AuthorDate: Mon Feb 8 13:55:08 2021 -0800

    GEODE-8562: Use standard .NET types in .NET ClassAsKey Example (#742)
    
    * Use standard .NET types (e.g. String instead of CacheableString)
    * Use new Objects.Hash() API so client and server match
    * Remove public from CacheableString since no longer needed
    * Print matching hashCode output and add to README.md
---
 clicache/src/CacheableString.hpp        |  2 +-
 examples/dotnet/classaskey/PhotosKey.cs | 39 +++++++---------
 examples/dotnet/classaskey/Program.cs   | 42 +++++++----------
 examples/dotnet/classaskey/README.md    | 80 +++++++++++++++++++++------------
 examples/utilities/PhotosKey.java       | 15 ++-----
 5 files changed, 87 insertions(+), 91 deletions(-)

diff --git a/clicache/src/CacheableString.hpp b/clicache/src/CacheableString.hpp
index b4f1c37..c15d7f3 100644
--- a/clicache/src/CacheableString.hpp
+++ b/clicache/src/CacheableString.hpp
@@ -40,7 +40,7 @@ namespace Apache
       /// An immutable string wrapper that can serve as a distributable
       /// key object for caching as well as being a string value.
       /// </summary>
-      public ref class CacheableString
+      ref class CacheableString
         :  public IDataSerializablePrimitive, public CacheableKey
       {
       public:
diff --git a/examples/dotnet/classaskey/PhotosKey.cs b/examples/dotnet/classaskey/PhotosKey.cs
index eb8bb9a..f94c4ef 100644
--- a/examples/dotnet/classaskey/PhotosKey.cs
+++ b/examples/dotnet/classaskey/PhotosKey.cs
@@ -22,18 +22,22 @@ namespace Apache.Geode.Examples.ClassAsKey
 {
   public class PhotosKey : IDataSerializable, ICacheableKey
   {
-    public List<CacheableString> people;
-    public CacheableDate rangeStart;
-    public CacheableDate rangeEnd;
+    public List<String> people;
+    public DateTime rangeStart;
+    public DateTime rangeEnd;
 
     // A default constructor is required for deserialization
     public PhotosKey() { }
 
-    public PhotosKey(List<CacheableString> names, CacheableDate start, CacheableDate end)
+    public PhotosKey(List<String> names, DateTime start, DateTime end)
     {
       people = names;
-      rangeStart = start;
-      rangeEnd = end;
+
+      // Geode server defaults to Utc to ensure hashes match between client and
+      // server
+      TimeZone tz = TimeZone.CurrentTimeZone;
+      rangeStart = tz.ToUniversalTime(start);
+      rangeEnd = tz.ToUniversalTime(end);
     }
 
     public override string ToString()
@@ -53,15 +57,15 @@ namespace Apache.Geode.Examples.ClassAsKey
     public void ToData(DataOutput output)
     {
       output.WriteObject(people);
-      output.WriteObject(rangeStart);
-      output.WriteObject(rangeEnd);
+      output.WriteDate(rangeStart);
+      output.WriteDate(rangeEnd);
     }
 
     public void FromData(DataInput input)
     {
-      people = (List<CacheableString>)input.ReadObject();
-      rangeStart = (CacheableDate)input.ReadObject();
-      rangeEnd = (CacheableDate)input.ReadObject();
+      people = (List<String>)input.ReadObject();
+      rangeStart = (DateTime)input.ReadDate();
+      rangeEnd = (DateTime)input.ReadDate();
     }
 
     public ulong ObjectSize
@@ -94,17 +98,7 @@ namespace Apache.Geode.Examples.ClassAsKey
 
     public override int GetHashCode()
     {
-      int prime = 31;
-      int result = 1;
-      foreach (CacheableString cs in people)
-      {
-        result = result * prime + cs.GetHashCode();
-      }
-
-      result = result * prime + rangeStart.GetHashCode();
-      result = result * prime + rangeEnd.GetHashCode();
-
-      return result;
+      return Objects.Hash(people, rangeStart, rangeEnd);
     }
 
     public static ISerializable CreateDeserializable()
@@ -114,4 +108,3 @@ namespace Apache.Geode.Examples.ClassAsKey
   }
 }
 
-
diff --git a/examples/dotnet/classaskey/Program.cs b/examples/dotnet/classaskey/Program.cs
index e51093d..0352440 100644
--- a/examples/dotnet/classaskey/Program.cs
+++ b/examples/dotnet/classaskey/Program.cs
@@ -39,8 +39,8 @@ namespace Apache.Geode.Examples.ClassAsKey
       PhotosKey[] keys = new PhotosKey[MAXPHOTOKEYS];
       PhotosValue[] values = new PhotosValue[MAXPHOTOKEYS];
 
-      CacheableDate start;
-      CacheableDate end;
+      DateTime start;
+      DateTime end;
 
       rand = new Random();
       int numPhotos;
@@ -62,7 +62,8 @@ namespace Apache.Geode.Examples.ClassAsKey
         }
         values[i] = new PhotosValue(metaData);
 
-        Console.WriteLine("Inserting " + numPhotos + " photos for key: " + keys[i].ToString());
+        Console.WriteLine("Inserting " + numPhotos + " photos for key: " + keys[i].ToString() +
+          " with hashCode = " + Objects.Hash(keys[i].people, keys[i].rangeStart, keys[i].rangeEnd));
 
         photosMetaData.Put(keys[i], values[i]);
       }
@@ -133,16 +134,16 @@ namespace Apache.Geode.Examples.ClassAsKey
       return photosMetaData;
     }
 
-    public static List<CacheableString> ChoosePeople()
+    public static List<String> ChoosePeople()
     {
-      List<CacheableString> availablePeople = new List<CacheableString> {
-        new CacheableString("Alice"),
-        new CacheableString("Bob"),
-        new CacheableString("Carol"),
-        new CacheableString("Ted")
+      List<String> availablePeople = new List<String> {
+        "Alice",
+        "Bob",
+        "Carol",
+        "Ted"
       };
 
-      List<CacheableString> chosenPeople = new List<CacheableString>();
+      List<String> chosenPeople = new List<String>();
 
       // Choose at least one person
       int numChosen = rand.Next(1, availablePeople.Count+1);
@@ -162,23 +163,21 @@ namespace Apache.Geode.Examples.ClassAsKey
       }
 
       // Sort the chosen. We only care who is chosen, not the order they're chosen.
-      IComparer<CacheableString> comparer = new CacheableStringComparer();
-      chosenPeople.Sort(comparer);
+      chosenPeople.Sort();
       return chosenPeople;
     }
 
-    public static void ChooseDateRange(out CacheableDate start, out CacheableDate end)
+    public static void ChooseDateRange(out DateTime start, out DateTime end)
     {
       //Choose start and end dates between Jan 1, 1970 and now
       var earliestStart = new DateTime(1970, 1, 1);
       int numAvailableDays = (int)(DateTime.Now - earliestStart).TotalDays;
 
       var startIndex = rand.Next(numAvailableDays);
-      var startDate = earliestStart.AddDays(startIndex);
-      start = new CacheableDate(startDate);
+      start = earliestStart.AddDays(startIndex);
 
-      int numRemainingDays = (int)(DateTime.Now - startDate).TotalDays;
-      end = new CacheableDate(startDate.AddDays(rand.Next(numRemainingDays)));
+      int numRemainingDays = (int)(DateTime.Now - start).TotalDays;
+      end = start.AddDays(rand.Next(numRemainingDays));
     }
 
     public static Bitmap ChooseThumb()
@@ -198,15 +197,6 @@ namespace Apache.Geode.Examples.ClassAsKey
       return thumb;
     }
   }
-
-  public class CacheableStringComparer : IComparer<CacheableString>
-  {
-    public int Compare(CacheableString a, CacheableString b)
-    {
-      return a.Value.CompareTo(b.Value);
-    }
-  }
-
 }
 
 
diff --git a/examples/dotnet/classaskey/README.md b/examples/dotnet/classaskey/README.md
index 2cf63ff..29dd20f 100644
--- a/examples/dotnet/classaskey/README.md
+++ b/examples/dotnet/classaskey/README.md
@@ -1,6 +1,6 @@
 # classaskey example
 
-Many applications are best served by using compound keys to store and retrieve data. Geode Native fills this need by allowing users to define their own custom class to be used as a key. By leveraging the Geode Native Cacheable data types, it is very easy to implement the ICacheableKey interface and design classes that can be used as keys.
+Many applications are best served by using compound keys to store and retrieve data. Geode Native fills this need by allowing users to define their own custom class to be used as a key. It is very easy to implement the ICacheableKey interface and design classes that can be used as keys. In addition, by leveraging the Geode Native Objects.Hash() function will ensure client and server hashcodes match. This is important for performance sensitive applications that use single hop.
 
 This example shows how to design a photo filter as the key for storing metadata for a photo library. The photo filter class (called PhotoKeys in the code) provides for storing and retrieving all photos containing a group of people and that were taken during a date range. The photo metadata class (called PhotoValues in the code) contains the full resolution photoId and thumbnail image for the photo key. In this example, the photoId is an integer representing an index into a photo library. [...]
 
@@ -33,51 +33,73 @@ This example shows how to design a photo filter as the key for storing metadata
     $ startserver.ps1
     ```
 
-1. Execute `Debug\dotnet-classaskey.exe`. Expect output similar to below. Since the keys are generated using random numbers, your output will differ.
+1. Execute `Debug\dotnet-classaskey.exe`. Expect client and server output similar to below. Since the keys are generated using random numbers, your output will differ. However, as shown in the following output, the hashCodes should match between client and server.
 
+    Program output:
     ```console
     Registering for data serialization
-    Populating the photos region
-
-    Inserting 5 photos for key: {Alice, Bob, Carol, Ted} from 7/3/1999 12:00:00 AM to 3/17/2011 12:00:00 AM
-    Inserting 2 photos for key: {Alice, Bob, Ted} from 9/22/1980 12:00:00 AM to 12/5/1980 12:00:00 AM
-    Inserting 5 photos for key: {Alice, Carol} from 3/6/1990 12:00:00 AM to 9/26/1993 12:00:00 AM
-    Inserting 1 photos for key: {Alice, Bob} from 1/29/1999 12:00:00 AM to 2/1/2002 12:00:00 AM
-    Inserting 0 photos for key: {Alice, Bob, Carol, Ted} from 6/5/1989 12:00:00 AM to 7/7/1989 12:00:00 AM
-    Inserting 1 photos for key: {Alice, Bob} from 4/8/1979 12:00:00 AM to 5/26/2011 12:00:00 AM
-    Inserting 0 photos for key: {Alice, Carol, Ted} from 5/25/1977 12:00:00 AM to 5/15/1997 12:00:00 AM
-    Inserting 0 photos for key: {Bob} from 2/20/1981 12:00:00 AM to 3/11/2020 12:00:00 AM
-    Inserting 0 photos for key: {Alice, Bob, Carol, Ted} from 7/9/1982 12:00:00 AM to 4/20/1998 12:00:00 AM
-    Inserting 3 photos for key: {Alice, Bob, Carol, Ted} from 11/24/2007 12:00:00 AM to 4/30/2012 12:00:00 AM
-
-    Fetching photos for key: {Alice, Bob, Carol, Ted} from 7/3/1999 12:00:00 AM to 3/17/2011 12:00:00 AM
+    Populating the photosMetaData region
+
+    Inserting 3 photos for key: {Alice} from 4/21/2017 7:00:00 AM to 7/18/2020 7:00:00 AM with hashCode = -401665386
+    Inserting 3 photos for key: {Bob, Carol, Ted} from 7/26/2002 7:00:00 AM to 7/4/2005 7:00:00 AM with hashCode = -1032114678
+    Inserting 2 photos for key: {Alice, Bob, Carol, Ted} from 4/30/1987 7:00:00 AM to 4/15/2020 7:00:00 AM with hashCode = -647461847
+    Inserting 0 photos for key: {Alice, Bob, Carol, Ted} from 8/3/1971 7:00:00 AM to 2/23/2015 8:00:00 AM with hashCode = -358151561
+    Inserting 2 photos for key: {Alice, Bob, Carol, Ted} from 7/5/1984 7:00:00 AM to 11/6/1985 8:00:00 AM with hashCode = 452667681
+    Inserting 2 photos for key: {Bob} from 11/1/1988 7:00:00 AM to 5/3/1992 7:00:00 AM with hashCode = 651272813
+    Inserting 2 photos for key: {Alice, Ted} from 7/25/1982 7:00:00 AM to 3/23/1999 7:00:00 AM with hashCode = 1995204525
+    Inserting 5 photos for key: {Alice, Bob, Carol, Ted} from 12/12/1974 8:00:00 AM to 1/10/1990 8:00:00 AM with hashCode = -1945749946
+    Inserting 1 photos for key: {Alice, Bob, Carol, Ted} from 12/31/1990 8:00:00 AM to 9/26/1997 7:00:00 AM with hashCode = 1893650760
+    Inserting 4 photos for key: {Bob, Carol, Ted} from 5/7/2016 7:00:00 AM to 5/30/2016 7:00:00 AM with hashCode = 664954774
+
+    Fetching photos for key: {Alice} from 4/21/2017 7:00:00 AM to 7/18/2020 7:00:00 AM
        Fetching photo number 0
        Fetching photo number 1
        Fetching photo number 2
-       Fetching photo number 3
-       Fetching photo number 4
-    Fetching photos for key: {Alice, Bob, Ted} from 9/22/1980 12:00:00 AM to 12/5/1980 12:00:00 AM
+    Fetching photos for key: {Bob, Carol, Ted} from 7/26/2002 7:00:00 AM to 7/4/2005 7:00:00 AM
+       Fetching photo number 0
+       Fetching photo number 1
+       Fetching photo number 2
+    Fetching photos for key: {Alice, Bob, Carol, Ted} from 4/30/1987 7:00:00 AM to 4/15/2020 7:00:00 AM
+       Fetching photo number 0
+       Fetching photo number 1
+    Fetching photos for key: {Alice, Bob, Carol, Ted} from 8/3/1971 7:00:00 AM to 2/23/2015 8:00:00 AM
+    Fetching photos for key: {Alice, Bob, Carol, Ted} from 7/5/1984 7:00:00 AM to 11/6/1985 8:00:00 AM
        Fetching photo number 0
        Fetching photo number 1
-    Fetching photos for key: {Alice, Carol} from 3/6/1990 12:00:00 AM to 9/26/1993 12:00:00 AM
+    Fetching photos for key: {Bob} from 11/1/1988 7:00:00 AM to 5/3/1992 7:00:00 AM
+       Fetching photo number 0
+       Fetching photo number 1
+    Fetching photos for key: {Alice, Ted} from 7/25/1982 7:00:00 AM to 3/23/1999 7:00:00 AM
+       Fetching photo number 0
+       Fetching photo number 1
+    Fetching photos for key: {Alice, Bob, Carol, Ted} from 12/12/1974 8:00:00 AM to 1/10/1990 8:00:00 AM
        Fetching photo number 0
        Fetching photo number 1
        Fetching photo number 2
        Fetching photo number 3
        Fetching photo number 4
-    Fetching photos for key: {Alice, Bob} from 1/29/1999 12:00:00 AM to 2/1/2002 12:00:00 AM
-       Fetching photo number 0
-    Fetching photos for key: {Alice, Bob, Carol, Ted} from 6/5/1989 12:00:00 AM to 7/7/1989 12:00:00 AM
-    Fetching photos for key: {Alice, Bob} from 4/8/1979 12:00:00 AM to 5/26/2011 12:00:00 AM
+    Fetching photos for key: {Alice, Bob, Carol, Ted} from 12/31/1990 8:00:00 AM to 9/26/1997 7:00:00 AM
        Fetching photo number 0
-    Fetching photos for key: {Alice, Carol, Ted} from 5/25/1977 12:00:00 AM to 5/15/1997 12:00:00 AM
-    Fetching photos for key: {Bob} from 2/20/1981 12:00:00 AM to 3/11/2020 12:00:00 AM
-    Fetching photos for key: {Alice, Bob, Carol, Ted} from 7/9/1982 12:00:00 AM to 4/20/1998 12:00:00 AM
-    Fetching photos for key: {Alice, Bob, Carol, Ted} from 11/24/2007 12:00:00 AM to 4/30/2012 12:00:00 AM
+    Fetching photos for key: {Bob, Carol, Ted} from 5/7/2016 7:00:00 AM to 5/30/2016 7:00:00 AM
        Fetching photo number 0
        Fetching photo number 1
        Fetching photo number 2
-    [fine 2021/01/16 23:55:35.040714 Pacific Standard Time FirstPro:26196 20716] Cache closed.
+       Fetching photo number 3
+    [fine 2021/02/06 14:20:08.989562 Pacific Standard Time  FirstPro:548 23060] Cache closed.
+    [fine 2021/02/06 14:20:09.000032 Pacific Standard Time  FirstPro:548 23060] Removing cliCallback 1
+     ```
+     Server Log (for readability filtered for just the hashCode):
+     ```console
+    [warn 2021/02/06 14:20:08.200 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = -401665386
+    [warn 2021/02/06 14:20:08.236 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = -1032114678
+    [warn 2021/02/06 14:20:08.272 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = -647461847
+    [warn 2021/02/06 14:20:08.285 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = -358151561
+    [warn 2021/02/06 14:20:08.330 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = 452667681
+    [warn 2021/02/06 14:20:08.365 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = 651272813
+    [warn 2021/02/06 14:20:08.404 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = 1995204525
+    [warn 2021/02/06 14:20:08.443 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = -1945749946
+    [warn 2021/02/06 14:20:08.469 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = 1893650760
+    [warn 2021/02/06 14:20:08.509 PST <ServerConnection on port 40404 Thread 1> tid=0x42] hashCode = 664954774
     ```
     
 1. Run the `stopserver.ps1` script to gracefully shutdown the Geode cluster.
diff --git a/examples/utilities/PhotosKey.java b/examples/utilities/PhotosKey.java
index 35c9520..23ded8e 100644
--- a/examples/utilities/PhotosKey.java
+++ b/examples/utilities/PhotosKey.java
@@ -22,6 +22,7 @@ import org.apache.geode.*;
 import org.apache.geode.cache.Declarable;
 import org.apache.geode.DataSerializer;
 
+import org.apache.geode.logging.internal.log4j.api.LogService;
 
 public class PhotosKey implements DataSerializable {
   public List<String> people;
@@ -56,22 +57,12 @@ public class PhotosKey implements DataSerializable {
     DataSerializer.writeDate(this.rangeStart, out);
     DataSerializer.writeDate(this.rangeEnd, out);
   } 
-  
 
   public int hashCode() {
-	final int prime = 31;
-	int result = 1;
-	for( String s : people )
-	{
-		result = result * prime + s.hashCode();
-	}
-
-	result = result * prime + rangeStart.hashCode();
-	result = result * prime + rangeEnd.hashCode();
-	return result;
+	LogService.getLogger().warn("hashCode = {}", Objects.hash(people, rangeStart, rangeEnd));
+	return Objects.hash(people, rangeStart, rangeEnd);
   }
 
-
   public boolean equals(final Object obj)
   {
     if (this == obj)