You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by cl...@apache.org on 2014/07/02 21:52:45 UTC

svn commit: r1607465 - in /qpid/proton/trunk/proton-c/src: object/object.c tests/object.c

Author: cliffjansen
Date: Wed Jul  2 19:52:45 2014
New Revision: 1607465

URL: http://svn.apache.org/r1607465
Log:
PROTON-617: pn_map_del fix to restore lost linking information between map entries

Modified:
    qpid/proton/trunk/proton-c/src/object/object.c
    qpid/proton/trunk/proton-c/src/tests/object.c

Modified: qpid/proton/trunk/proton-c/src/object/object.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/object/object.c?rev=1607465&r1=1607464&r2=1607465&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/object/object.c (original)
+++ qpid/proton/trunk/proton-c/src/object/object.c Wed Jul  2 19:52:45 2014
@@ -631,17 +631,24 @@ void pn_map_del(pn_map_t *map, void *key
   pni_entry_t *prev = NULL;
   pni_entry_t *entry = pni_map_entry(map, key, &prev, false);
   if (entry) {
+    void *dref_key = (map->count_keys) ? entry->key : NULL;
+    void *dref_value = (map->count_values) ? entry->value : NULL;
     if (prev) {
       prev->next = entry->next;
       prev->state = entry->state;
+    } else if (entry->next) {
+      assert(entry->state == PNI_ENTRY_LINK);
+      pni_entry_t *next = &map->entries[entry->next];
+      *entry = *next;
+      entry = next;
     }
     entry->state = PNI_ENTRY_FREE;
     entry->next = 0;
-    if (map->count_keys) pn_decref2(entry->key, map);
     entry->key = NULL;
-    if (map->count_values) pn_decref2(entry->value, map);
     entry->value = NULL;
     map->size--;
+    if (dref_key) pn_decref2(dref_key, map);
+    if (dref_value) pn_decref2(dref_value, map);
   }
 }
 

Modified: qpid/proton/trunk/proton-c/src/tests/object.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/tests/object.c?rev=1607465&r1=1607464&r2=1607465&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/tests/object.c (original)
+++ qpid/proton/trunk/proton-c/src/tests/object.c Wed Jul  2 19:52:45 2014
@@ -499,6 +499,50 @@ static void test_hash(void)
   pn_decref(three);
 }
 
+
+// collider class: all objects have same hash, no two objects compare equal
+static intptr_t collider_compare(void *a, void *b)
+{
+  if (a == b) return 0;
+  return (a > b) ? 1 : -1;
+}
+
+static uintptr_t collider_hashcode(void *obj)
+{
+  return 23;
+}
+
+#define collider_initialize NULL
+#define collider_finalize NULL
+#define collider_inspect NULL
+
+static void test_map_links(void)
+{
+  const pn_class_t collider_clazz = PN_CLASS(collider);
+  void *keys[3];
+  for (int i = 0; i < 3; i++)
+    keys[i] = pn_new(0, &collider_clazz);
+
+  // test deleting a head, middle link, tail
+
+  for (int delete_idx=0; delete_idx < 3; delete_idx++) {
+    pn_map_t *map = pn_map(0, 0.75, 0);
+    // create a chain of entries that have same head (from identical key hashcode)
+    for (int i = 0; i < 3; i++) {
+      pn_map_put(map, keys[i], keys[i]);
+    }
+    pn_map_del(map, keys[delete_idx]);
+    for (int i = 0; i < 3; i++) {
+      void *value = (i == delete_idx) ? NULL : keys[i];
+      assert (pn_map_get(map, keys[i]) == value);
+    }
+    pn_free(map);
+  }
+  for (int i = 0; i < 3; i++)
+    pn_free(keys[i]);
+}
+
+
 static bool equals(const char *a, const char *b)
 {
   if (a == NULL && b == NULL) {
@@ -792,6 +836,7 @@ int main(int argc, char **argv)
   test_list_index();
 
   test_map();
+  test_map_links();
 
   test_hash();
 



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org