subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1477533 - in /subversion/branches/fsfs-format7/subversion/libsvn_fs_fs: cached_data.c changes.c changes.h noderevs.c noderevs.h string_table.c string_table.h
Date Tue, 30 Apr 2013 10:27:40 GMT
Author: stefan2
Date: Tue Apr 30 10:27:39 2013
New Revision: 1477533

URL: http://svn.apache.org/r1477533
Log:
On the fsfs-format7 branch: Make access to elements in cached containers
O(1) again by providing partial getters for them.

* subversion/libsvn_fs_fs/string_table.h
  (svn_fs_fs__string_table_get_func): declare a getter that works for
                                      cache-serialized string tables
* subversion/libsvn_fs_fs/string_table.c
  (svn_fs_fs__string_table_get_func): implement it

* subversion/libsvn_fs_fs/changes.h
  (svn_fs_fs__changes_get_list_func): declare partial getter for change lists
* subversion/libsvn_fs_fs/changes.c
  (svn_fs_fs__changes_get_list_func): implement it

* subversion/libsvn_fs_fs/noderevs.h
  (svn_fs_fs__noderevs_get_func): declare partial getter for noderevs
* subversion/libsvn_fs_fs/noderevs.c
  (resolve_apr_array_header): new utiltiy
  (svn_fs_fs__noderevs_get_func): implement the partial getter

* subversion/libsvn_fs_fs/cached_data.c
  (get_node_revision_body,
   svn_fs_fs__get_changes): use partial getters instead of copying the
                            whole container

