Commits

dizzyd committed fb0ed06

Move iterator out to keydir_handle; multiple independent readers can now fold (correctly) at the same time.

  • Participants
  • Parent commits 308e791

Comments (0)

Files changed (1)

File c_src/bitcask_nifs.c

 typedef struct
 {
     khash_t(entries)* entries;
-    khiter_t          iterator;
     khash_t(fstats)*  fstats;
     size_t        key_count;
     size_t        key_bytes;
 typedef struct
 {
     bitcask_keydir* keydir;
+    khiter_t        iterator;
     ErlNifTid       il_thread;  /* Iterator lock thread */
     ErlNifMutex*    il_signal_mutex;
     ErlNifCond*     il_signal;
     bitcask_keydir* keydir = enif_alloc_compat(env, sizeof(bitcask_keydir));
     memset(keydir, '\0', sizeof(bitcask_keydir));
     keydir->entries  = kh_init(entries);
-    keydir->iterator = kh_begin(keydir->entries);
     keydir->fstats   = kh_init(fstats);
 
     // Assign the keydir to our handle and hand it back
 
             // Initialize hash tables
             keydir->entries  = kh_init(entries);
-            keydir->iterator = kh_begin(keydir->entries);
             keydir->fstats   = kh_init(fstats);
 
             // Be sure to initialize the rwlock and set our refcount
             update_fstats(env, keydir, entry.file_id, 1, 1,
                           entry.total_sz, entry.total_sz);
 
-            // Reset the iterator to ensure that someone doesn't cause a crash
-            // by trying to interleave change operations with iterations
-            keydir->iterator = kh_begin(keydir->entries);
-
             RW_UNLOCK(keydir);
             return ATOM_OK;
         }
 
             kh_del(entries, keydir->entries, itr);
 
-            // Reset the iterator to ensure that someone doesn't cause a crash
-            // by trying to interleave change operations with iterations
-            keydir->iterator = kh_begin(keydir->entries);
-
             enif_free_compat(env, entry);
         }
 
         new_handle->keydir = new_keydir;
         memset(new_keydir, '\0', sizeof(bitcask_keydir));
         new_keydir->entries  = kh_init(entries);
-        new_keydir->iterator = kh_begin(new_keydir->entries);
         new_keydir->fstats   = kh_init(fstats);
 
         // Deep copy each item from the existing handle
 
     if (enif_get_resource(env, argv[0], bitcask_keydir_RESOURCE, (void**)&handle))
     {
-        bitcask_keydir* keydir = handle->keydir;
-
         // If a iterator thread is already active for this keydir, bail
         if (handle->il_thread)
         {
         }
 
         // Ready to go; initialize the iterator and unlock the signal mutex
-        keydir->iterator = kh_begin(keydir->entries);
+        handle->iterator = kh_begin(handle->keydir->entries);
         enif_mutex_unlock(handle->il_signal_mutex);
 
         return ATOM_OK;
             return enif_make_tuple2(env, ATOM_ERROR, ATOM_ITERATION_NOT_STARTED);
         }
 
-        while (keydir->iterator != kh_end(keydir->entries))
+        while (handle->iterator != kh_end(keydir->entries))
         {
-            if (kh_exist(keydir->entries, keydir->iterator))
+            if (kh_exist(keydir->entries, handle->iterator))
             {
-                bitcask_keydir_entry* entry = kh_key(keydir->entries, keydir->iterator);
+                bitcask_keydir_entry* entry = kh_key(keydir->entries, handle->iterator);
                 ErlNifBinary key;
 
                 // Alloc the binary and make sure it succeeded
                                                      enif_make_uint(env, entry->tstamp));
 
                 // Update the iterator to the next entry
-                (keydir->iterator)++;
+                (handle->iterator)++;
                 return curr;
             }
             else
             {
                 // No item in this slot; increment the iterator and keep looping
-                (keydir->iterator)++;
+                (handle->iterator)++;
             }
         }