subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1416996 [13/13] - in /subversion/branches/wc-collate-path: ./ build/ build/ac-macros/ build/generator/ contrib/client-side/svnmerge/ contrib/server-side/svncutter/ notes/ subversion/bindings/cxxhl/ subversion/bindings/javahl/native/ subver...
Date Tue, 04 Dec 2012 15:35:57 GMT
Modified: subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-list-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-list-cmd.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-list-cmd.c (original)
+++ subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-list-cmd.c Tue Dec  4 15:35:13 2012
@@ -48,7 +48,7 @@ struct print_baton {
   svn_client_ctx_t *ctx;
 };
 
-/* This implements the svn_client_list_func_t API, printing a single
+/* This implements the svn_client_list_func2_t API, printing a single
    directory entry in text format. */
 static svn_error_t *
 print_dirent(void *baton,
@@ -56,6 +56,8 @@ print_dirent(void *baton,
              const svn_dirent_t *dirent,
              const svn_lock_t *lock,
              const char *abs_path,
+             const char *external_parent_url,
+             const char *external_target,
              apr_pool_t *pool)
 {
   struct print_baton *pb = baton;
@@ -123,11 +125,12 @@ svn_cl__null_list(apr_getopt_t *os,
       SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                  subpool));
 
-      err = svn_client_list2(truepath, &peg_revision,
+      err = svn_client_list3(truepath, &peg_revision,
                              &(opt_state->start_revision),
                              opt_state->depth,
                              dirent_fields,
                              opt_state->verbose,
+                             FALSE, /* include externals */
                              print_dirent,
                              &pb, ctx, subpool);
 

Modified: subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-log-cmd.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-log-cmd.c (original)
+++ subversion/branches/wc-collate-path/tools/client-side/svn-bench/null-log-cmd.c Tue Dec  4 15:35:13 2012
@@ -134,7 +134,7 @@ svn_cl__null_log(apr_getopt_t *os,
   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   apr_array_header_t *targets;
-  struct log_receiver_baton lb = { ctx };
+  struct log_receiver_baton lb;
   const char *target;
   int i;
   apr_array_header_t *revprops;
@@ -194,6 +194,7 @@ svn_cl__null_log(apr_getopt_t *os,
         }
     }
 
+  lb.ctx = ctx;
   lb.quiet = opt_state->quiet;
 
   revprops = apr_array_make(pool, 3, sizeof(char *));

Propchange: subversion/branches/wc-collate-path/tools/server-side/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Dec  4 15:35:13 2012
@@ -3,3 +3,4 @@ svn-populate-node-origins-index
 svnauthz-validate
 svn-rep-sharing-stats
 fsfs-reorg
+fsfs-stats

Modified: subversion/branches/wc-collate-path/tools/server-side/fsfs-reorg.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/tools/server-side/fsfs-reorg.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/tools/server-side/fsfs-reorg.c (original)
+++ subversion/branches/wc-collate-path/tools/server-side/fsfs-reorg.c Tue Dec  4 15:35:13 2012
@@ -47,165 +47,376 @@
 
 #define ERROR_TAG "diff: "
 
+/* forward declarations */
 typedef struct noderev_t noderev_t;
 typedef struct revision_info_t revision_info_t;
 
+/* A FSFS rev file is sequence of fragments and unused space (the latter
+ * only being inserted by this tool and not during ordinary SVN operation).
+ * 
+ * This type defines the type of any fragment.
+ *
+ * Please note that the classification as "property", "dir" or "file"
+ * fragments is only to be used while determining the future placement
+ * of a representation.  If the rep is shared, the same rep may be used
+ * as *any* of the 3 kinds.
+ */
 enum fragment_kind_t
 {
+  /* the 2 number line containing changes and root node offsets */
   header_fragment,
+
+  /* list of all changes in a revision */
   changes_fragment,
-  noderep_fragment,
+
+  /* (the textual representation of) a noderev */
+  noderev_fragment,
+
+  /* a property rep (including PLAIN / DELTA header) */
   property_fragment,
+
+  /* a directory rep (including PLAIN / DELTA header) */
   dir_fragment,
+
+  /* a file rep (including PLAIN / DELTA header) */
   file_fragment
 };
 
+/* A fragment.  This is used to represent the final ordering, i.e. there
+ * will be an array containing elements of this type that basically put
+ * a fragment at some location in the target file.
+ */
 typedef struct fragment_t
 {
+  /* position in the target file */
   apr_size_t position;
-  void *data;
+
+  /* kind of fragment */
   enum fragment_kind_t kind;
+
+  /* pointer to the  fragment struct; type depends on KIND */
+  void *data;
 } fragment_t;
 
+/* Location info for a single revision.
+ */
 typedef struct revision_location_t
 {
+  /* pack file offset (manifest value), 0 for non-packed files */
   apr_size_t offset;
+  
+  /* offset of the changes list relative to OFFSET */
   apr_size_t changes;
+
+  /* length of the changes list on bytes */
   apr_size_t changes_len;
+
+  /* first offset behind the revision data in the pack file (file length
+   * for non-packed revs) */
   apr_size_t end;  
 } revision_location_t;
 
+/* Absolute position and size of some item.
+ */
 typedef struct location_t
 {
+  /* absolute offset in the file */
   apr_size_t offset;
+
+  /* item length in bytes */
   apr_size_t size;
 } location_t;
 
+/* A parsed directory entry. Note that instances of this struct may be
+ * shared between different DIRECTORY_T containers.
+ */
 typedef struct direntry_t
 {
+  /* (local) entry / path name */
   const char *name;
+
+  /* strlen (name) */
   apr_size_t name_len;
+
+  /* node rev providing ID and representation(s) */
   noderev_t *node;
 } direntry_t;
 
+/* Representation of a parsed directory content.
+ */
 typedef struct directory_t
 {
+  /* array of pointers to DIRENTRY_T */
   apr_array_header_t *entries;
+
+  /* MD5 of the textual representation. Will be set lazily as a side-effect
+   * of determining the length of this dir's textual representation. */
   unsigned char target_md5[16];
+
+  /* (expanded) length of the textual representation.
+   * Determined lazily during the write process. */
   apr_size_t size;
 } directory_t;
 
+/* A representation fragment.
+ */
 typedef struct representation_t
 {
+  /* location in the source file */
   location_t original;
+
+  /* location in the reordered target file */
   location_t target;
+
+  /* length of the PLAIN / DELTA line in the source file in bytes */
   apr_size_t header_size;
+
+  /* deltification base, or NULL if there is none */
   struct representation_t *delta_base;
+
+  /* revision that contains this representation
+   * (may be referenced by other revisions, though) */
   revision_info_t *revision;
+
+  /* representation content parsed as a directory. This will be NULL, if
+   * *no* directory noderev uses this representation. */
   directory_t *dir;
+
+  /* the source content has a PLAIN header, so we may simply copy the
+   * source content into the target */
   svn_boolean_t is_plain;
+
+  /* coloring flag used in the reordering algorithm to keep track of
+   * representations that still need to be placed. */
   svn_boolean_t covered;
 } representation_t;
 
+/* A node rev.
+ */
 struct noderev_t
 {
+  /* location within the source file */
   location_t original;
+
+  /* location within the reorganized target file. */
   location_t target;
+
+  /* predecessor node, or NULL if there is none */
   noderev_t *predecessor;
+
+  /* content representation; may be NULL if there is none */
   representation_t *text;
+
+  /* properties representation; may be NULL if there is none */
   representation_t *props;
+
+  /* revision that this noderev belongs to */
   revision_info_t *revision;
+
+  /* coloring flag used in the reordering algorithm to keep track of
+   * representations that still need to be placed. */
   svn_boolean_t covered;
 };
 
+/* Represents a single revision.
+ * There will be only one instance per revision. */
 struct revision_info_t
 {
+  /* number of this revision */
   svn_revnum_t revision;
+
+  /* position in the source file */
   revision_location_t original;
+
+  /* position in the reorganized target file */
   revision_location_t target;
+
+  /* noderev of the root directory */
   noderev_t *root_noderev;
+
+  /* all noderevs_t of this revision (ordered by source file offset),
+   * i.e. those that point back to this struct */
   apr_array_header_t *node_revs;
+  
+  /* all representation_t of this revision (ordered by source file offset),
+   * i.e. those that point back to this struct */
   apr_array_header_t *representations;
 };
 
+/* Represents a packed revision file.
+ */
 typedef struct revision_pack_t
 {
+  /* first revision in the pack file */
   svn_revnum_t base;
+
+  /* revision_info_t* of all revisions in the pack file; in revision order. */
   apr_array_header_t *info;
+
+  /* list of fragments to place in the target pack file; in target order. */
   apr_array_header_t *fragments;
+
+  /* source pack file length */
   apr_size_t filesize;
+
+  /* temporary value. Equal to the number of bytes in the target pack file
+   * already allocated to fragments. */
   apr_size_t target_offset;
 } revision_pack_t;
 
+/* Cache for revision source content.  All content is stored in DATA and
+ * the HASH maps revision number to an svn_string_t instance whose data
+ * member points into DATA.
+ * 
+ * Once TOTAL_SIZE exceeds LIMIT, all content will be discarded.  Similarly,
+ * the hash gets cleared every 10000 insertions to keep the HASH_POOL
+ * memory usage in check.
+ */
 typedef struct content_cache_t
 {
-  apr_pool_t *pool;
+  /* pool used for HASH */
   apr_pool_t *hash_pool;
 
+  /* svn_revnum_t -> svn_string_t.
+   * The strings become (potentially) invalid when adding new cache entries. */
   apr_hash_t *hash;
 
+  /* data buffer. the first TOTAL_SIZE bytes are actually being used. */
   char *data;
+
+  /* DATA capacity */
   apr_size_t limit;
 
+  /* number of bytes used in DATA */
   apr_size_t total_size;
+
+  /* number of insertions since the last hash cleanup */
   apr_size_t insert_count;
 } content_cache_t;
 
+/* A cached directory. In contrast to directory_t, this stored the data as
+ * the plain hash that the normal FSFS will use to serialize & diff dirs.
+ */
 typedef struct dir_cache_entry_t
 {
+  /* revision containing the representation */
   svn_revnum_t revision;
+
+  /* offset of the representation within that revision */
   apr_size_t offset;
-  
+
+  /* key-value representation of the directory entries */
   apr_hash_t *hash;
 } dir_cache_entry_t;
 
+/* Directory cache. (revision, offset) will be mapped directly into the
+ * ENTRIES array of ENTRY_COUNT buckets (many entries will be NULL).
+ * Two alternating pools will be used to allocate dir content.
+ * 
+ * If the INSERT_COUNT exceeds a given limit, the pools get exchanged and
+ * the older of the two will be cleared. This is to keep dir objects valid
+ * for at least one insertion.
+ */
 typedef struct dir_cache_t
 {
+  /* fixed-size array of ENTRY_COUNT elements */
   dir_cache_entry_t *entries;
 
+  /* currently used for entry allocations */
   apr_pool_t *pool1;
+  
+  /* previously used for entry allocations */
   apr_pool_t *pool2;
+
+  /* size of ENTRIES in elements */
   apr_size_t entry_count;
+
+  /* number of directory elements added. I.e. usually >> #cached dirs */
   apr_size_t insert_count;
 } dir_cache_t;
 
+/* A cached, undeltified txdelta window.
+ */
 typedef struct window_cache_entry_t
 {
+  /* revision containing the window */
   svn_revnum_t revision;
+
+  /* offset of the deltified window within that revision */
   apr_size_t offset;
 
+  /* window content */
   svn_stringbuf_t *window;
 } window_cache_entry_t;
 
+/* Cache for undeltified txdelta windows. (revision, offset) will be mapped
+ * directly into the ENTRIES array of INSERT_COUNT buckets (most entries
+ * will be NULL).
+ *
+ * The cache will be cleared when USED exceeds CAPACITY.
+ */
 typedef struct window_cache_t
 {
+  /* fixed-size array of ENTRY_COUNT elements */
   window_cache_entry_t *entries;
 
+  /* used to allocate windows */
   apr_pool_t *pool;
+
+  /* size of ENTRIES in elements */
   apr_size_t entry_count;
+
+  /* maximum combined size of all cached windows */
   apr_size_t capacity;
+
+  /* current combined size of all cached windows */
   apr_size_t used;
 } window_cache_t;
 
+/* Root data structure containing all information about a given repository.
+ */
 typedef struct fs_fs_t
 {
+  /* repository to reorg */
   const char *path;
+
+  /* revision to start at (must be 0, ATM) */
   svn_revnum_t start_revision;
+
+  /* FSFS format number */
   int format;
 
+  /* highest revision number in the repo */
   svn_revnum_t max_revision;
+
+  /* first non-packed revision */
   svn_revnum_t min_unpacked_rev;
+
+  /* sharing size*/
   int max_files_per_dir;
 
+  /* all revisions */
   apr_array_header_t *revisions;
+
+  /* all packed files */
   apr_array_header_t *packs;
 
+  /* empty representation.
+   * Used as a dummy base for DELTA reps without base. */
   representation_t *null_base;
+
+  /* revision content cache */
   content_cache_t *cache;
+
+  /* directory hash cache */
   dir_cache_t *dir_cache;
+
+  /* undeltified txdelta window cache */
   window_cache_t *window_cache;
 } fs_fs_t;
 
+/* Return the rev pack folder for revision REV in FS.
+ */
 static const char *
 get_pack_folder(fs_fs_t *fs,
                 svn_revnum_t rev,
@@ -215,6 +426,8 @@ get_pack_folder(fs_fs_t *fs,
                       fs->path, rev / fs->max_files_per_dir);
 }
 
+/* Return the path of the file containing revision REV in FS.
+ */
 static const char *
 rev_or_pack_file_name(fs_fs_t *fs,
                       svn_revnum_t rev,
@@ -226,6 +439,8 @@ rev_or_pack_file_name(fs_fs_t *fs,
                           rev / fs->max_files_per_dir, rev);
 }
 
+/* Open the file containing revision REV in FS and return it in *FILE.
+ */
 static svn_error_t *
 open_rev_or_pack_file(apr_file_t **file,
                       fs_fs_t *fs,
@@ -239,6 +454,9 @@ open_rev_or_pack_file(apr_file_t **file,
                           pool);
 }
 
+/* Read the whole content of the file containing REV in FS and return that
+ * in *CONTENT.
+ */
 static svn_error_t *
 read_rev_or_pack_file(svn_stringbuf_t **content,
                       fs_fs_t *fs,
@@ -250,13 +468,15 @@ read_rev_or_pack_file(svn_stringbuf_t **
                                   pool);
 }
 
+/* Return a new content cache with the given size LIMIT.  Use POOL for
+ * all cache-related allocations.
+ */
 static content_cache_t *
 create_content_cache(apr_pool_t *pool,
                      apr_size_t limit)
 {
   content_cache_t *result = apr_pcalloc(pool, sizeof(*result));
 
-  result->pool = pool;
   result->hash_pool = svn_pool_create(pool);
   result->hash = svn_hash__make(result->hash_pool);
   result->limit = limit;
@@ -267,6 +487,9 @@ create_content_cache(apr_pool_t *pool,
   return result;
 }
 
+/* Return the content of revision REVISION from CACHE. Return NULL upon a
+ * cache miss. This is a cache-internal function.
+ */
 static svn_string_t *
 get_cached_content(content_cache_t *cache,
                    svn_revnum_t revision)
@@ -274,6 +497,9 @@ get_cached_content(content_cache_t *cach
   return apr_hash_get(cache->hash, &revision, sizeof(revision));
 }
 
+/* Take the content in DATA and store it under REVISION in CACHE.
+ * This is a cache-internal function.
+ */
 static void
 set_cached_content(content_cache_t *cache,
                    svn_revnum_t revision,
@@ -281,11 +507,14 @@ set_cached_content(content_cache_t *cach
 {
   svn_string_t *content;
   svn_revnum_t *key;
-  
+
+  /* double insertion? -> broken cache logic */
   assert(get_cached_content(cache, revision) == NULL);
 
+  /* purge the cache upon overflow */
   if (cache->total_size + data->len > cache->limit)
     {
+      /* the hash pool grows slowly over time; clear it once in a while */
       if (cache->insert_count > 10000)
         {
           svn_pool_clear(cache->hash_pool);
@@ -296,8 +525,13 @@ set_cached_content(content_cache_t *cach
         cache->hash = svn_hash__make(cache->hash_pool);
 
       cache->total_size = 0;
+
+      /* buffer overflow / revision too large */
+      if (data->len > cache->limit)
+        SVN_ERR_MALFUNCTION_NO_RETURN();
     }
 
+  /* copy data to cache and update he index (hash) */
   content = apr_palloc(cache->hash_pool, sizeof(*content));
   content->data = cache->data + cache->total_size;
   content->len = data->len;
@@ -312,6 +546,9 @@ set_cached_content(content_cache_t *cach
   ++cache->insert_count;
 }
 
+/* Get the file content of revision REVISION in FS and return it in *DATA.
+ * Use SCRATCH_POOL for temporary allocations.
+ */
 static svn_error_t *
 get_content(svn_string_t **data,
             fs_fs_t *fs,
@@ -322,7 +559,8 @@ get_content(svn_string_t **data,
   revision_info_t *revision_info;
   svn_stringbuf_t *temp;
   apr_off_t temp_offset;
-  
+
+  /* try getting the data from our cache */
   svn_string_t *result = get_cached_content(fs->cache, revision);
   if (result)
     {
@@ -330,6 +568,7 @@ get_content(svn_string_t **data,
       return SVN_NO_ERROR;
     }
 
+  /* not in cache. Is the revision valid at all? */
   if (revision - fs->start_revision > fs->revisions->nelts)
     return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
                              _("Unknown revision %ld"), revision);
@@ -337,6 +576,8 @@ get_content(svn_string_t **data,
                                 revision - fs->start_revision,
                                 revision_info_t*);
 
+  /* read the revision content. Assume that the file has *not* been
+   * reorg'ed, yet, i.e. all data is in one place. */
   temp = svn_stringbuf_create_ensure(  revision_info->original.end
                                      - revision_info->original.offset,
                                      scratch_pool);
@@ -350,6 +591,7 @@ get_content(svn_string_t **data,
   revision_info->original.offset = (apr_size_t)temp_offset;
   SVN_ERR(svn_io_file_read(file, temp->data, &temp->len, scratch_pool));
 
+  /* cache the result and return it */
   set_cached_content(fs->cache, revision,
                      svn_stringbuf__morph_into_string(temp));
   *data = get_cached_content(fs->cache, revision);
@@ -357,6 +599,9 @@ get_content(svn_string_t **data,
   return SVN_NO_ERROR;
 }
 
+/* Return a new directory cache with ENTRY_COUNT buckets in its index.
+ * Use POOL for all cache-related allocations.
+ */
 static dir_cache_t *
 create_dir_cache(apr_pool_t *pool,
                  apr_size_t entry_count)
@@ -372,6 +617,9 @@ create_dir_cache(apr_pool_t *pool,
   return result;
 }
 
+/* Return the position within FS' dir cache ENTRIES index for the given
+ * (REVISION, OFFSET) pair. This is a cache-internal function.
+ */
 static apr_size_t
 get_dir_cache_index(fs_fs_t *fs,
                     svn_revnum_t revision,
@@ -380,12 +628,18 @@ get_dir_cache_index(fs_fs_t *fs,
   return (revision + offset * 0xd1f3da69) % fs->dir_cache->entry_count;
 }
 
+/* Return the currently active pool of FS' dir cache. Note that it may be
+ * cleared after *2* insertions.
+ */
 static apr_pool_t *
 get_cached_dir_pool(fs_fs_t *fs)
 {
   return fs->dir_cache->pool1;
 }
 
+/* Return the cached directory content stored in REPRESENTATION within FS.
+ * If that has not been found in cache, return NULL.
+ */
 static apr_hash_t *
 get_cached_dir(fs_fs_t *fs,
                representation_t *representation)
@@ -401,17 +655,21 @@ get_cached_dir(fs_fs_t *fs,
     : NULL;
 }
 
+/* Cache the directory HASH for  REPRESENTATION within FS.
+ */
 static void
 set_cached_dir(fs_fs_t *fs,
                representation_t *representation,
                apr_hash_t *hash)
 {
+  /* select the entry to use */
   svn_revnum_t revision = representation->revision->revision;
   apr_size_t offset = representation->original.offset;
 
   apr_size_t i = get_dir_cache_index(fs, revision, offset);
   dir_cache_entry_t *entry = &fs->dir_cache->entries[i];
 
+  /* clean the cache and rotate pools at regular intervals */
   fs->dir_cache->insert_count += apr_hash_count(hash);
   if (fs->dir_cache->insert_count >= fs->dir_cache->entry_count * 100)
     {
@@ -428,11 +686,16 @@ set_cached_dir(fs_fs_t *fs,
       fs->dir_cache->pool1 = pool;
     }
 
+  /* write data to cache */
   entry->hash = hash;
   entry->offset = offset;
   entry->revision = revision;
 }
 
+/* Return a new txdelta window cache with ENTRY_COUNT buckets in its index
+ * and a the total CAPACITY given in bytes.
+ * Use POOL for all cache-related allocations.
+ */
 static window_cache_t *
 create_window_cache(apr_pool_t *pool,
                     apr_size_t entry_count,
@@ -449,6 +712,9 @@ create_window_cache(apr_pool_t *pool,
   return result;
 }
 
+/* Return the position within FS' window cache ENTRIES index for the given
+ * (REVISION, OFFSET) pair. This is a cache-internal function.
+ */
 static apr_size_t
 get_window_cache_index(fs_fs_t *fs,
                        svn_revnum_t revision,
@@ -457,6 +723,9 @@ get_window_cache_index(fs_fs_t *fs,
   return (revision + offset * 0xd1f3da69) % fs->window_cache->entry_count;
 }
 
+/* Return the cached txdelta window stored in REPRESENTATION within FS.
+ * If that has not been found in cache, return NULL.
+ */
 static svn_stringbuf_t *
 get_cached_window(fs_fs_t *fs,
                   representation_t *representation,
@@ -473,17 +742,21 @@ get_cached_window(fs_fs_t *fs,
     : NULL;
 }
 
+/* Cache the undeltified txdelta WINDOW for REPRESENTATION within FS.
+ */
 static void
 set_cached_window(fs_fs_t *fs,
                   representation_t *representation,
                   svn_stringbuf_t *window)
 {
+  /* select entry */
   svn_revnum_t revision = representation->revision->revision;
   apr_size_t offset = representation->original.offset;
 
   apr_size_t i = get_window_cache_index(fs, revision, offset);
   window_cache_entry_t *entry = &fs->window_cache->entries[i];
 
+  /* if the capacity is exceeded, clear the cache */
   fs->window_cache->used += window->len;
   if (fs->window_cache->used >= fs->window_cache->capacity)
     {
@@ -494,13 +767,15 @@ set_cached_window(fs_fs_t *fs,
       fs->window_cache->used = window->len;
     }
 
+  /* set the entry to a copy of the window data */
   entry->window = svn_stringbuf_dup(window, fs->window_cache->pool);
   entry->offset = offset;
   entry->revision = revision;
 }
 
-/* Given REV in FS, set *REV_OFFSET to REV's offset in the packed file.
-   Use POOL for temporary allocations. */
+/* Given rev pack PATH in FS, read the manifest file and return the offsets
+ * in *MANIFEST. Use POOL for allocations.
+ */
 static svn_error_t *
 read_manifest(apr_array_header_t **manifest,
               fs_fs_t *fs,
@@ -543,6 +818,10 @@ read_manifest(apr_array_header_t **manif
   return svn_stream_close(manifest_stream);
 }
 
+/* Read header information for the revision stored in FILE_CONTENT at
+ * offsets START or END.  Return the offsets within FILE_CONTENT for the
+ * *ROOT_NODEREV, the list of *CHANGES and its len in *CHANGES_LEN.
+ * Use POOL for temporary allocations. */
 static svn_error_t *
 read_revision_header(apr_size_t *changes,
                      apr_size_t *changes_len,
@@ -554,7 +833,7 @@ read_revision_header(apr_size_t *changes
 {
   char buf[64];
   const char *line;
-  const char *space;
+  char *space;
   apr_uint64_t val;
   apr_size_t len;
   
@@ -583,8 +862,10 @@ read_revision_header(apr_size_t *changes
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Final line in revision file missing space"));
 
-  *(char *)space = 0;
-  
+  /* terminate the header line */
+  *space = 0;
+
+  /* extract information */
   SVN_ERR(svn_cstring_strtoui64(&val, line+1, 0, APR_SIZE_MAX, 10));
   *root_noderev = (apr_size_t)val;
   SVN_ERR(svn_cstring_strtoui64(&val, space+1, 0, APR_SIZE_MAX, 10));
@@ -594,6 +875,10 @@ read_revision_header(apr_size_t *changes
   return SVN_NO_ERROR;
 }
 
+/* Read the FSFS format number and sharding size from the format file at
+ * PATH and return it in *PFORMAT and *MAX_FILES_PER_DIR respectively.
+ * Use POOL for temporary allocations.
+ */
 static svn_error_t *
 read_format(int *pformat, int *max_files_per_dir,
             const char *path, apr_pool_t *pool)
@@ -603,6 +888,7 @@ read_format(int *pformat, int *max_files
   char buf[80];
   apr_size_t len;
 
+  /* open format file and read the first line */
   err = svn_io_file_open(&file, path, APR_READ | APR_BUFFERED,
                          APR_OS_DEFAULT, pool);
   if (err && APR_STATUS_IS_ENOENT(err->apr_err))
@@ -677,21 +963,27 @@ read_format(int *pformat, int *max_files
   return svn_io_file_close(file, pool);
 }
 
+/* Read the content of the file at PATH and return it in *RESULT.
+ * Use POOL for temporary allocations.
+ */
 static svn_error_t *
 read_number(svn_revnum_t *result, const char *path, apr_pool_t *pool)
 {
   svn_stringbuf_t *content;
-  apr_int64_t number;
+  apr_uint64_t number;
   
   SVN_ERR(svn_stringbuf_from_file2(&content, path, pool));
 
   content->data[content->len-1] = 0;
-  SVN_ERR(svn_cstring_atoi64(&number, content->data));
+  SVN_ERR(svn_cstring_strtoui64(&number, content->data, 0, LONG_MAX, 10));
   *result = (svn_revnum_t)number;
 
   return SVN_NO_ERROR;
 }
 
+/* Create *FS for the repository at PATH and read the format and size info.
+ * Use POOL for temporary allocations.
+ */
 static svn_error_t *
 fs_open(fs_fs_t **fs, const char *path, apr_pool_t *pool)
 {
@@ -706,7 +998,8 @@ fs_open(fs_fs_t **fs, const char *path, 
                       pool));
   if (((*fs)->format != 4) && ((*fs)->format != 6))
     return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL, NULL);
-    
+
+  /* read size (HEAD) info */
   SVN_ERR(read_number(&(*fs)->min_unpacked_rev,
                       svn_dirent_join(path, "db/min-unpacked-rev", pool),
                       pool));
@@ -715,17 +1008,23 @@ fs_open(fs_fs_t **fs, const char *path, 
                      pool);
 }
 
+/* Utility function that returns true if STRING->DATA matches KEY.
+ */
 static svn_boolean_t
 key_matches(svn_string_t *string, const char *key)
 {
   return strcmp(string->data, key) == 0;
 }
 
+/* Comparator used for binary search comparing the absolute file offset
+ * of a noderev to some other offset. DATA is a *noderev_t, KEY is pointer
+ * to an apr_size_t.
+ */
 static int
 compare_noderev_offsets(const void *data, const void *key)
 {
-  apr_ssize_t diff = (*(const noderev_t **)data)->original.offset
-                   - *(const apr_size_t *)key;
+  apr_ssize_t diff = (*(const noderev_t *const *)data)->original.offset
+                     - *(const apr_size_t *)key;
 
   /* sizeof(int) may be < sizeof(ssize_t) */
   if (diff < 0)
@@ -733,6 +1032,13 @@ compare_noderev_offsets(const void *data
   return diff > 0 ? 1 : 0;
 }
 
+/* Get the revision and offset info from the node ID with FS. Return the
+ * data as *REVISION_INFO and *OFFSET, respectively.
+ *
+ * Note that we assume that the revision_info_t object ID's revision has
+ * already been created. That can be guaranteed for standard FSFS pack
+ * files as IDs never point to future revisions.
+ */
 static svn_error_t *
 parse_revnode_pos(revision_info_t **revision_info,
                   apr_size_t *offset,
@@ -742,6 +1048,7 @@ parse_revnode_pos(revision_info_t **revi
   int revision;
   apr_uint64_t temp;
 
+  /* split the ID and verify the format */
   const char *revision_pos = strrchr(id->data, 'r');
   char *offset_pos = (char *)strchr(id->data, '/');
 
@@ -749,12 +1056,14 @@ parse_revnode_pos(revision_info_t **revi
     return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
                              _("Invalid node id '%s'"), id->data);
 
+  /* extract the numbers (temp. modifying the ID)*/
   *offset_pos = 0;
   SVN_ERR(svn_cstring_atoi(&revision, revision_pos + 1));
   SVN_ERR(svn_cstring_strtoui64(&temp, offset_pos + 1, 0, APR_SIZE_MAX, 10));
   *offset = (apr_size_t)temp;
   *offset_pos = '/';
 
+  /* validate the revision number and return the revision info */
   if (revision - fs->start_revision > fs->revisions->nelts)
     return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
                              _("Unknown revision %d"), revision);
@@ -766,6 +1075,12 @@ parse_revnode_pos(revision_info_t **revi
   return SVN_NO_ERROR;
 }
 
+/* Returns in *RESULT the noderev at OFFSET relative the revision given in
+ * REVISION_INFO.  If no such noderev has been parsed, yet, error out.
+ *
+ * Since we require the noderev to already have been parsed, we can use
+ * this functions only to access "older", i.e. predecessor noderevs.
+ */
 static svn_error_t *
 find_noderev(noderev_t **result,
             revision_info_t *revision_info,
@@ -776,18 +1091,21 @@ find_noderev(noderev_t **result,
                                           compare_noderev_offsets);
   if ((idx < 0) || (idx >= revision_info->node_revs->nelts))
     return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
-                             _("No noderev found at offset %" APR_OFF_T_FMT),
-                             offset);
+                             _("No noderev found at offset %ld"),
+                             (long)offset);
 
   *result = APR_ARRAY_IDX(revision_info->node_revs, idx, noderev_t *);
   if ((*result)->original.offset != offset)
     return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
-                             _("No noderev found at offset %" APR_OFF_T_FMT),
-                             offset);
+                             _("No noderev found at offset %ld"),
+                             (long)offset);
 
   return SVN_NO_ERROR;
 }
 
+/* In *RESULT, return the noderev given by ID in FS.  The noderev must
+ * already have been parsed and put into the FS data structures.
+ */
 static svn_error_t *
 parse_pred(noderev_t **result,
            fs_fs_t *fs,
@@ -802,11 +1120,15 @@ parse_pred(noderev_t **result,
   return SVN_NO_ERROR;
 }
 
+/* Comparator used for binary search comparing the absolute file offset
+ * of a representation to some other offset. DATA is a *representation_t,
+ * KEY is a pointer to an apr_size_t.
+ */
 static int
 compare_representation_offsets(const void *data, const void *key)
 {
-  apr_ssize_t diff = (*(const representation_t **)data)->original.offset
-                   - *(const apr_size_t *)key;
+  apr_ssize_t diff = (*(const representation_t *const *)data)->original.offset
+                     - *(const apr_size_t *)key;
 
   /* sizeof(int) may be < sizeof(ssize_t) */
   if (diff < 0)
@@ -814,6 +1136,15 @@ compare_representation_offsets(const voi
   return diff > 0 ? 1 : 0;
 }
 
+/* Find the revision_info_t object to the given REVISION in FS and return
+ * it in *REVISION_INFO. For performance reasons, we skip the lookup if
+ * the info is already provided.
+ *
+ * In that revision, look for the representation_t object for offset OFFSET.
+ * If it already exists, set *idx to its index in *REVISION_INFO's
+ * representations list and return the representation object. Otherwise,
+ * set the index to where it must be inserted and return NULL.
+ */
 static representation_t *
 find_representation(int *idx,
                     fs_fs_t *fs,
@@ -823,7 +1154,8 @@ find_representation(int *idx,
 {
   revision_info_t *info;
   *idx = -1;
-  
+
+  /* first let's find the revision '*/
   info = revision_info ? *revision_info : NULL;
   if (info == NULL || info->revision != revision)
     {
@@ -834,23 +1166,36 @@ find_representation(int *idx,
         *revision_info = info;
     }
 
+  /* not found -> no result */
   if (info == NULL)
     return NULL;
+  
+  assert(revision == info->revision);
 
+  /* look for the representation */
   *idx = svn_sort__bsearch_lower_bound(&offset,
                                        info->representations,
                                        compare_representation_offsets);
   if (*idx < info->representations->nelts)
     {
+      /* return the representation, if this is the one we were looking for */
       representation_t *result
         = APR_ARRAY_IDX(info->representations, *idx, representation_t *);
       if (result->original.offset == offset)
         return result;
     }
 
+  /* not parsed, yet */
   return NULL;
 }
 
+/* Read the representation header in FILE_CONTENT at OFFSET.  Return its
+ * size in *HEADER_SIZE, set *IS_PLAIN if no deltification was used and
+ * return the deltification base representation in *REPRESENTATION.  If
+ * there is none, set it to NULL.  Use FS to it look up.
+ *
+ * Use SCRATCH_POOL for temporary allocations.
+ */
 static svn_error_t *
 read_rep_base(representation_t **representation,
               apr_size_t *header_size,
@@ -858,17 +1203,18 @@ read_rep_base(representation_t **represe
               fs_fs_t *fs,
               svn_stringbuf_t *file_content,
               apr_size_t offset,
-              apr_pool_t *pool,
               apr_pool_t *scratch_pool)
 {
   char *str, *last_str;
   int idx, revision;
   apr_uint64_t temp;
 
+  /* identify representation header (1 line) */
   const char *buffer = file_content->data + offset;
   const char *line_end = strchr(buffer, '\n');
   *header_size = line_end - buffer + 1;
 
+  /* check for PLAIN rep */
   if (strncmp(buffer, "PLAIN\n", *header_size) == 0)
     {
       *is_plain = TRUE;
@@ -876,6 +1222,7 @@ read_rep_base(representation_t **represe
       return SVN_NO_ERROR;
     }
 
+  /* check for DELTA against empty rep */
   *is_plain = FALSE;
   if (strncmp(buffer, "DELTA\n", *header_size) == 0)
     {
@@ -884,10 +1231,12 @@ read_rep_base(representation_t **represe
       return SVN_NO_ERROR;
     }
 
+  /* it's delta against some other rep. Duplicate the header info such
+   * that we may modify it during parsing. */
   str = apr_pstrndup(scratch_pool, buffer, line_end - buffer);
   last_str = str;
 
-  /* We hopefully have a DELTA vs. a non-empty base revision. */
+  /* parse it. */
   str = svn_cstring_tokenize(" ", &last_str);
   str = svn_cstring_tokenize(" ", &last_str);
   SVN_ERR(svn_cstring_atoi(&revision, str));
@@ -895,10 +1244,18 @@ read_rep_base(representation_t **represe
   str = svn_cstring_tokenize(" ", &last_str);
   SVN_ERR(svn_cstring_strtoui64(&temp, str, 0, APR_SIZE_MAX, 10));
 
+  /* it should refer to a rep in an earlier revision.  Look it up */
   *representation = find_representation(&idx, fs, NULL, revision, (apr_size_t)temp);
   return SVN_NO_ERROR;
 }
 
+/* Parse the representation reference (text: or props:) in VALUE, look
+ * it up in FS and return it in *REPRESENTATION.  To be able to parse the
+ * base rep, we pass the FILE_CONTENT as well.
+ * 
+ * If necessary, allocate the result in POOL; use SCRATCH_POOL for temp.
+ * allocations.
+ */
 static svn_error_t *
 parse_representation(representation_t **representation,
                      fs_fs_t *fs,
@@ -915,14 +1272,19 @@ parse_representation(representation_t **
   apr_uint64_t size;
   int idx;
 
+  /* read location (revision, offset) and size */
   char *c = (char *)value->data;
   SVN_ERR(svn_cstring_atoi(&revision, svn_cstring_tokenize(" ", &c)));
   SVN_ERR(svn_cstring_strtoui64(&offset, svn_cstring_tokenize(" ", &c), 0, APR_SIZE_MAX, 10));
   SVN_ERR(svn_cstring_strtoui64(&size, svn_cstring_tokenize(" ", &c), 0, APR_SIZE_MAX, 10));
 
+  /* look it up */
   result = find_representation(&idx, fs, &revision_info, revision, (apr_size_t)offset);
   if (!result)
     {
+      /* not parsed, yet (probably a rep in the same revision).
+       * Create a new rep object and determine its base rep as well.
+       */
       result = apr_pcalloc(pool, sizeof(*result));
       result->revision = revision_info;
       result->original.offset = (apr_size_t)offset;
@@ -930,7 +1292,7 @@ parse_representation(representation_t **
       SVN_ERR(read_rep_base(&result->delta_base, &result->header_size,
                             &result->is_plain, fs, file_content,
                             (apr_size_t)offset + revision_info->original.offset,
-                            pool, scratch_pool));
+                            scratch_pool));
 
       svn_sort__array_insert(&result, revision_info->representations, idx);
     }
@@ -940,8 +1302,10 @@ parse_representation(representation_t **
   return SVN_NO_ERROR;
 }
 
-/* Skip forwards to THIS_CHUNK in REP_STATE and then read the next delta
-   window into *NWIN. */
+/* Read the delta window contents of all windows in REPRESENTATION in FS.
+ * Return the data as svn_txdelta_window_t* instances in *WINDOWS.
+ * Use POOL for allocations.
+ */
 static svn_error_t *
 read_windows(apr_array_header_t **windows,
              fs_fs_t *fs,
@@ -958,13 +1322,16 @@ read_windows(apr_array_header_t **window
 
   *windows = apr_array_make(pool, 0, sizeof(svn_txdelta_window_t *));
 
+  /* get the whole revision content */
   SVN_ERR(get_content(&content, fs, representation->revision->revision, pool));
 
+  /* create a read stream and position it directly after the rep header */
   data.data = content->data + offset + 3;
   data.len = representation->original.size - 3;
   stream = svn_stream_from_string(&data, pool);
   SVN_ERR(svn_stream_read(stream, &version, &len));
 
+  /* read the windows from that stream */
   while (TRUE)
     {
       svn_txdelta_window_t *window;
@@ -985,6 +1352,9 @@ read_windows(apr_array_header_t **window
   return SVN_NO_ERROR;
 }
 
+/* Read the content of the PLAIN REPRESENTATION in FS and return it in
+ * *CONTENT.  Use POOL for allocations.
+ */
 static svn_error_t *
 read_plain(svn_stringbuf_t **content,
            fs_fs_t *fs,
@@ -997,6 +1367,7 @@ read_plain(svn_stringbuf_t **content,
 
   SVN_ERR(get_content(&data, fs, representation->revision->revision, pool));
 
+  /* content is stored as fulltext already */
   *content = svn_stringbuf_ncreate(data->data + offset,
                                    representation->original.size,
                                    pool);
@@ -1004,9 +1375,10 @@ read_plain(svn_stringbuf_t **content,
   return SVN_NO_ERROR;
 }
 
-/* Get the undeltified window that is a result of combining all deltas
-   from the current desired representation identified in *RB with its
-   base representation.  Store the window in *RESULT. */
+/* Get the undeltified representation that is a result of combining all
+ * deltas from the current desired REPRESENTATION in FS with its base
+ * representation.  Store the result in *CONTENT.
+ * Use POOL for allocations. */
 static svn_error_t *
 get_combined_window(svn_stringbuf_t **content,
                     fs_fs_t *fs,
@@ -1017,23 +1389,31 @@ get_combined_window(svn_stringbuf_t **co
   apr_array_header_t *windows;
   svn_stringbuf_t *base_content, *result;
   const char *source;
-  apr_pool_t *sub_pool = svn_pool_create(pool);
-  apr_pool_t *iter_pool = svn_pool_create(pool);
+  apr_pool_t *sub_pool;
+  apr_pool_t *iter_pool;
 
+  /* special case: no un-deltification necessary */
   if (representation->is_plain)
     return read_plain(content, fs, representation, pool);
 
+  /* special case: data already in cache */
   *content = get_cached_window(fs, representation, pool);
   if (*content)
     return SVN_NO_ERROR;
-  
+
+  /* read the delta windows for this representation */
+  sub_pool = svn_pool_create(pool);
+  iter_pool = svn_pool_create(pool);
   SVN_ERR(read_windows(&windows, fs, representation, sub_pool));
+
+  /* fetch the / create a base content */
   if (representation->delta_base && representation->delta_base->revision)
     SVN_ERR(get_combined_window(&base_content, fs,
                                 representation->delta_base, sub_pool));
   else
     base_content = svn_stringbuf_create_empty(sub_pool);
 
+  /* apply deltas */
   result = svn_stringbuf_create_empty(pool);
   source = base_content->data;
   
@@ -1056,12 +1436,15 @@ get_combined_window(svn_stringbuf_t **co
 
   svn_pool_destroy(iter_pool);
   svn_pool_destroy(sub_pool);
-  
+
+  /* cache result and return it */
   set_cached_window(fs, representation, result);
   *content = result;
+  
   return SVN_NO_ERROR;
 }
 
+/* forward declaration */
 static svn_error_t *
 read_noderev(noderev_t **noderev,
              fs_fs_t *fs,
@@ -1071,6 +1454,13 @@ read_noderev(noderev_t **noderev,
              apr_pool_t *pool,
              apr_pool_t *scratch_pool);
 
+/* Get the noderev at OFFSET in FILE_CONTENT in FS.  The file content must
+ * pertain to the revision given in REVISION_INFO.  If the data has not
+ * been read yet, parse it and store it in REVISION_INFO.  Return the result
+ * in *NODEREV.
+ * 
+ * Use POOL for allocations and SCRATCH_POOL for temporaries.
+ */
 static svn_error_t *
 get_noderev(noderev_t **noderev,
             fs_fs_t *fs,
@@ -1097,6 +1487,10 @@ get_noderev(noderev_t **noderev,
   return SVN_NO_ERROR;
 }
 
+/* Read the directory stored in REPRESENTATION in FS into *HASH.  The result
+ * will be allocated in FS' directory cache and it will be plain key-value
+ * hash.  Use SCRATCH_POOL for temporary allocations.
+ */
 static svn_error_t *
 read_dir(apr_hash_t **hash,
          fs_fs_t *fs,
@@ -1108,12 +1502,16 @@ read_dir(apr_hash_t **hash,
   svn_stream_t *stream;
   apr_pool_t *pool;
 
+  /* chances are, we find the info in cache already */
   *hash = get_cached_dir(fs, representation);
   if (*hash)
     return SVN_NO_ERROR;
 
+  /* create the result container */
   pool = get_cached_dir_pool(fs);
   *hash = svn_hash__make(pool);
+
+  /* if this is a non-empty rep, read it and de-serialize the hash */
   if (representation != NULL)
     {
       text_pool = svn_pool_create(scratch_pool);
@@ -1123,11 +1521,18 @@ read_dir(apr_hash_t **hash,
       svn_pool_destroy(text_pool);
     }
 
+  /* cache the result */
   set_cached_dir(fs, representation, *hash);
   
   return SVN_NO_ERROR;
 }
 
+/* Starting at the directory in REPRESENTATION in FILE_CONTENT, read all
+ * DAG nodes, directories and representations linked in that tree structure.
+ * Store them in FS and read them only once.
+ *
+ * Use POOL for persistent allocations and SCRATCH_POOL for temporaries.
+ */
 static svn_error_t *
 parse_dir(fs_fs_t *fs,
           svn_stringbuf_t *file_content,
@@ -1140,9 +1545,11 @@ parse_dir(fs_fs_t *fs,
   apr_pool_t *iter_pool = svn_pool_create(scratch_pool);
   apr_hash_t *base_dir = svn_hash__make(scratch_pool);
 
+  /* special case: empty dir rep */
   if (representation == NULL)
     return SVN_NO_ERROR;
 
+  /* if we have a previous representation of that dir, hash it by name */
   if (representation->delta_base && representation->delta_base->dir)
     {
       apr_array_header_t *dir = representation->delta_base->dir->entries;
@@ -1155,31 +1562,41 @@ parse_dir(fs_fs_t *fs,
         }
     }
 
+  /* read this directory */
   SVN_ERR(read_dir(&hash, fs, representation, scratch_pool));
 
+  /* add it as an array to the representation (entries yet to be filled) */
   representation->dir = apr_pcalloc(pool, sizeof(*representation->dir));
   representation->dir->entries
     = apr_array_make(pool, apr_hash_count(hash), sizeof(direntry_t *));
 
-  /* Translate the string dir entries into real entries. */
+  /* Translate the string dir entries into real entries.  Reuse existing
+   * objects as much as possible to keep memory consumption low.
+   */
   for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi))
     {
       const char *name = svn__apr_hash_index_key(hi);
       svn_string_t *str_val = svn__apr_hash_index_val(hi);
       apr_size_t offset;
       revision_info_t *revision_info;
+
+      /* look for corresponding entry in previous version */
       apr_size_t name_len = strlen(name);
       direntry_t *entry = base_dir
                         ? apr_hash_get(base_dir, name, name_len)
                         : NULL;
 
+      /* parse the new target revnode ID (revision, offset) */
       SVN_ERR(parse_revnode_pos(&revision_info, &offset, fs, str_val));
 
+      /* if this is a new entry or if the content changed, create a new
+       * instance for it. */
       if (   !entry
           || !entry->node->text
           || entry->node->text->revision != revision_info
           || entry->node->original.offset != offset)
         {
+          /* create & init the new entry. Reuse the name string if possible */
           direntry_t *new_entry = apr_pcalloc(pool, sizeof(*entry));
           new_entry->name_len = name_len;
           if (entry)
@@ -1187,11 +1604,13 @@ parse_dir(fs_fs_t *fs,
           else
             new_entry->name = apr_pstrdup(pool, name);
 
+          /* Link it to the content noderev. Recurse. */
           entry = new_entry;
           SVN_ERR(get_noderev(&entry->node, fs, file_content, offset,
                               revision_info, pool, iter_pool));
         }
 
+      /* set the directory entry */
       APR_ARRAY_PUSH(representation->dir->entries, direntry_t *) = entry;
       svn_pool_clear(iter_pool);
     }
@@ -1200,6 +1619,12 @@ parse_dir(fs_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Starting at the noderev at OFFSET in FILE_CONTENT, read all DAG nodes,
+ * directories and representations linked in that tree structure.  Store
+ * them in FS and read them only once.  Return the result in *NODEREV.
+ *
+ * Use POOL for persistent allocations and SCRATCH_POOL for temporaries.
+ */
 static svn_error_t *
 read_noderev(noderev_t **noderev,
              fs_fs_t *fs,
@@ -1214,10 +1639,12 @@ read_noderev(noderev_t **noderev,
   svn_boolean_t is_dir = FALSE;
 
   scratch_pool = svn_pool_create(scratch_pool);
-  
+
+  /* parse the noderev line-by-line until we find an empty line */
   result->original.offset = offset;
   while (1)
     {
+      /* for this line, extract key and value. Ignore invalid values */
       svn_string_t key;
       svn_string_t value;
       char *sep;
@@ -1227,6 +1654,8 @@ read_noderev(noderev_t **noderev,
 
       line = svn_string_ncreate(start, end - start, scratch_pool);
       offset += end - start + 1;
+
+      /* empty line -> end of noderev data */
       if (line->len == 0)
         break;
       
@@ -1244,6 +1673,7 @@ read_noderev(noderev_t **noderev,
       value.data = sep + 2;
       value.len = line->len - (key.len + 2);
 
+      /* translate (key, value) into noderev elements */
       if (key_matches(&key, "type"))
         is_dir = strcmp(value.data, "dir") == 0;
       else if (key_matches(&key, "pred"))
@@ -1258,6 +1688,7 @@ read_noderev(noderev_t **noderev,
                                      pool, scratch_pool));
     }
 
+  /* link noderev to revision info */
   result->revision = revision_info;
   result->original.size = offset - result->original.offset;
 
@@ -1267,22 +1698,30 @@ read_noderev(noderev_t **noderev,
                                                        revision_info->node_revs,
                                                        compare_noderev_offsets));
 
+  /* if this is a directory, read and process that recursively */
   if (is_dir)
     SVN_ERR(parse_dir(fs, file_content, result->text,
                       pool, scratch_pool));
 
+  /* done */
   svn_pool_destroy(scratch_pool);
   *noderev = result;
 
   return SVN_NO_ERROR;
 }
 
-static void print_progress(svn_revnum_t revision)
+/* Simple utility to print a REVISION number and make it appear immediately.
+ */
+static void
+print_progress(svn_revnum_t revision)
 {
   printf("%8ld", revision);
   fflush(stdout);
 }
 
+/* Read the content of the pack file staring at revision BASE and store it
+ * in FS.  Use POOL for allocations.
+ */
 static svn_error_t *
 read_pack_file(fs_fs_t *fs,
                svn_revnum_t base,
@@ -1295,8 +1734,11 @@ read_pack_file(fs_fs_t *fs,
   svn_stringbuf_t *file_content;
   revision_pack_t *revisions;
   const char *pack_folder = get_pack_folder(fs, base, local_pool);
+
+  /* read the whole pack file into memory */
   SVN_ERR(read_rev_or_pack_file(&file_content, fs, base, local_pool));
 
+  /* create the revision container */
   revisions = apr_pcalloc(pool, sizeof(*revisions));
   revisions->base = base;
   revisions->fragments = NULL;
@@ -1306,15 +1748,18 @@ read_pack_file(fs_fs_t *fs,
   revisions->filesize = file_content->len;
   APR_ARRAY_PUSH(fs->packs, revision_pack_t*) = revisions;
 
+  /* parse the manifest file */
   SVN_ERR(read_manifest(&manifest, fs, pack_folder, local_pool));
   if (manifest->nelts != fs->max_files_per_dir)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, NULL);
 
+  /* process each revision in the pack file */
   for (i = 0; i < manifest->nelts; ++i)
     {
       apr_size_t root_node_offset;
       svn_string_t rev_content;
-  
+
+      /* create the revision info for the current rev */
       revision_info_t *info = apr_pcalloc(pool, sizeof(*info));
       info->node_revs = apr_array_make(iter_pool, 4, sizeof(noderev_t*));
       info->representations = apr_array_make(iter_pool, 4, sizeof(representation_t*));
@@ -1332,28 +1777,37 @@ read_pack_file(fs_fs_t *fs,
                                    info->original.end,
                                    iter_pool));
 
+      /* put it into our containers */
       APR_ARRAY_PUSH(revisions->info, revision_info_t*) = info;
       APR_ARRAY_PUSH(fs->revisions, revision_info_t*) = info;
-      
+
+      /* cache the revision content */
       rev_content.data = file_content->data + info->original.offset;
       rev_content.len = info->original.end - info->original.offset;
       set_cached_content(fs->cache, info->revision, &rev_content);
 
+      /* parse the revision content recursively. */
       SVN_ERR(read_noderev(&info->root_noderev, fs, file_content,
                            root_node_offset, info, pool, iter_pool));
 
+      /* copy dynamically grown containers from temp into result pool */
       info->node_revs = apr_array_copy(pool, info->node_revs);
       info->representations = apr_array_copy(pool, info->representations);
-      
+
+      /* destroy temps */
       svn_pool_clear(iter_pool);
     }
 
+  /* one more pack file processed */
   print_progress(base);
   apr_pool_destroy(local_pool);
 
   return SVN_NO_ERROR;
 }
 
+/* Read the content of REVSION file and store it in FS.
+ * Use POOL for allocations.
+ */
 static svn_error_t *
 read_revision_file(fs_fs_t *fs,
                    svn_revnum_t revision,
@@ -1366,8 +1820,10 @@ read_revision_file(fs_fs_t *fs,
   revision_pack_t *revisions = apr_pcalloc(pool, sizeof(*revisions));
   revision_info_t *info = apr_pcalloc(pool, sizeof(*info));
 
+  /* read the whole pack file into memory */
   SVN_ERR(read_rev_or_pack_file(&file_content, fs, revision, local_pool));
 
+  /* create the revision info for the current rev */
   info->node_revs = apr_array_make(pool, 4, sizeof(noderev_t*));
   info->representations = apr_array_make(pool, 4, sizeof(representation_t*));
 
@@ -1382,8 +1838,12 @@ read_revision_file(fs_fs_t *fs,
                                info->original.end,
                                local_pool));
 
+  /* put it into our containers */
   APR_ARRAY_PUSH(fs->revisions, revision_info_t*) = info;
 
+  /* create a pseudo-pack file container for just this rev to keep our
+   * data structures as uniform as possible.
+   */
   revisions->base = revision;
   revisions->fragments = NULL;
   revisions->info = apr_array_make(pool, 1, sizeof(revision_info_t*));
@@ -1391,15 +1851,18 @@ read_revision_file(fs_fs_t *fs,
   APR_ARRAY_PUSH(revisions->info, revision_info_t*) = info;
   APR_ARRAY_PUSH(fs->packs, revision_pack_t*) = revisions;
 
+  /* cache the revision content */
   rev_content.data = file_content->data + info->original.offset;
   rev_content.len = info->original.end - info->original.offset;
   set_cached_content(fs->cache, info->revision, &rev_content);
 
+  /* parse the revision content recursively. */
   SVN_ERR(read_noderev(&info->root_noderev, fs, file_content,
                        root_node_offset, info,
                        pool, local_pool));
   APR_ARRAY_PUSH(info->node_revs, noderev_t*) = info->root_noderev;
 
+  /* show progress every 1000 revs or so */
   if (revision % fs->max_files_per_dir == 0)
     print_progress(revision);
 
@@ -1408,6 +1871,10 @@ read_revision_file(fs_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Read the repository at PATH beginning with revision START_REVISION and
+ * return the result in *FS.  Allocate caches with MEMSIZE bytes total
+ * capacity.  Use POOL for non-cache allocations.
+ */
 static svn_error_t *
 read_revisions(fs_fs_t **fs,
                const char *path,
@@ -1421,16 +1888,17 @@ read_revisions(fs_fs_t **fs,
   apr_size_t dir_cache_size;
 
   /* determine cache sizes */
-
   if (memsize < 100)
     memsize = 100;
   
   content_cache_size = memsize * 7 / 10 > 4000 ? 4000 : memsize * 7 / 10;
   window_cache_size = memsize * 2 / 10 * 1024 * 1024;
   dir_cache_size = (memsize / 10) * 16000;
-  
+
+  /* read repo format and such */
   SVN_ERR(fs_open(fs, path, pool));
 
+  /* create data containers and caches */
   (*fs)->start_revision = start_revision
                         - (start_revision % (*fs)->max_files_per_dir);
   (*fs)->revisions = apr_array_make(pool,
@@ -1454,20 +1922,28 @@ read_revisions(fs_fs_t **fs,
                          (svn_pool_create_allocator(FALSE)),
                           10000, window_cache_size);
 
+  /* read all packed revs */
   for ( revision = start_revision
       ; revision < (*fs)->min_unpacked_rev
       ; revision += (*fs)->max_files_per_dir)
     SVN_ERR(read_pack_file(*fs, revision, pool));
-    
+
+  /* read non-packed revs */
   for ( ; revision <= (*fs)->max_revision; ++revision)
     SVN_ERR(read_revision_file(*fs, revision, pool));
 
   return SVN_NO_ERROR;
 }
 
+/* Return the maximum number of decimal digits required to represent offsets
+ * in the given PACK file.
+ */
 static apr_size_t
 get_max_offset_len(const revision_pack_t *pack)
 {
+  /* the pack files may grow a few percent.
+   * Fudge it up to be on safe side.
+   */
   apr_size_t max_future_size = pack->filesize * 2 + 10000;
   apr_size_t result = 0;
 
@@ -1480,6 +1956,9 @@ get_max_offset_len(const revision_pack_t
   return result;
 }
 
+/* Create the fragments container in PACK and add revision header fragments
+ * to it.  Use POOL for allocations.
+ */
 static svn_error_t *
 add_revisions_pack_heads(revision_pack_t *pack,
                          apr_pool_t *pool)
@@ -1543,6 +2022,9 @@ add_revisions_pack_heads(revision_pack_t
   return SVN_NO_ERROR;
 }
 
+/* For the revision given by INFO in FS, return the fragment container in
+ * *FRAGMENTS and the current placement offset in *CURRENT_POS.
+ */
 static svn_error_t *
 get_target_offset(apr_size_t **current_pos,
                   apr_array_header_t **fragments,
@@ -1553,6 +2035,7 @@ get_target_offset(apr_size_t **current_p
   revision_pack_t *pack;
   svn_revnum_t revision = info->revision;
 
+  /* identify the pack object */
   if (fs->min_unpacked_rev > revision)
     {
       i = (revision - fs->start_revision) / fs->max_files_per_dir;
@@ -1563,6 +2046,7 @@ get_target_offset(apr_size_t **current_p
       i += revision - fs->min_unpacked_rev;
     }
 
+  /* extract the desired info from it */
   pack = APR_ARRAY_IDX(fs->packs, i, revision_pack_t*);
   *current_pos = &pack->target_offset;
   *fragments = pack->fragments;
@@ -1570,11 +2054,19 @@ get_target_offset(apr_size_t **current_p
   return SVN_NO_ERROR;
 }
 
+/* forward declaration */
 static svn_error_t *
 add_noderev_recursively(fs_fs_t *fs,
                         noderev_t *node,
                         apr_pool_t *pool);
 
+/* Place fragments for the given REPRESENTATION of the given KIND, iff it
+ * has not been covered, yet.  Place the base reps along the deltification
+ * chain as far as those reps have not been covered, yet.  If REPRESENTATION
+ * is a directory, recursively place its elements.
+ * 
+ * Use POOL for allocations.
+ */
 static svn_error_t *
 add_representation_recursively(fs_fs_t *fs,
                                representation_t *representation,
@@ -1584,13 +2076,16 @@ add_representation_recursively(fs_fs_t *
   apr_size_t *current_pos;
   apr_array_header_t *fragments;
   fragment_t fragment;
-  
+
+  /* place REPRESENTATION only once and only if it exists and will not
+   * be covered later as a directory. */
   if (   representation == NULL
       || representation->covered
       || (representation->dir && kind != dir_fragment)
       || representation == fs->null_base)
     return SVN_NO_ERROR;
 
+  /* add and place a fragment for REPRESENTATION */
   SVN_ERR(get_target_offset(&current_pos, &fragments,
                             fs, representation->revision));
   representation->target.offset = *current_pos;
@@ -1601,9 +2096,12 @@ add_representation_recursively(fs_fs_t *
   fragment.position = *current_pos;
   APR_ARRAY_PUSH(fragments, fragment_t) = fragment;
 
+  /* determine the size of data to be added to the target file */
   if (   kind != dir_fragment
       && representation->delta_base && representation->delta_base->dir)
     {
+      /* base rep is a dir -> would change -> need to store it as fulltext
+       * in our target file */
       apr_pool_t *text_pool = svn_pool_create(pool);
       svn_stringbuf_t *content;
 
@@ -1617,6 +2115,7 @@ add_representation_recursively(fs_fs_t *
     if (   kind == dir_fragment
         || (representation->delta_base && representation->delta_base->dir))
       {
+        /* deltified directories may grow considerably */
         if (representation->original.size < 50)
           *current_pos += 300;
         else
@@ -1624,6 +2123,8 @@ add_representation_recursively(fs_fs_t *
       }
     else
       {
+        /* plain / deltified content will not change but the header may
+         * grow slightly due to larger offsets. */
         representation->target.size = representation->original.size;
 
         if (representation->delta_base &&
@@ -1633,12 +2134,14 @@ add_representation_recursively(fs_fs_t *
           *current_pos += representation->original.size + 13;
       }
 
+  /* follow the delta chain and place base revs immediately after this */
   if (representation->delta_base)
     SVN_ERR(add_representation_recursively(fs,
                                            representation->delta_base,
                                            kind,
                                            pool));
 
+  /* finally, recurse into directories */
   if (representation->dir)
     {
       int i;
@@ -1655,6 +2158,11 @@ add_representation_recursively(fs_fs_t *
   return SVN_NO_ERROR;
 }
 
+/* Place fragments for the given NODE in FS, iff it has not been covered,
+ * yet.  Place the reps (text, props) immediately after the node.
+ *
+ * Use POOL for allocations.
+ */
 static svn_error_t *
 add_noderev_recursively(fs_fs_t *fs,
                         noderev_t *node,
@@ -1664,20 +2172,24 @@ add_noderev_recursively(fs_fs_t *fs,
   apr_array_header_t *fragments;
   fragment_t fragment;
 
+  /* don't add it twice */
   if (node->covered)
     return SVN_NO_ERROR;
 
+  /* add and place a fragment for NODE */
   SVN_ERR(get_target_offset(&current_pos, &fragments, fs, node->revision));
   node->covered = TRUE;
   node->target.offset = *current_pos;
 
   fragment.data = node;
-  fragment.kind = noderep_fragment;
+  fragment.kind = noderev_fragment;
   fragment.position = *current_pos;
   APR_ARRAY_PUSH(fragments, fragment_t) = fragment;
 
+  /* size may slightly increase */
   *current_pos += node->original.size + 40;
-  
+
+  /* recurse into representations */
   if (node->text && node->text->dir)
     SVN_ERR(add_representation_recursively(fs, node->text, dir_fragment, pool));
   else
@@ -1688,6 +2200,8 @@ add_noderev_recursively(fs_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Place a fragment for the last revision in PACK. Use POOL for allocations.
+ */
 static svn_error_t *
 add_revisions_pack_tail(revision_pack_t *pack,
                         apr_pool_t *pool)
@@ -1708,6 +2222,7 @@ add_revisions_pack_tail(revision_pack_t 
 
   pack->target_offset += 2 * offset_len + 3;
 
+  /* end of target file reached.  Store that info in all revs. */
   for (i = 0; i < pack->info->nelts; ++i)
     {
       info = APR_ARRAY_IDX(pack->info, i, revision_info_t*);
@@ -1717,6 +2232,9 @@ add_revisions_pack_tail(revision_pack_t 
   return SVN_NO_ERROR;
 }
 
+/* Place all fragments for all revisions / packs in FS.
+ * Use POOL for allocations.
+ */
 static svn_error_t *
 reorder_revisions(fs_fs_t *fs,
                   apr_pool_t *pool)
@@ -1757,12 +2275,20 @@ reorder_revisions(fs_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* forward declaration */
 static svn_error_t *
 get_fragment_content(svn_string_t **content,
                      fs_fs_t *fs,
                      fragment_t *fragment,
                      apr_pool_t *pool);
 
+/* Directory content may change and with it, the deltified representations
+ * may significantly.  This function causes all directory target reps in
+ * PACK of FS to be built and their new MD5 as well as rep sizes be updated.
+ * We must do that before attempting to write noderevs.
+ * 
+ * Use POOL for allocations.
+ */
 static svn_error_t *
 update_noderevs(fs_fs_t *fs,
                 revision_pack_t *pack,
@@ -1778,6 +2304,8 @@ update_noderevs(fs_fs_t *fs,
         {
           svn_string_t *content;
 
+          /* request updated rep content but ignore the result.
+           * We are only interested in the MD5, content and rep size updates. */
           SVN_ERR(get_fragment_content(&content, fs, fragment, itempool));
           svn_pool_clear(itempool);
         }
@@ -1788,6 +2316,11 @@ update_noderevs(fs_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Determine the target size of the FRAGMENT in FS and return the value
+ * in *LENGTH.  If ADD_PADDING has been set, slightly fudge the numbers
+ * to account for changes in offset lengths etc.  Use POOL for temporary
+ * allocations.
+ */
 static svn_error_t *
 get_content_length(apr_size_t *length,
                    fs_fs_t *fs,
@@ -1804,7 +2337,7 @@ get_content_length(apr_size_t *length,
         case dir_fragment:
           *length = content->len + 16;
           break;
-        case noderep_fragment:
+        case noderev_fragment:
           *length = content->len + 3;
           break;
         default:
@@ -1817,6 +2350,9 @@ get_content_length(apr_size_t *length,
   return SVN_NO_ERROR;
 }
 
+/* Move the FRAGMENT to global file offset NEW_POSITION.  Update the target
+ * location info of the underlying object as well.
+ */
 static void
 move_fragment(fragment_t *fragment,
               apr_size_t new_position)
@@ -1824,9 +2360,11 @@ move_fragment(fragment_t *fragment,
   revision_info_t *info;
   representation_t *representation;
   noderev_t *node;
-  
+
+  /* move the fragment */
   fragment->position = new_position; 
 
+  /* move the underlying object */
   switch (fragment->kind)
     {
       case header_fragment:
@@ -1846,13 +2384,17 @@ move_fragment(fragment_t *fragment,
         representation->target.offset = new_position;
         break;
 
-      case noderep_fragment:
+      case noderev_fragment:
         node = fragment->data;
         node->target.offset = new_position;
         break;
     }
 }
 
+/* Move the fragments in PACK's target fragment list to their final offsets.
+ * This may require several iterations if the fudge factors turned out to
+ * be insufficient.  Use POOL for allocations.
+ */
 static svn_error_t *
 pack_revisions(fs_fs_t *fs,
                revision_pack_t *pack,
@@ -1866,8 +2408,13 @@ pack_revisions(fs_fs_t *fs,
 
   apr_pool_t *itempool = svn_pool_create(pool);
 
+  /* update all directory reps. Chances are that most of the target rep
+   * sizes are now close to accurate. */
   SVN_ERR(update_noderevs(fs, pack, pool));
 
+  /* compression phase: pack all fragments tightly with only a very small
+   * fudge factor.  This should cause offsets to shrink, thus all the
+   * actual fragment rate should tend to be even smaller afterwards. */
   current_pos = pack->info->nelts > 1 ? 64 : 0;
   for (i = 0; i + 1 < pack->fragments->nelts; ++i)
     {
@@ -1879,9 +2426,15 @@ pack_revisions(fs_fs_t *fs,
       svn_pool_clear(itempool);
     }
 
+  /* don't forget the final fragment (last revision's revision header) */
   fragment = &APR_ARRAY_IDX(pack->fragments, pack->fragments->nelts-1, fragment_t);
   fragment->position = current_pos;
 
+  /* expansion phase: check whether all fragments fit into their allotted
+   * slots.  Grow them geometrically if they don't fit.  Retry until they
+   * all do fit.
+   * Note: there is an upper limit to which fragments can grow.  So, this
+   * loop will terminate.  Often, no expansion will be necessary at all. */
   do
     {
       needed_to_expand = FALSE;
@@ -1918,6 +2471,8 @@ pack_revisions(fs_fs_t *fs,
       fragment = &APR_ARRAY_IDX(pack->fragments, pack->fragments->nelts-1, fragment_t);
       fragment->position = current_pos;
 
+      /* update the revision
+       * sizes (they all end at the end of the pack file now) */
       SVN_ERR(get_content_length(&len, fs, fragment, FALSE, itempool));
       current_pos += len;
 
@@ -1934,6 +2489,8 @@ pack_revisions(fs_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Write reorg'ed target content for PACK in FS.  Use POOL for allocations.
+ */
 static svn_error_t *
 write_revisions(fs_fs_t *fs,
                 revision_pack_t *pack,
@@ -1950,6 +2507,7 @@ write_revisions(fs_fs_t *fs,
   apr_size_t current_pos = 0;
   svn_stringbuf_t *null_buffer = svn_stringbuf_create_empty(iterpool);
 
+  /* create the target file */
   const char *dir = apr_psprintf(iterpool, "%s/new/%ld%s",
                                   fs->path, pack->base / fs->max_files_per_dir,
                                   pack->info->nelts > 1 ? ".pack" : "");
@@ -1962,38 +2520,46 @@ write_revisions(fs_fs_t *fs,
                             APR_OS_DEFAULT,
                             iterpool));
 
+  /* write all fragments */
   for (i = 0; i < pack->fragments->nelts; ++i)
     {
       apr_size_t padding;
+
+      /* get fragment content to write */
       fragment = &APR_ARRAY_IDX(pack->fragments, i, fragment_t);
       SVN_ERR(get_fragment_content(&content, fs, fragment, itempool));
-
       SVN_ERR_ASSERT(fragment->position >= current_pos);
+
+      /* number of bytes between this and the previous fragment */
       if (   fragment->kind == header_fragment
           && i+1 < pack->fragments->nelts)
+        /* special case: header fragments are aligned to the slot end */
         padding = APR_ARRAY_IDX(pack->fragments, i+1, fragment_t).position -
                   content->len - current_pos;
       else
+        /* standard case: fragments are aligned to the slot start */
         padding = fragment->position - current_pos;
 
+      /* write padding between fragments */
       if (padding)
         {
           while (null_buffer->len < padding)
             svn_stringbuf_appendbyte(null_buffer, 0);
 
           SVN_ERR(svn_io_file_write_full(file,
-                                          null_buffer->data,
-                                          padding,
-                                          NULL,
-                                          itempool));
+                                         null_buffer->data,
+                                         padding,
+                                         NULL,
+                                         itempool));
           current_pos += padding;
         }
 
+      /* write fragment content */
       SVN_ERR(svn_io_file_write_full(file,
-                                      content->data,
-                                      content->len,
-                                      NULL,
-                                      itempool));
+                                     content->data,
+                                     content->len,
+                                     NULL,
+                                     itempool));
       current_pos += content->len;
 
       svn_pool_clear(itempool);
@@ -2001,6 +2567,7 @@ write_revisions(fs_fs_t *fs,
 
   apr_file_close(file);
 
+  /* write new manifest file */
   if (pack->info->nelts > 1)
     {
       svn_stream_t *stream;
@@ -2016,18 +2583,23 @@ write_revisions(fs_fs_t *fs,
           revision_info_t *info = APR_ARRAY_IDX(pack->info, i,
                                                 revision_info_t *);
           SVN_ERR(svn_stream_printf(stream, itempool,
-                                    "%" APR_UINT64_T_FMT "\n",
+                                    "%" APR_SIZE_T_FMT "\n",
                                     info->target.offset));
           svn_pool_clear(itempool);
         }
     }
 
+  /* cleanup */
   svn_pool_destroy(itempool);
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
 
+/* Write reorg'ed target content for all revisions in FS.  To maximize
+ * data locality, pack and write in one go per pack file.
+ * Use POOL for allocations.
+ */
 static svn_error_t *
 pack_and_write_revisions(fs_fs_t *fs,
                          apr_pool_t *pool)
@@ -2051,6 +2623,10 @@ pack_and_write_revisions(fs_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* For the directory REPRESENTATION in FS, construct the new (target)
+ * serialized plaintext representation and return it in *CONTENT.
+ * Allocate the result in POOL and temporaries in SCRATCH_POOL.
+ */
 static svn_error_t *
 get_updated_dir(svn_string_t **content,
                 fs_fs_t *fs,
@@ -2064,14 +2640,19 @@ get_updated_dir(svn_string_t **content,
   int i;
   svn_stream_t *stream;
   svn_stringbuf_t *result;
-  
+
+  /* get the original content */
   SVN_ERR(read_dir(&hash, fs, representation, scratch_pool));
   hash = apr_hash_copy(hash_pool, hash);
+
+  /* update all entries */
   for (i = 0; i < dir->nelts; ++i)
     {
       char buffer[256];
       svn_string_t *new_val;
       apr_size_t pos;
+
+      /* find the original entry for for the current name */
       direntry_t *entry = APR_ARRAY_IDX(dir, i, direntry_t *);
       svn_string_t *str_val = apr_hash_get(hash, entry->name, entry->name_len);
       if (str_val == NULL)
@@ -2079,54 +2660,40 @@ get_updated_dir(svn_string_t **content,
                                  _("Dir entry '%s' not found"), entry->name);
 
       SVN_ERR_ASSERT(str_val->len < sizeof(buffer));
-      
+
+      /* create and updated node ID */
       memcpy(buffer, str_val->data, str_val->len+1);
       pos = strchr(buffer, '/') - buffer + 1;
       pos += svn__ui64toa(buffer + pos, entry->node->target.offset - entry->node->revision->target.offset);
       new_val = svn_string_ncreate(buffer, pos, hash_pool);
 
+      /* store it in the hash */
       apr_hash_set(hash, entry->name, entry->name_len, new_val);
     }
 
+  /* serialize the updated hash */
   result = svn_stringbuf_create_ensure(representation->target.size, pool);
   stream = svn_stream_from_stringbuf(result, hash_pool);
   SVN_ERR(svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, hash_pool));
   svn_pool_destroy(hash_pool);
 
+  /* done */
   *content = svn_stringbuf__morph_into_string(result);
   
   return SVN_NO_ERROR;
 }
 
-struct diff_write_baton_t
-{
-  svn_stream_t *stream;
-  apr_size_t size;
-};
-
-static svn_error_t *
-diff_write_handler(void *baton,
-                   const char *data,
-                   apr_size_t *len)
-{
-  struct diff_write_baton_t *whb = baton;
-
-  SVN_ERR(svn_stream_write(whb->stream, data, len));
-  whb->size += *len;
-
-  return SVN_NO_ERROR;
-}
-
+/* Calculate the delta representation for the given CONTENT and BASE.
+ * Return the rep in *DIFF.  Use POOL for allocations.
+ */
 static svn_error_t *
 diff_stringbufs(svn_stringbuf_t *diff,
-                apr_size_t *inflated_size,
                 svn_string_t *base,
                 svn_string_t *content,
                 apr_pool_t *pool)
 {
   svn_txdelta_window_handler_t diff_wh;
   void *diff_whb;
-  struct diff_write_baton_t whb;
 
   svn_stream_t *stream;
   svn_stream_t *source = svn_stream_from_string(base, pool);
@@ -2140,20 +2707,20 @@ diff_stringbufs(svn_stringbuf_t *diff,
                           SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
                           pool);
 
-  whb.stream = svn_txdelta_target_push(diff_wh, diff_whb, source, pool);
-  whb.size = 0;
-
-  stream = svn_stream_create(&whb, pool);
-  svn_stream_set_write(stream, diff_write_handler);
+  /* create delta stream */
+  stream = svn_txdelta_target_push(diff_wh, diff_whb, source, pool);
 
+  /* run delta */
   SVN_ERR(svn_stream_write(stream, content->data, &content->len));
-  SVN_ERR(svn_stream_close(whb.stream));
   SVN_ERR(svn_stream_close(stream));
 
-  *inflated_size = whb.size;
   return SVN_NO_ERROR;
 }
 
+/* Update the noderev id value for KEY in the textual noderev representation
+ * in NODE_REV.  Take the new id from NODE.  This is a no-op if the KEY
+ * cannot be found.
+ */
 static void
 update_id(svn_stringbuf_t *node_rev,
           const char *key,
@@ -2162,6 +2729,7 @@ update_id(svn_stringbuf_t *node_rev,
   char *newline_pos = 0;
   char *pos;
 
+  /* we need to update the offset only -> find its position */
   pos = strstr(node_rev->data, key);
   if (pos)
     pos = strchr(pos, '/');
@@ -2170,6 +2738,7 @@ update_id(svn_stringbuf_t *node_rev,
 
   if (pos && newline_pos)
     {
+      /* offset data has been found -> replace it */
       char temp[SVN_INT64_BUFFER_SIZE];
       apr_size_t len = svn__i64toa(temp, node->target.offset - node->revision->target.offset);
       svn_stringbuf_replace(node_rev,
@@ -2178,6 +2747,11 @@ update_id(svn_stringbuf_t *node_rev,
     }
 }
 
+/* Update the representation id value for KEY in the textual noderev
+ * representation in NODE_REV.  Take the offset, sizes and new MD5 from
+ * REPRESENTATION.  Use SCRATCH_POOL for allocations.
+ * This is a no-op if the KEY cannot be found.
+ */
 static void
 update_text(svn_stringbuf_t *node_rev,
             const char *key,
@@ -2194,11 +2768,11 @@ update_text(svn_stringbuf_t *node_rev,
   val_pos = pos + key_len;
   if (representation->dir)
     {
+      /* for directories, we need to write all rep info anew */
       char *newline_pos = strchr(val_pos, '\n');
-      svn_checksum_t checksum = {representation->dir->target_md5,
-                                 svn_checksum_md5};
-      const char* temp = apr_psprintf(scratch_pool, "%ld %" APR_UINT64_T_FMT " %" 
-                                      APR_UINT64_T_FMT" %" APR_SIZE_T_FMT " %s",
+      svn_checksum_t checksum;
+      const char* temp = apr_psprintf(scratch_pool, "%ld %" APR_SIZE_T_FMT " %" 
+                                      APR_SIZE_T_FMT" %" APR_SIZE_T_FMT " %s",
                                       representation->revision->revision,
                                       representation->target.offset - representation->revision->target.offset,
                                       representation->target.size,
@@ -2206,18 +2780,22 @@ update_text(svn_stringbuf_t *node_rev,
                                       svn_checksum_to_cstring(&checksum,
                                                               scratch_pool));
 
+      checksum.digest = representation->dir->target_md5;
+      checksum.kind = svn_checksum_md5;
       svn_stringbuf_replace(node_rev,
                             val_pos - node_rev->data, newline_pos - val_pos,
                             temp, strlen(temp));
     }
   else
     {
+      /* ordinary representation: replace offset and rep size only.
+       * Content size and checksums are unchanged. */
       const char* temp;
       char *end_pos = strchr(val_pos, ' ');
       
       val_pos = end_pos + 1;
       end_pos = strchr(strchr(val_pos, ' ') + 1, ' ');
-      temp = apr_psprintf(scratch_pool, "%" APR_UINT64_T_FMT " %" APR_UINT64_T_FMT,
+      temp = apr_psprintf(scratch_pool, "%" APR_SIZE_T_FMT " %" APR_SIZE_T_FMT,
                           representation->target.offset - representation->revision->target.offset,
                           representation->target.size);
 
@@ -2227,6 +2805,13 @@ update_text(svn_stringbuf_t *node_rev,
     }
 }
 
+/* Get the target content (data block as to be written to the file) for
+ * the given FRAGMENT in FS.  Return the content in *CONTENT.  Use POOL
+ * for allocations.
+ *
+ * Note that, as a side-effect, this will update the target rep. info for
+ * directories.
+ */
 static svn_error_t *
 get_fragment_content(svn_string_t **content,
                      fs_fs_t *fs,
@@ -2243,14 +2828,16 @@ get_fragment_content(svn_string_t **cont
 
   switch (fragment->kind)
     {
+      /* revision headers can be constructed from target position info */
       case header_fragment:
         info = fragment->data;
         *content = svn_string_createf(pool,
-                                      "\n%" APR_UINT64_T_FMT " %" APR_UINT64_T_FMT "\n",
+                                      "\n%" APR_SIZE_T_FMT " %" APR_SIZE_T_FMT "\n",
                                       info->root_noderev->target.offset - info->target.offset,
                                       info->target.changes);
         return SVN_NO_ERROR;
 
+      /* The changes list remains untouched */
       case changes_fragment:
         info = fragment->data;
         SVN_ERR(get_content(&revision_content, fs, info->revision, pool));
@@ -2260,6 +2847,9 @@ get_fragment_content(svn_string_t **cont
         (*content)->len = info->target.changes_len;
         return SVN_NO_ERROR;
 
+      /* property and file reps get new headers any need to be rewritten,
+       * iff the base rep is a directory.  The actual (deltified) content
+       * remains unchanged, though.  MD5 etc. do not change. */
       case property_fragment:
       case file_fragment:
         representation = fragment->data;
@@ -2269,6 +2859,8 @@ get_fragment_content(svn_string_t **cont
         if (representation->delta_base)
           if (representation->delta_base->dir)
             {
+              /* if the base happens to be a directory, reconstruct the
+               * full text and represent it as PLAIN rep. */
               SVN_ERR(get_combined_window(&text, fs, representation, pool));
               representation->target.size = text->len;
 
@@ -2279,11 +2871,12 @@ get_fragment_content(svn_string_t **cont
               return SVN_NO_ERROR;
             }
           else
+            /* construct a new rep header */
             if (representation->delta_base == fs->null_base)
               header = svn_stringbuf_create("DELTA\n", pool);
             else
               header = svn_stringbuf_createf(pool,
-                                             "DELTA %ld %" APR_UINT64_T_FMT " %" APR_UINT64_T_FMT "\n",
+                                             "DELTA %ld %" APR_SIZE_T_FMT " %" APR_SIZE_T_FMT "\n",
                                              representation->delta_base->revision->revision,
                                              representation->delta_base->target.offset
                                              - representation->delta_base->revision->target.offset,
@@ -2291,6 +2884,8 @@ get_fragment_content(svn_string_t **cont
         else
           header = svn_stringbuf_create("PLAIN\n", pool);
 
+        /* if it exists, the actual delta base is unchanged. Hence, this
+         * rep is unchanged even if it has been deltified. */
         header_size = strchr(revision_content->data +
                              representation->original.offset, '\n') -
                       revision_content->data -
@@ -2304,7 +2899,10 @@ get_fragment_content(svn_string_t **cont
         *content = svn_stringbuf__morph_into_string(header);
         return SVN_NO_ERROR;
 
+      /* directory reps need to be rewritten (and deltified) completely.
+       * As a side-effect, update the MD5 and target content size. */
       case dir_fragment:
+        /* construct new content and update MD5 */
         representation = fragment->data;
         SVN_ERR(get_updated_dir(&revision_content, fs, representation,
                                 pool, pool));
@@ -2315,18 +2913,21 @@ get_fragment_content(svn_string_t **cont
                checksum->digest,
                sizeof(representation->dir->target_md5));
 
+        /* deltify against the base rep if necessary */
         if (representation->delta_base)
           {
             if (representation->delta_base->dir == NULL)
               {
+                /* dummy or non-dir base rep -> self-compress only */
                 header = svn_stringbuf_create("DELTA\n", pool);
                 base_content = svn_string_create_empty(pool);
               }
             else
               {
+                /* deltify against base rep (which is a directory, too)*/
                 representation_t *base_rep = representation->delta_base;
                 header = svn_stringbuf_createf(pool,
-                                               "DELTA %ld %" APR_UINT64_T_FMT " %" APR_UINT64_T_FMT "\n",
+                                               "DELTA %ld %" APR_SIZE_T_FMT " %" APR_SIZE_T_FMT "\n",
                                                base_rep->revision->revision,
                                                base_rep->target.offset - base_rep->revision->target.offset,
                                                base_rep->target.size);
@@ -2334,16 +2935,18 @@ get_fragment_content(svn_string_t **cont
                                         pool, pool));
               }
 
+            /* run deltification and update target content size */
             header_size = header->len;
-            SVN_ERR(diff_stringbufs(header, &representation->dir->size,
-                                    base_content,
+            SVN_ERR(diff_stringbufs(header, base_content,
                                     revision_content, pool));
+            representation->dir->size = revision_content->len;
             representation->target.size = header->len - header_size;
             svn_stringbuf_appendcstr(header, "ENDREP\n");
             *content = svn_stringbuf__morph_into_string(header);
           }
         else
           {
+            /* no delta base (not even a dummy) -> PLAIN rep */
             representation->target.size = revision_content->len;
             representation->dir->size = revision_content->len;
             *content = svn_string_createf(pool, "PLAIN\n%sENDREP\n",
@@ -2352,7 +2955,9 @@ get_fragment_content(svn_string_t **cont
 
         return SVN_NO_ERROR;
 
-      case noderep_fragment:
+      /* construct the new noderev content.  No side-effects.*/
+      case noderev_fragment:
+        /* get the original noderev as string */
         node = fragment->data;
         SVN_ERR(get_content(&revision_content, fs,
                             node->revision->revision, pool));
@@ -2361,6 +2966,7 @@ get_fragment_content(svn_string_t **cont
                                          node->original.size,
                                          pool);
 
+        /* update the values that may have hanged for target */
         update_id(node_rev, "id: ", node);
         update_id(node_rev, "pred: ", node->predecessor);
         update_text(node_rev, "text: ", node->text, pool);
@@ -2375,6 +2981,9 @@ get_fragment_content(svn_string_t **cont
   return SVN_NO_ERROR;
 }
 
+/* In the repository at PATH, restore the original content in case we ran
+ * this reorg tool before.  Use POOL for allocations.
+ */
 static svn_error_t *
 prepare_repo(const char *path, apr_pool_t *pool)
 {
@@ -2385,16 +2994,19 @@ prepare_repo(const char *path, apr_pool_
   const char *revs_path = svn_dirent_join(path, "db/revs", pool);
   const char *old_rep_cache_path = svn_dirent_join(path, "db/rep-cache.db.old", pool);
   const char *rep_cache_path = svn_dirent_join(path, "db/rep-cache.db", pool);
-  
+
+  /* is there a backup? */
   SVN_ERR(svn_io_check_path(old_path, &kind, pool));
   if (kind == svn_node_dir)
     {
+      /* yes, restore the org content from it */
       SVN_ERR(svn_io_remove_dir2(new_path, TRUE, NULL, NULL, pool));
       SVN_ERR(svn_io_file_move(revs_path, new_path, pool));
       SVN_ERR(svn_io_file_move(old_path, revs_path, pool));
       SVN_ERR(svn_io_remove_dir2(new_path, TRUE, NULL, NULL, pool));
     }
 
+  /* same for the rep cache db */
   SVN_ERR(svn_io_check_path(old_rep_cache_path, &kind, pool));
   if (kind == svn_node_file)
     SVN_ERR(svn_io_file_move(old_rep_cache_path, rep_cache_path, pool));
@@ -2402,6 +3014,9 @@ prepare_repo(const char *path, apr_pool_
   return SVN_NO_ERROR;
 }
 
+/* In the repository at PATH, create a backup of the orig content and
+ * replace it with the reorg'ed. Use POOL for allocations.
+ */
 static svn_error_t *
 activate_new_revs(const char *path, apr_pool_t *pool)
 {
@@ -2413,6 +3028,8 @@ activate_new_revs(const char *path, apr_
   const char *old_rep_cache_path = svn_dirent_join(path, "db/rep-cache.db.old", pool);
   const char *rep_cache_path = svn_dirent_join(path, "db/rep-cache.db", pool);
 
+  /* if there is no backup, yet, move the current repo content to the backup
+   * and place it with the new (reorg'ed) data. */
   SVN_ERR(svn_io_check_path(old_path, &kind, pool));
   if (kind == svn_node_none)
     {
@@ -2420,6 +3037,7 @@ activate_new_revs(const char *path, apr_
       SVN_ERR(svn_io_file_move(new_path, revs_path, pool));
     }
 
+  /* same for the rep cache db */
   SVN_ERR(svn_io_check_path(old_rep_cache_path, &kind, pool));
   if (kind == svn_node_none)
     SVN_ERR(svn_io_file_move(rep_cache_path, old_rep_cache_path, pool));
@@ -2427,6 +3045,9 @@ activate_new_revs(const char *path, apr_
   return SVN_NO_ERROR;
 }
 
+/* Write tool usage info text to OSTREAM using PROGNAME as a prefix and
+ * POOL for allocations.
+ */
 static void
 print_usage(svn_stream_t *ostream, const char *progname,
             apr_pool_t *pool)
@@ -2446,6 +3067,7 @@ print_usage(svn_stream_t *ostream, const
      progname));
 }
 
+/* linear control flow */
 int main(int argc, const char *argv[])
 {
   apr_pool_t *pool;

Modified: subversion/branches/wc-collate-path/tools/server-side/svn-backup-dumps.py
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/tools/server-side/svn-backup-dumps.py?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/tools/server-side/svn-backup-dumps.py (original)
+++ subversion/branches/wc-collate-path/tools/server-side/svn-backup-dumps.py Tue Dec  4 15:35:13 2012
@@ -686,7 +686,7 @@ if __name__ == "__main__":
         print("Everything OK.")
         sys.exit(0)
     else:
-        print("An error occured!")
+        print("An error occurred!")
         sys.exit(1)
 
 # vim:et:ts=4:sw=4

Modified: subversion/branches/wc-collate-path/tools/server-side/svnauthz-validate.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/tools/server-side/svnauthz-validate.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/tools/server-side/svnauthz-validate.c (original)
+++ subversion/branches/wc-collate-path/tools/server-side/svnauthz-validate.c Tue Dec  4 15:35:13 2012
@@ -88,10 +88,12 @@ main(int argc, const char **argv)
   /* Repeat svn_cmdline__getopt_init() inline. */
   apr_err = apr_getopt_init(&os, pool, argc, argv);
   if (apr_err)
-    return svn_cmdline_handle_exit_error(
-             svn_error_wrap_apr(apr_err,
-                                ("Error initializing command line arguments")),
-             pool, "svn-rep-sharing-stats: ");
+    {
+       err = svn_error_wrap_apr(apr_err,
+                                ("Error initializing command line arguments"));
+       svn_handle_warning2(stderr, err, "svnauthz-validate: ");
+       return 2;
+    }
 
   os->interleave = 1;
   while (1)
@@ -131,8 +133,14 @@ main(int argc, const char **argv)
     }
 
   /* Grab AUTHZ_FILE from argv. */
-  SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.authz_file, os->argv[os->ind],
-                                      pool));
+  err = svn_utf_cstring_to_utf8(&opts.authz_file, os->argv[os->ind], pool);
+  if (err)
+    {
+      svn_handle_warning2(stderr, err, "svnauthz-validate: ");
+      svn_error_clear(err);
+      return 2;
+    }
+
   opts.authz_file = svn_dirent_internal_style(opts.authz_file, pool);
 
   /* Read the access file and validate it. */



Mime
View raw message