Modified:
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.h
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.h

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c?rev=1477533&r1=1477532&r2=1477533&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c Tue Apr 30 10:27:39
2013
@@ -333,7 +333,6 @@ get_node_revision_body(node_revision_t *
       if (   is_packed_rev(fs, rev_item->revision)
           && ffd->noderevs_container_cache)
         {
-          svn_fs_fs__noderevs_t *noderevs;
           apr_off_t offset;
           apr_uint32_t sub_item;
           SVN_ERR(svn_fs_fs__item_offset(&offset, &sub_item, fs,
@@ -342,14 +341,12 @@ get_node_revision_body(node_revision_t *
           key.revision = packed_base_rev(fs, rev_item->revision);
           key.second = offset;
 
-          SVN_ERR(svn_cache__get((void **)&noderevs, &is_cached,
-                                 ffd->noderevs_container_cache, &key, pool));
+          SVN_ERR(svn_cache__get_partial((void **)noderev_p, &is_cached,
+                                         ffd->noderevs_container_cache, &key, 
+                                         svn_fs_fs__noderevs_get_func,
+                                         &sub_item, pool));
           if (is_cached)
-            {
-              SVN_ERR(svn_fs_fs__noderevs_get(noderev_p, noderevs, sub_item,
-                                              pool));
-              return SVN_NO_ERROR;
-            }
+            return SVN_NO_ERROR;
         }
 
       key.revision = rev_item->revision;
@@ -2167,7 +2164,6 @@ svn_fs_fs__get_changes(apr_array_header_
 
   if (ffd->changes_container_cache && is_packed_rev(fs, rev))
     {
-      svn_fs_fs__changes_t *container;
       apr_off_t offset;
       apr_uint32_t sub_item;
       pair_cache_key_t key;
@@ -2177,11 +2173,10 @@ svn_fs_fs__get_changes(apr_array_header_
       key.revision = packed_base_rev(fs, rev);
       key.second = offset;
 
-      SVN_ERR(svn_cache__get((void **)&container, &found,
-                            ffd->changes_container_cache, &key, pool));
-      if (found)
-        SVN_ERR(svn_fs_fs__changes_get_list(changes, container, sub_item,
-                                            pool));
+      SVN_ERR(svn_cache__get_partial((void **)changes, &found,
+                                     ffd->changes_container_cache, &key,
+                                     svn_fs_fs__changes_get_list_func,
+                                     &sub_item, pool));
     }
   else if (ffd->changes_cache)
     {

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c?rev=1477533&r1=1477532&r2=1477533&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c Tue Apr 30 10:27:39
2013
@@ -474,3 +474,94 @@ svn_fs_fs__deserialize_changes_container
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_fs_fs__changes_get_list_func(void **out,
+                                 const void *data,
+                                 apr_size_t data_len,
+                                 void *baton,
+                                 apr_pool_t *pool)
+{
+  int first;
+  int last;
+  int i;
+  apr_array_header_t *list;
+
+  apr_uint32_t idx = *(apr_uint32_t *)baton;
+  const svn_fs_fs__changes_t *container = data;
+
+  /* resolve all the sub-container pointers we need */
+  const string_table_t *paths
+    = svn_temp_deserializer__ptr(container,
+                                 (const void *const *)&container->paths);
+  const apr_array_header_t *serialized_offsets
+    = svn_temp_deserializer__ptr(container,
+                                 (const void *const *)&container->offsets);
+  const apr_array_header_t *serialized_changes
+    = svn_temp_deserializer__ptr(container,
+                                 (const void *const *)&container->changes);
+  const int *offsets
+    = svn_temp_deserializer__ptr(serialized_offsets,
+                              (const void *const *)&serialized_offsets->elts);
+  const binary_change_t *changes
+    = svn_temp_deserializer__ptr(serialized_changes,
+                              (const void *const *)&serialized_changes->elts);
+
+  /* validate index */
+  if (idx + 1 >= (apr_size_t)serialized_offsets->nelts)
+    return svn_error_createf(SVN_ERR_FS_CONTAINER_INDEX, NULL,
+                             _("Changes list index %u exceeds container "
+                               "size %d"),
+                             (unsigned)idx, serialized_offsets->nelts - 1);
+
+  /* range of changes to return */
+  first = offsets[idx];
+  last = offsets[idx+1];
+
+  /* construct result */
+  list = apr_array_make(pool, last - first, sizeof(change_t*));
+
+  for (i = first; i < last; ++i)
+    {
+      const binary_change_t *binary_change = &changes[i];
+
+      /* convert BINARY_CHANGE into a standard FSFS change_t */
+      change_t *change = apr_pcalloc(pool, sizeof(*change));
+      change->path = svn_fs_fs__string_table_get_func(paths,
+                                                      binary_change->path,
+                                                      pool);
+
+      if (svn_fs_fs__id_txn_used(&binary_change->rev_id))
+        change->noderev_id
+          = (binary_change->flags & CHANGE_TXN_NODE)
+          ? svn_fs_fs__id_txn_create(&binary_change->node_id,
+                                     &binary_change->copy_id,
+                                     &binary_change->rev_id,
+                                     pool)
+          : svn_fs_fs__id_rev_create(&binary_change->node_id,
+                                     &binary_change->copy_id,
+                                     &binary_change->rev_id,
+                                     pool);
+
+      change->kind = (svn_fs_path_change_kind_t)
+        ((binary_change->flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT);
+      change->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0;
+      change->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0;
+      change->node_kind = (svn_node_kind_t)
+        ((binary_change->flags & CHANGE_NODE_MASK) >> CHANGE_NODE_SHIFT);
+
+      change->copyfrom_rev = binary_change->copyfrom_rev;
+      if (SVN_IS_VALID_REVNUM(binary_change->copyfrom_rev))
+        change->copyfrom_path 
+          = svn_fs_fs__string_table_get_func(paths,
+                                             binary_change->copyfrom_path,
+                                             pool);
+
+      /* add it to the result */
+      APR_ARRAY_PUSH(list, change_t*) = change;
+    }
+
+  *out = list;
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h?rev=1477533&r1=1477532&r2=1477533&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h Tue Apr 30 10:27:39
2013
@@ -114,4 +114,17 @@ svn_fs_fs__deserialize_changes_container
                                          apr_size_t data_len,
                                          apr_pool_t *pool);
 
+/* Implements svn_cache__partial_getter_func_t for svn_fs_fs__changes_t,
+ * setting *OUT to the change list (apr_array_header_t *) selected by
+ * the apr_uint32_t index passed in as *BATON.  This function is similar
+ * to svn_fs_fs__changes_get_list but operates on the cache serialized
+ * representation of the container.
+ */
+svn_error_t *
+svn_fs_fs__changes_get_list_func(void **out,
+                                 const void *data,
+                                 apr_size_t data_len,
+                                 void *baton,
+                                 apr_pool_t *pool);
+
 #endif
\ No newline at end of file

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.c?rev=1477533&r1=1477532&r2=1477533&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.c Tue Apr 30 10:27:39
2013
@@ -896,3 +896,114 @@ svn_fs_fs__deserialize_noderevs_containe
 
   return SVN_NO_ERROR;
 }
+
+/* Deserialize the cache serialized APR struct at *IN in BUFFER and write
+ * the result to OUT.  Note that this will only resolve the pointers and
+ * not the array elements themselves. */
+static void
+resolve_apr_array_header(apr_array_header_t *out,
+                         const void *buffer,
+                         apr_array_header_t * const *in)
+{
+  const apr_array_header_t *array
+    = svn_temp_deserializer__ptr(buffer, (const void *const *)in);
+  const char *elements
+    = svn_temp_deserializer__ptr(array, (const void *const *)&array->elts);
+
+  *out = *array;
+  out->elts = (char *)elements;
+  out->pool = NULL;
+}
+
+svn_error_t *
+svn_fs_fs__noderevs_get_func(void **out,
+                             const void *data,
+                             apr_size_t data_len,
+                             void *baton,
+                             apr_pool_t *pool)
+{
+  node_revision_t *noderev;
+  binary_noderev_t *binary_noderev;
+  
+  apr_array_header_t ids;
+  apr_array_header_t data_reps;
+  apr_array_header_t prop_reps;
+  apr_array_header_t noderevs;
+
+  apr_uint32_t idx = *(apr_uint32_t *)baton;
+  const svn_fs_fs__noderevs_t *container = data;
+
+  /* Resolve all container pointers */
+  const string_table_t *paths
+    = svn_temp_deserializer__ptr(container,
+                         (const void *const *)&container->paths);
+
+  resolve_apr_array_header(&ids, container, &container->ids);
+  resolve_apr_array_header(&data_reps, container, &container->data_reps);
+  resolve_apr_array_header(&prop_reps, container, &container->prop_reps);
+  resolve_apr_array_header(&noderevs, container, &container->noderevs);
+  
+  /* allocate result struct and fill it field by field */
+  noderev = apr_pcalloc(pool, sizeof(*noderev));
+  binary_noderev = &APR_ARRAY_IDX(&noderevs, idx, binary_noderev_t);
+  
+  noderev->kind = (svn_node_kind_t)(binary_noderev->flags & NODEREV_KIND_MASK);
+  SVN_ERR(get_id(&noderev->id, &ids, binary_noderev->id, pool));
+  SVN_ERR(get_id(&noderev->predecessor_id, &ids,
+                 binary_noderev->predecessor_id, pool));
+
+  if (binary_noderev->flags & NODEREV_HAS_COPYFROM)
+    {
+      noderev->copyfrom_path
+        = svn_fs_fs__string_table_get_func(paths,
+                                           binary_noderev->copyfrom_path,
+                                           pool);
+      noderev->copyroot_rev = binary_noderev->copyfrom_rev;
+    }
+  else
+    {
+      noderev->copyfrom_path = NULL;
+      noderev->copyfrom_rev = SVN_INVALID_REVNUM;
+    }
+
+  if (binary_noderev->flags & NODEREV_HAS_COPYROOT)
+    {
+      noderev->copyroot_path
+        = svn_fs_fs__string_table_get_func(paths,
+                                           binary_noderev->copyroot_path,
+                                           pool);
+      noderev->copyroot_rev = binary_noderev->copyroot_rev;
+    }
+  else
+    {
+      noderev->copyroot_path = NULL;
+      noderev->copyroot_rev = 0;
+    }
+
+  noderev->predecessor_count = binary_noderev->predecessor_count;
+
+  SVN_ERR(get_representation(&noderev->prop_rep, &prop_reps,
+                             binary_noderev->prop_rep, pool));
+  SVN_ERR(get_representation(&noderev->data_rep, &data_reps,
+                             binary_noderev->data_rep.representation, pool));
+  if (noderev->data_rep)
+    {
+      noderev->data_rep->uniquifier.txn_id
+        = binary_noderev->data_rep.uniquifier.txn_id;
+      noderev->data_rep->uniquifier.number
+        = binary_noderev->data_rep.uniquifier.number;
+    }
+
+  if (binary_noderev->flags & NODEREV_HAS_CPATH)
+    noderev->created_path
+      = svn_fs_fs__string_table_get_func(paths,
+                                         binary_noderev->created_path,
+                                         pool);
+
+  noderev->mergeinfo_count = binary_noderev->mergeinfo_count;
+
+  noderev->has_mergeinfo = (binary_noderev->flags & NODEREV_HAS_MINFO) ? 1 : 0;
+  *out = noderev;
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.h?rev=1477533&r1=1477532&r2=1477533&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.h (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/noderevs.h Tue Apr 30 10:27:39
2013
@@ -115,4 +115,16 @@ svn_fs_fs__deserialize_noderevs_containe
                                           apr_size_t data_len,
                                           apr_pool_t *pool);
 
+/* Implements svn_cache__partial_getter_func_t for svn_fs_fs__noderevs_t,
+ * setting *OUT to the node_revision_t selected by the apr_uint32_t index
+ * passed in as *BATON.  This function is similar to svn_fs_fs__noderevs_get
+ * but operates on the cache serialized representation of the container.
+ */
+svn_error_t *
+svn_fs_fs__noderevs_get_func(void **out,
+                             const void *data,
+                             apr_size_t data_len,
+                             void *baton,
+                             apr_pool_t *pool);
+
 #endif
\ No newline at end of file

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.c?rev=1477533&r1=1477532&r2=1477533&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.c Tue Apr 30 10:27:39
2013
@@ -811,3 +811,70 @@ svn_fs_fs__deserialize_string_table(void
                                (void **)&sub_table->long_strings[k].data);
     }
 }
+
+const char*
+svn_fs_fs__string_table_get_func(const string_table_t *table,
+                                 apr_size_t idx,
+                                 apr_pool_t *pool)
+{
+  apr_size_t table_number = idx >> TABLE_SHIFT;
+  apr_size_t sub_index = idx & STRING_INDEX_MASK;
+
+  if (table_number < table->size)
+    {
+      /* resolve TABLE->SUB_TABLES pointer and select sub-table */
+      string_sub_table_t *sub_tables
+        = (string_sub_table_t *)svn_temp_deserializer__ptr(table,
+                                   (const void *const *)&table->sub_tables);
+      string_sub_table_t *sub_table = sub_tables + table_number;
+
+      /* pick the right kind of string */
+      if (idx & LONG_STRING_MASK)
+        {
+          if (sub_index < sub_table->long_string_count)
+            {
+              /* resolve SUB_TABLE->LONG_STRINGS, select the string we want
+                 and resolve the pointer to its char data */
+              svn_string_t *long_strings
+                = (svn_string_t *)svn_temp_deserializer__ptr(sub_table,
+                             (const void *const *)&sub_table->long_strings);
+              const char *str_data
+                = (const char*)svn_temp_deserializer__ptr(long_strings,
+                        (const void *const *)&long_strings[sub_index].data);
+
+              /* return a copy of the char data */
+              return apr_pstrmemdup(pool,
+                                    str_data,
+                                    long_strings[sub_index].len);
+            }
+        }
+      else
+        {
+          if (sub_index < sub_table->short_string_count)
+            {
+              /* construct a copy of our sub-table struct with SHORT_STRINGS
+                 and DATA pointers resolved.  Leave all other pointers as
+                 they are.  This allows us to use the same code for string
+                 reconstruction here as in the non-serialized case. */
+              string_sub_table_t table_copy = *sub_table;
+              table_copy.data
+                = (const char *)svn_temp_deserializer__ptr(sub_tables,
+                                     (const void *const *)&sub_table->data);
+              table_copy.short_strings
+                = (string_header_t *)svn_temp_deserializer__ptr(sub_tables,
+                            (const void *const *)&sub_table->short_strings);
+
+              /* reconstruct the char data and return it */
+              string_header_t *header = table_copy.short_strings + sub_index;
+              apr_size_t len = header->head_length + header->tail_length + 1;
+              char *result = apr_palloc(pool, len);
+              
+              table_copy_string(result, len, &table_copy, header);
+
+              return result;
+            }
+        }
+    }
+
+  return "";
+}

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.h?rev=1477533&r1=1477532&r2=1477533&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.h (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/string_table.h Tue Apr 30 10:27:39
2013
@@ -130,6 +130,15 @@ void
 svn_fs_fs__deserialize_string_table(void *buffer,
                                     string_table_t **table);
 
+/* Extract string number INDEX from the cache serialized representation at
+ * TABLE and return a copy of it allocated in POOL.  Returns an empty string
+ * for invalid indexes.
+ */
+const char*
+svn_fs_fs__string_table_get_func(const string_table_t *table,
+                                 apr_size_t idx,
+                                 apr_pool_t *pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */



Mime
View raw message