You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/03/23 22:48:47 UTC

svn commit: r1580623 - in /subversion/trunk/subversion: include/private/svn_delta_private.h libsvn_delta/svndiff.c libsvn_fs_fs/cached_data.c libsvn_fs_fs/caching.c libsvn_fs_fs/fs.h libsvn_fs_fs/temp_serializer.c libsvn_fs_fs/temp_serializer.h

Author: stefan2
Date: Sun Mar 23 21:48:46 2014
New Revision: 1580623

URL: http://svn.apache.org/r1580623
Log:
Reduce the CPU overhead caused by the FSFS format 7 block read feature.
Instead of parsing txdelta windows every time we encounter them, initially
cache their raw form and parse it only when the window gets accessed for
the first time.

* subversion/libsvn_fs_fs/temp_serializer.h
  (svn_fs_fs__raw_cached_window_t): Declare a data type for cached raw /
                                    unparsed txdelta windows.
  (svn_fs_fs__serialize_raw_window,
   svn_fs_fs__deserialize_raw_window): Declare the corresponding
                                       (de-)serialization functions.

* subversion/libsvn_fs_fs/temp_serializer.c
  (svn_fs_fs__serialize_raw_window,
   svn_fs_fs__deserialize_raw_window): Implement the new (de-)serialization
                                       functions.

* subversion/include/private/svn_delta_private.h
  (svn_txdelta__read_raw_window_len): New private API to extract the minimum
                                      information we need to read a raw window.

* subversion/libsvn_delta/svndiff.c
  (read_one_size): Add a parameter to ultimately count the number of header
                   bytes we read.
  (read_window_header): Return the number of parsed header bytes as well.
  (svn_txdelta_read_svndiff_window,
   svn_txdelta_skip_svndiff_window): Update callers.
  (svn_txdelta__read_raw_window_len): Implement as a variation of
                                      svn_txdelta_skip_svndiff_window.

* subversion/libsvn_fs_fs/fs.h
  (fs_fs_data_t): Add the new cache instance.

* subversion/libsvn_fs_fs/caching.c
  (svn_fs_fs__initialize_caches): Initialize the new cache instance.

* subversion/libsvn_fs_fs/cached_data.c
  (rep_state_t): We have yet another delta window cache.
  (create_rep_state_body): Initialize that new member.
  (parse_raw_window): A new cache getter that converts the cached
                      raw txdelta window into a parsed one.
  (get_cached_window): If we can't find the window in its parsed
                       form, try to find the raw version in our
                       cache and parse that.
  (read_delta_window): Check that both window caches are available,
                       even though we should always either have
                       all or neither of them.
  (init_rep_state): Update init code similarly to parse_raw_window.
  (get_window_header): Replaced by ...
  (get_txdelta_window_end): ... this function, which returns only the
                            end offset of the respective window.
  (get_raw_window_end): New function that does the same for raw windows.
  (cache_windows): Rewrite as checking both caches before reading data
                   and only populating the raw window cache.
  (block_read_windows): Make sure we attempt to cache delta windows
                        only if the we have those caches.

Modified:
    subversion/trunk/subversion/include/private/svn_delta_private.h
    subversion/trunk/subversion/libsvn_delta/svndiff.c
    subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
    subversion/trunk/subversion/libsvn_fs_fs/caching.c
    subversion/trunk/subversion/libsvn_fs_fs/fs.h
    subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c
    subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h

Modified: subversion/trunk/subversion/include/private/svn_delta_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_delta_private.h?rev=1580623&r1=1580622&r2=1580623&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_delta_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_delta_private.h Sun Mar 23 21:48:46 2014
@@ -101,6 +101,12 @@ svn_delta__delta_from_editor(const svn_d
                              struct svn_delta__extra_baton *exb,
                              apr_pool_t *pool);
 
+/** Read the txdelta window header from @a stream and return the total
+    length of the unparsed window data in @a *window_len. */
+svn_error_t *
+svn_txdelta__read_raw_window_len(apr_size_t *window_len,
+                                 svn_stream_t *stream,
+                                 apr_pool_t *pool);
 
 #ifdef __cplusplus
 }

