Author: stefan2
Date: Sat Apr 16 18:52:36 2011
New Revision: 1094027

URL: http://svn.apache.org/viewvc?rev=1094027&view=rev
Log:
Refactor some of the directories serialization and lookup code in
preparation of a new update function.

* subversion/libsvn_fs_fs/temp_serializer.c
  (serialize_dir_entry, find_entry): factored out from functions below
  (serialize_dir, svn_fs_fs__extract_dir_entry): call new utility functions

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c

Modified: subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c?rev=1094027&r1=1094026&r2=1094027&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c Sat Apr 16 
18:52:36 2011
@@ -259,6 +259,25 @@ compare_dirent_id_names(const void *lhs,
                 (*(const svn_fs_dirent_t *const *)rhs)->name);
 }
 
+/* Utility function to serialize the *ENTRY_P into a the given
+ * serialization CONTEXT.
+ */
+static void
+serialize_dir_entry(svn_temp_serializer__context_t *context,
+                    svn_fs_dirent_t **entry_p)
+{
+  svn_fs_dirent_t *entry = *entry_p;
+
+  svn_temp_serializer__push(context,
+                            (const void * const *)entry_p,
+                             sizeof(svn_fs_dirent_t));
+
+  svn_fs_fs__id_serialize(context, &entry->id);
+  svn_temp_serializer__add_string(context, &entry->name);
+
+  svn_temp_serializer__pop(context);
+}
+
 /* Utility function to serialize the ENTRIES into a new serialization
  * context to be returned. Allocation will be made form POOL.
  */
@@ -301,17 +320,7 @@ serialize_dir(apr_hash_t *entries, apr_p
 
   /* serialize the individual entries and their sub-structures */
   for (i = 0; i < count; ++i)
-    {
-      svn_fs_dirent_t **entry = &hash_data.entries[i];
-      svn_temp_serializer__push(context,
-                                (const void * const *)entry,
-                                sizeof(svn_fs_dirent_t));
-
-      svn_fs_fs__id_serialize(context, &(*entry)->id);
-      svn_temp_serializer__add_string(context, &(*entry)->name);
-
-      svn_temp_serializer__pop(context);
-    }
+    serialize_dir_entry(context, &hash_data.entries[i]);
 
   return context;
 }
@@ -694,25 +703,20 @@ svn_fs_fs__get_sharded_offset(void **out
   return SVN_NO_ERROR;
 }
 
-/* Implements svn_cache__partial_getter_func_t for a directory contents hash.
- */
-svn_error_t *
-svn_fs_fs__extract_dir_entry(void **out,
-                             const char *data,
-                             apr_size_t data_len,
-                             void *baton,
-                             apr_pool_t *pool)
+/* Utility function that returns the lowest index of the first entry in
+ * *ENTRIES that points to a dir entry with a name equal or larger than NAME.
+ * If an exact match has been found, *FOUND will be set to TRUE. COUNT is
+ * the number of valid entries in ENTRIES.
+ */
+static apr_size_t
+find_entry(svn_fs_dirent_t **entries,
+           const char *name,
+           apr_size_t count,
+           svn_boolean_t *found)
 {
-  hash_data_t *hash_data = (hash_data_t *)data;
-  const char* name = baton;
-
-  /* resolve the reference to the entries array */
-  const svn_fs_dirent_t * const *entries =
-      svn_temp_deserializer__ptr(data, (const void **)&hash_data->entries);
-
   /* binary search for the desired entry by name */
   apr_size_t lower = 0;
-  apr_size_t upper = hash_data->count;
+  apr_size_t upper = count;
   apr_size_t middle;
 
   for (middle = upper / 2; lower < upper; middle = (upper + lower) / 2)
@@ -729,33 +733,69 @@ svn_fs_fs__extract_dir_entry(void **out,
         upper = middle;
     }
 
+  /* check whether we actually found a match */
+  *found = FALSE;
+  if (lower < count)
+    {
+      const svn_fs_dirent_t *entry =
+          svn_temp_deserializer__ptr(entries, (const void **)&entries[lower]);
+      const char* entry_name =
+          svn_temp_deserializer__ptr(entry, (const void **)&entry->name);
+
+      if (strcmp(entry_name, name) == 0)
+        *found = TRUE;
+    }
+
+  return lower;
+}
+
+/* Implements svn_cache__partial_getter_func_t for a directory contents hash.
+ */
+svn_error_t *
+svn_fs_fs__extract_dir_entry(void **out,
+                             const char *data,
+                             apr_size_t data_len,
+                             void *baton,
+                             apr_pool_t *pool)
+{
+  hash_data_t *hash_data = (hash_data_t *)data;
+  const char* name = baton;
+  svn_boolean_t found;
+
+  /* resolve the reference to the entries array */
+  const svn_fs_dirent_t * const *entries =
+    svn_temp_deserializer__ptr(data, (const void **)&hash_data->entries);
+
+  /* binary search for the desired entry by name */
+  apr_size_t index = find_entry((svn_fs_dirent_t **)entries,
+                                name,
+                                hash_data->count,
+                                &found);
+
   /* de-serialize that entry or return NULL, if no match has been found */
   *out = NULL;
-  if (lower < hash_data->count)
+  if (found)
     {
       const svn_fs_dirent_t *source =
-          svn_temp_deserializer__ptr(entries, (const void **)&entries[lower]);
+          svn_temp_deserializer__ptr(entries, (const void **)&entries[index]);
 
       /* Entries have been serialized one-by-one, each time including all
        * nestes structures and strings. Therefore, they occupy a single
        * block of memory whose end-offset is either the beginning of the
        * next entry or the end of the buffer
        */
-      apr_size_t end_offset = lower + 1 < hash_data->count
-                            ? ((apr_size_t*)entries)[lower+1]
+      apr_size_t end_offset = index + 1 < hash_data->count
+                            ? ((apr_size_t*)entries)[index+1]
                             : data_len;
-      apr_size_t size = end_offset - ((apr_size_t*)entries)[lower];
+      apr_size_t size = end_offset - ((apr_size_t*)entries)[index];
 
       /* copy & deserialize the entry */
       svn_fs_dirent_t *new_entry = apr_palloc(pool, size);
       memcpy(new_entry, source, size);
 
       svn_temp_deserializer__resolve(new_entry, (void **)&new_entry->name);
-      if (strcmp(new_entry->name, name) == 0)
-        {
-          svn_fs_fs__id_deserialize(new_entry, (svn_fs_id_t **)&new_entry->id);
-          *(svn_fs_dirent_t **)out = new_entry;
-        }
+      svn_fs_fs__id_deserialize(new_entry, (svn_fs_id_t **)&new_entry->id);
+      *(svn_fs_dirent_t **)out = new_entry;
     }
 
   return SVN_NO_ERROR;


Reply via email to