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 */