Modified: subversion/trunk/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_delta/svndiff.c?rev=1580623&r1=1580622&r2=1580623&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/trunk/subversion/libsvn_delta/svndiff.c Sun Mar 23 21:48:46 2014
@@ -788,9 +788,12 @@ read_one_byte(unsigned char *byte, svn_s
   return SVN_NO_ERROR;
 }
 
-/* Read and decode one integer from STREAM into *SIZE. */
+/* Read and decode one integer from STREAM into *SIZE. 
+   Increment *BYTE_COUNTER by the number of chars we have read. */
 static svn_error_t *
-read_one_size(apr_size_t *size, svn_stream_t *stream)
+read_one_size(apr_size_t *size,
+              apr_size_t *byte_counter,
+              svn_stream_t *stream)
 {
   unsigned char c;
 
@@ -798,6 +801,7 @@ read_one_size(apr_size_t *size, svn_stre
   while (1)
     {
       SVN_ERR(read_one_byte(&c, stream));
+      ++*byte_counter;
       *size = (*size << 7) | (c & 0x7f);
       if (!(c & 0x80))
         break;
@@ -809,25 +813,28 @@ read_one_size(apr_size_t *size, svn_stre
 static svn_error_t *
 read_window_header(svn_stream_t *stream, svn_filesize_t *sview_offset,
                    apr_size_t *sview_len, apr_size_t *tview_len,
-                   apr_size_t *inslen, apr_size_t *newlen)
+                   apr_size_t *inslen, apr_size_t *newlen,
+                   apr_size_t *header_len)
 {
   unsigned char c;
 
   /* Read the source view offset by hand, since it's not an apr_size_t. */
+  *header_len = 0;
   *sview_offset = 0;
   while (1)
     {
       SVN_ERR(read_one_byte(&c, stream));
+      ++*header_len;
       *sview_offset = (*sview_offset << 7) | (c & 0x7f);
       if (!(c & 0x80))
         break;
     }
 
   /* Read the four size fields. */
-  SVN_ERR(read_one_size(sview_len, stream));
-  SVN_ERR(read_one_size(tview_len, stream));
-  SVN_ERR(read_one_size(inslen, stream));
-  SVN_ERR(read_one_size(newlen, stream));
+  SVN_ERR(read_one_size(sview_len, header_len, stream));
+  SVN_ERR(read_one_size(tview_len, header_len, stream));
+  SVN_ERR(read_one_size(inslen, header_len, stream));
+  SVN_ERR(read_one_size(newlen, header_len, stream));
 
   if (*tview_len > SVN_DELTA_WINDOW_SIZE ||
       *sview_len > SVN_DELTA_WINDOW_SIZE ||
@@ -854,11 +861,11 @@ svn_txdelta_read_svndiff_window(svn_txde
                                 apr_pool_t *pool)
 {
   svn_filesize_t sview_offset;
-  apr_size_t sview_len, tview_len, inslen, newlen, len;
+  apr_size_t sview_len, tview_len, inslen, newlen, len, header_len;
   unsigned char *buf;
 
   SVN_ERR(read_window_header(stream, &sview_offset, &sview_len, &tview_len,
-                             &inslen, &newlen));
+                             &inslen, &newlen, &header_len));
   len = inslen + newlen;
   buf = apr_palloc(pool, len);
   SVN_ERR(svn_stream_read_full(stream, (char*)buf, &len));
@@ -878,14 +885,28 @@ svn_txdelta_skip_svndiff_window(apr_file
 {
   svn_stream_t *stream = svn_stream_from_aprfile2(file, TRUE, pool);
   svn_filesize_t sview_offset;
-  apr_size_t sview_len, tview_len, inslen, newlen;
+  apr_size_t sview_len, tview_len, inslen, newlen, header_len;
   apr_off_t offset;
 
   SVN_ERR(read_window_header(stream, &sview_offset, &sview_len, &tview_len,
-                             &inslen, &newlen));
+                             &inslen, &newlen, &header_len));
 
   offset = inslen + newlen;
   return svn_io_file_seek(file, APR_CUR, &offset, pool);
 }
 
+svn_error_t *
+svn_txdelta__read_raw_window_len(apr_size_t *window_len,
+                                 svn_stream_t *stream,
+                                 apr_pool_t *pool)
+{
+  svn_filesize_t sview_offset;
+  apr_size_t sview_len, tview_len, inslen, newlen, header_len;
+
+  SVN_ERR(read_window_header(stream, &sview_offset, &sview_len, &tview_len,
+                             &inslen, &newlen, &header_len));
+
+  *window_len = inslen + newlen + header_len;
+  return SVN_NO_ERROR;
+}
 

Modified: subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/cached_data.c?rev=1580623&r1=1580622&r2=1580623&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/cached_data.c Sun Mar 23 21:48:46 2014
@@ -601,6 +601,8 @@ typedef struct rep_state_t
                     /* shared lazy-open rev/pack file structure */
   shared_file_t *sfile;
                     /* The txdelta window cache to use or NULL. */
+  svn_cache__t *raw_window_cache;
+                    /* Caches raw (unparsed) windows. May be NULL. */
   svn_cache__t *window_cache;
                     /* Caches un-deltified windows. May be NULL. */
   svn_cache__t *combined_cache;
@@ -739,6 +741,7 @@ create_rep_state_body(rep_state_t **rep_
   rs->size = rep->size;
   rs->revision = rep->revision;
   rs->item_index = rep->item_index;
+  rs->raw_window_cache = ffd->raw_window_cache;
   rs->window_cache = ffd->txdelta_window_cache;
   rs->combined_cache = ffd->combined_window_cache;
   rs->ver = -1;
@@ -1061,6 +1064,43 @@ get_window_key(window_cache_key_t *key, 
   return key;
 }
 
+/* Implement svn_cache__partial_getter_func_t for raw txdelta windows.
+ * Parse the raw data and return a svn_fs_fs__txdelta_cached_window_t.
+ */
+static svn_error_t *
+parse_raw_window(void **out,
+                 const void *data,
+                 apr_size_t data_len,
+                 void *baton,
+                 apr_pool_t *result_pool)
+{
+  svn_string_t raw_window;
+  svn_stream_t *stream;
+
+  /* unparsed and parsed window */
+  const svn_fs_fs__raw_cached_window_t *window
+    = (const svn_fs_fs__raw_cached_window_t *)data;
+  svn_fs_fs__txdelta_cached_window_t *result
+    = apr_pcalloc(result_pool, sizeof(*result));
+
+  /* create a read stream taking the raw window as input */
+  raw_window.data = svn_temp_deserializer__ptr(window,
+                                (const void * const *)&window->window.data);
+  raw_window.len = window->window.len;
+  stream = svn_stream_from_string(&raw_window, result_pool);
+
+  /* parse it */
+  SVN_ERR(svn_txdelta_read_svndiff_window(&result->window, stream, 1,
+                                          result_pool));
+
+  /* complete the window and return it */
+  result->end_offset = window->end_offset;
+  *out = result;
+
+  return SVN_NO_ERROR;
+}
+
+
 /* Read the WINDOW_P number CHUNK_INDEX for the representation given in
  * rep state RS from the current FSFS session's cache.  This will be a
  * no-op and IS_CACHED will be set to FALSE if no cache has been given.
@@ -1095,6 +1135,19 @@ get_cached_window(svn_txdelta_window_t *
                              &key,
                              pool));
 
+      /* If we did not find a parsed txdelta window, we might have a raw
+         version of it in our cache.  If so, read, parse and re-cache it. */
+      if (!*is_cached && rs->raw_window_cache)
+        {
+          SVN_ERR(svn_cache__get_partial((void **) &cached_window, is_cached,
+                                         rs->raw_window_cache, &key,
+                                         parse_raw_window, NULL, pool));
+          if (*is_cached)
+            SVN_ERR(svn_cache__set(rs->window_cache, &key, cached_window,
+                                   pool));
+        }
+
+      /* Return cached information. */
       if (*is_cached)
         {
           /* found it. Pass it back to the caller. */
@@ -1358,7 +1411,7 @@ read_delta_window(svn_txdelta_window_t *
   if (   rs->chunk_index == 0
       && SVN_IS_VALID_REVNUM(rs->revision)
       && svn_fs_fs__use_log_addressing(rs->sfile->fs, rs->revision)
-      && rs->window_cache)
+      && rs->raw_window_cache)
     {
       SVN_ERR(block_read(NULL, rs->sfile->fs, rs->revision, rs->item_index,
                          rs->sfile->rfile, pool, pool));
@@ -2435,6 +2488,7 @@ init_rep_state(rep_state_t *rs,
   rs->size = entry->size - rep_header->header_size - 7;
   rs->ver = 1;
   rs->chunk_index = 0;
+  rs->raw_window_cache = ffd->raw_window_cache;
   rs->window_cache = ffd->txdelta_window_cache;
   rs->combined_cache = ffd->combined_window_cache;
 
@@ -2442,18 +2496,35 @@ init_rep_state(rep_state_t *rs,
 }
 
 /* Implement svn_cache__partial_getter_func_t for txdelta windows.
- * Instead of the whole window data, return only the
- * svn_fs_fs__txdelta_cached_window_t wrapper containing the end-offset.
+ * Instead of the whole window data, return only END_OFFSET member.
+ */
+static svn_error_t *
+get_txdelta_window_end(void **out,
+                       const void *data,
+                       apr_size_t data_len,
+                       void *baton,
+                       apr_pool_t *result_pool)
+{
+  const svn_fs_fs__txdelta_cached_window_t *window
+    = (const svn_fs_fs__txdelta_cached_window_t *)data;
+  *(apr_off_t*)out = window->end_offset;
+
+  return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__partial_getter_func_t for raw windows.
+ * Instead of the whole window data, return only END_OFFSET member.
  */
 static svn_error_t *
-get_window_header(void **out,
-                  const void *data,
-                  apr_size_t data_len,
-                  void *baton,
-                  apr_pool_t *result_pool)
+get_raw_window_end(void **out,
+                   const void *data,
+                   apr_size_t data_len,
+                   void *baton,
+                   apr_pool_t *result_pool)
 {
-  *out = apr_pmemdup(result_pool, data,
-                     sizeof(svn_fs_fs__txdelta_cached_window_t));
+  const svn_fs_fs__raw_cached_window_t *window
+    = (const svn_fs_fs__raw_cached_window_t *)data;
+  *(apr_off_t*)out = window->end_offset;
 
   return SVN_NO_ERROR;
 }
@@ -2462,6 +2533,9 @@ get_window_header(void **out,
  * (excluding the delta bases) and put those not already cached into the
  * window caches.  If MAX_OFFSET is not -1, don't read windows that start
  * at or beyond that offset.  Use POOL for temporary allocations.
+ *
+ * This function requires RS->RAW_WINDOW_CACHE and RS->WINDOW_CACHE to
+ * be non-NULL. 
  */
 static svn_error_t *
 cache_windows(svn_fs_t *fs,
@@ -2469,49 +2543,71 @@ cache_windows(svn_fs_t *fs,
               apr_off_t max_offset,
               apr_pool_t *pool)
 {
+  apr_pool_t *iterpool = svn_pool_create(pool);
   while (rs->current < rs->size)
     {
-      svn_fs_fs__txdelta_cached_window_t *cached_window;
+      apr_off_t end_offset;
       svn_boolean_t found = FALSE;
+      window_cache_key_t key = { 0 };
+
+      svn_pool_clear(iterpool);
 
       if (max_offset != -1 && rs->start + rs->current >= max_offset)
-        return SVN_NO_ERROR;
+        {
+          svn_pool_destroy(iterpool);
+          return SVN_NO_ERROR;
+        }
 
       /* We don't need to read the data again if it is already in cache.
+       * It might be cached as either raw or parsed window.
        */
-      if (rs->window_cache)
-        {
-          window_cache_key_t key = { 0 };
-          SVN_ERR(svn_cache__get_partial((void **) &cached_window, &found,
-                                         rs->window_cache,
-                                         get_window_key(&key, rs),
-                                         get_window_header, NULL, pool));
-        }
+      SVN_ERR(svn_cache__get_partial((void **) &end_offset, &found,
+                                     rs->raw_window_cache,
+                                     get_window_key(&key, rs),
+                                     get_raw_window_end, NULL,
+                                     iterpool));
+      if (! found)
+        SVN_ERR(svn_cache__get_partial((void **) &end_offset, &found,
+                                       rs->window_cache, &key,
+                                       get_txdelta_window_end, NULL,
+                                       iterpool));
 
       if (found)
         {
-          /* Skip this window; we already have it. */
-          rs->current = cached_window->end_offset;
+          rs->current = end_offset;
         }
       else
         {
           /* Read, decode and cache the window. */
-          svn_txdelta_window_t *window;
+          svn_fs_fs__raw_cached_window_t window;
           apr_off_t start_offset = rs->start + rs->current;
-          apr_off_t end_offset;
+          apr_size_t window_len;
+          char *buf;
 
           /* navigate to the current window */
-          SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, pool));
-          SVN_ERR(svn_txdelta_read_svndiff_window(&window,
-                                                  rs->sfile->rfile->stream,
-                                                  rs->ver, pool));
-
-          /* determine on-disk window size */
-          SVN_ERR(get_file_offset(&end_offset, rs, pool));
-          rs->current = end_offset - rs->start;
+          SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, iterpool));
+          SVN_ERR(svn_txdelta__read_raw_window_len(&window_len,
+                                                   rs->sfile->rfile->stream,
+                                                   iterpool));
+
+          /* Read the raw window. */
+          buf = apr_palloc(iterpool, window_len + 1);
+          SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, iterpool));
+          SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, buf,
+                                         window_len, NULL, NULL, iterpool));
+          buf[window_len] = 0;
+
+          /* update relative offset in representation */
+          rs->current += window_len;
+
+          /* Construct the cachable raw window object. */
+          window.end_offset = rs->current;
+          window.window.len = window_len;
+          window.window.data = buf;
 
           /* cache the window now */
-          SVN_ERR(set_cached_window(window, rs, pool));
+          SVN_ERR(svn_cache__set(rs->raw_window_cache, &key, &window,
+                                 iterpool));
         }
 
       if (rs->current > rs->size)
@@ -2522,6 +2618,7 @@ cache_windows(svn_fs_t *fs,
       rs->chunk_index++;
     }
 
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -2545,7 +2642,7 @@ block_read_windows(svn_fs_fs__rep_header
   window_cache_key_t key = { 0 };
 
   if (   (rep_header->type != svn_fs_fs__rep_plain
-          && !ffd->txdelta_window_cache)
+          && (!ffd->txdelta_window_cache || !ffd->raw_window_cache))
       || (rep_header->type == svn_fs_fs__rep_plain
           && !ffd->combined_window_cache))
     return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/caching.c?rev=1580623&r1=1580622&r2=1580623&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/caching.c Sun Mar 23 21:48:46 2014
@@ -622,6 +622,20 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   /* if enabled, cache text deltas and their combinations */
   if (cache_txdeltas)
     {
+      SVN_ERR(create_cache(&(ffd->raw_window_cache),
+                           NULL,
+                           membuffer,
+                           0, 0, /* Do not use inprocess cache */
+                           svn_fs_fs__serialize_raw_window,
+                           svn_fs_fs__deserialize_raw_window,
+                           sizeof(window_cache_key_t),
+                           apr_pstrcat(pool, prefix, "RAW_WINDOW",
+                                       SVN_VA_NULL),
+                           SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
+                           fs,
+                           no_handler,
+                           fs->pool));
+
       SVN_ERR(create_cache(&(ffd->txdelta_window_cache),
                            NULL,
                            membuffer,

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.h?rev=1580623&r1=1580622&r2=1580623&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.h Sun Mar 23 21:48:46 2014
@@ -366,6 +366,10 @@ typedef struct fs_fs_data_t
      respective pack file. */
   svn_cache__t *packed_offset_cache;
 
+  /* Cache for svn_fs_fs__raw_cached_window_t objects; the key is
+     window_cache_key_t. */
+  svn_cache__t *raw_window_cache;
+
   /* Cache for txdelta_window_t objects; the key is window_cache_key_t */
   svn_cache__t *txdelta_window_cache;
 

Modified: subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c?rev=1580623&r1=1580622&r2=1580623&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c Sun Mar 23 21:48:46 2014
@@ -341,6 +341,55 @@ svn_fs_fs__noderev_deserialize(void *buf
   svn_temp_deserializer__resolve(noderev, (void **)&noderev->created_path);
 }
 
+svn_error_t *
+svn_fs_fs__serialize_raw_window(void **buffer,
+                                apr_size_t *buffer_size,
+                                void *item,
+                                apr_pool_t *pool)
+{
+  svn_fs_fs__raw_cached_window_t *window = item;
+  svn_stringbuf_t *serialized;
+
+  /* initialize the serialization process and allocate a buffer large
+   * enough to do prevent re-allocations. */
+  svn_temp_serializer__context_t *context =
+      svn_temp_serializer__init(window,
+                                sizeof(*window),
+                                sizeof(*window) + window->window.len + 16,
+                                pool);
+
+  /* serialize the sub-structure(s) */
+  svn_temp_serializer__add_leaf(context,
+                                (const void * const *)&window->window.data,
+                                window->window.len + 1);
+
+  /* return the serialized result */
+  serialized = svn_temp_serializer__get(context);
+
+  *buffer = serialized->data;
+  *buffer_size = serialized->len;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__deserialize_raw_window(void **item,
+                                  void *buffer,
+                                  apr_size_t buffer_size,
+                                  apr_pool_t *pool)
+{
+  svn_fs_fs__raw_cached_window_t *window =
+      (svn_fs_fs__raw_cached_window_t *)buffer;
+
+  /* pointer reference fixup */
+  svn_temp_deserializer__resolve(window, (void **)&window->window.data);
+
+  /* done */
+  *item = buffer;
+
+  return SVN_NO_ERROR;
+}
+
 
 /* Utility function to serialize COUNT svn_txdelta_op_t objects
  * at OPS in the given serialization CONTEXT.

Modified: subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h?rev=1580623&r1=1580622&r2=1580623&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h Sun Mar 23 21:48:46 2014
@@ -49,6 +49,39 @@ void
 svn_fs_fs__noderev_deserialize(void *buffer,
                                node_revision_t **noderev_p);
 
+
+/**
+ * Adds position information to the the raw window data in WINDOW.
+ */
+typedef struct
+{
+  /* the (unprocessed) txdelta window byte sequence cached / to be cached */
+  svn_string_t window;
+
+  /* the offset within the representation right after reading the window */
+  apr_off_t end_offset;
+} svn_fs_fs__raw_cached_window_t;
+
+/**
+ * Implements #svn_cache__serialize_func_t for
+ * #svn_fs_fs__raw_cached_window_t.
+ */
+svn_error_t *
+svn_fs_fs__serialize_raw_window(void **buffer,
+                                apr_size_t *buffer_size,
+                                void *item,
+                                apr_pool_t *pool);
+
+/**
+ * Implements #svn_cache__deserialize_func_t for
+ * #svn_fs_fs__raw_cached_window_t.
+ */
+svn_error_t *
+svn_fs_fs__deserialize_raw_window(void **item,
+                                  void *buffer,
+                                  apr_size_t buffer_size,
+                                  apr_pool_t *pool);
+
 /**
  * #svn_txdelta_window_t is not sufficient for caching the data it
  * represents because data read process needs auxiliary information.