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 2015/10/21 15:32:44 UTC

svn commit: r1709832 - in /subversion/trunk/subversion/libsvn_fs_x: ./ cached_data.c fs.h temp_serializer.c temp_serializer.h transaction.c

Author: stefan2
Date: Wed Oct 21 13:32:44 2015
New Revision: 1709832

URL: http://svn.apache.org/viewvc?rev=1709832&view=rev
Log:
Merge the in-txn directory caching fixes from FSFS to FSX, resolve text
conflicts and use proper svn_fs_x__* identifiers.

This merges revisions r1679920-1679924, 1679926, 1682008 and 1702922 from
FSFS to FSX.

Modified:
    subversion/trunk/subversion/libsvn_fs_x/   (props changed)
    subversion/trunk/subversion/libsvn_fs_x/cached_data.c
    subversion/trunk/subversion/libsvn_fs_x/fs.h
    subversion/trunk/subversion/libsvn_fs_x/temp_serializer.c
    subversion/trunk/subversion/libsvn_fs_x/temp_serializer.h
    subversion/trunk/subversion/libsvn_fs_x/transaction.c

Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Oct 21 13:32:44 2015
@@ -93,5 +93,5 @@
 /subversion/branches/verify-at-commit/subversion/libsvn_fs_x:1462039-1462408
 /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110
 /subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384
-/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1649590,
 1651567,1652068,1652076,1652441,1653608,1654932,1654934,1654937,1655635,1655664,1657525,1657972,1657978,1658482,1659212,1659217,1659314,1659509,1662668,1665318,1665854,1665894,1667090,1667101,1667538,1669743,1669746,1669749,1669945,1670139,1670953,1673170,1673445,1673454,1673685,1673689,1673875,1674165,1674341,1674400,1674404,1674631,1674669,1674673,1675396,1676667,1677431,1678151,1678718,1678725,1679169,1679907,1680347,1681949,1681966,1682076,1682739,1682864,1683311,1683553,1684047,1686232,1686546,1687061,1687064,1688425,1692650,1693886,1694489,1694848,1696171,1696185,1696627-1696628,1696630,1696758,1697372,1697381,1697387,1697393,1697403,1697405,1701017,1702600,1703142,1703237,1703240,1705266,1705638,1705643,1705724,1705730,1705739,1707971-1707973,1707986,1707988-1707989,1708004
+/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1649590,
 1651567,1652068,1652076,1652441,1653608,1654932,1654934,1654937,1655635,1655664,1657525,1657972,1657978,1658482,1659212,1659217,1659314,1659509,1662668,1665318,1665854,1665894,1667090,1667101,1667538,1669743,1669746,1669749,1669945,1670139,1670953,1673170,1673445,1673454,1673685,1673689,1673875,1674165,1674341,1674400,1674404,1674631,1674669,1674673,1675396,1676667,1677431,1678151,1678718,1678725,1679169,1679907,1679920-1679924,1679926,1680347,1681949,1681966,1682008,1682076,1682739,1682864,1683311,1683553,1684047,1686232,1686546,1687061,1687064,1688425,1692650,1693886,1694489,1694848,1696171,1696185,1696627-1696628,1696630,1696758,1697372,1697381,1697387,1697393,1697403,1697405,1701017,1702600,1702922,1703142,1703237,1703240,1705266,1705638,1705643,1705724,1705730,1705739,1707971-1707973,1707986,1707988-1707989,1708004
 /subversion/trunk/subversion/libsvn_fs_x:1414756-1509914

Modified: subversion/trunk/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/cached_data.c?rev=1709832&r1=1709831&r2=1709832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/cached_data.c Wed Oct 21 13:32:44 2015
@@ -2472,11 +2472,42 @@ read_dir_entries(apr_array_header_t *ent
   return SVN_NO_ERROR;
 }
 
-/* Fetch the contents of a directory into ENTRIES.  Values are stored
+/* For directory NODEREV in FS, return the *FILESIZE of its in-txn
+ * representation.  If the directory representation is comitted data,
+ * set *FILESIZE to SVN_INVALID_FILESIZE. Use SCRATCH_POOL for temporaries.
+ */
+static svn_error_t *
+get_txn_dir_info(svn_filesize_t *filesize,
+                 svn_fs_t *fs,
+                 svn_fs_x__noderev_t *noderev,
+                 apr_pool_t *scratch_pool)
+{
+  if (noderev->data_rep
+      && ! svn_fs_x__is_revision(noderev->data_rep->id.change_set))
+    {
+      const svn_io_dirent2_t *dirent;
+      const char *filename;
+
+      filename = svn_fs_x__path_txn_node_children(fs, &noderev->noderev_id,
+                                                  scratch_pool, scratch_pool);
+
+      SVN_ERR(svn_io_stat_dirent2(&dirent, filename, FALSE, FALSE,
+                                  scratch_pool, scratch_pool));
+      *filesize = dirent->filesize;
+    }
+  else
+    {
+      *filesize = SVN_INVALID_FILESIZE;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Fetch the contents of a directory into DIR.  Values are stored
    as filename to string mappings; further conversion is necessary to
    convert them into svn_fs_x__dirent_t values. */
 static svn_error_t *
-get_dir_contents(apr_array_header_t **entries,
+get_dir_contents(svn_fs_x__dir_data_t *dir,
                  svn_fs_t *fs,
                  svn_fs_x__noderev_t *noderev,
                  apr_pool_t *result_pool,
@@ -2485,20 +2516,32 @@ get_dir_contents(apr_array_header_t **en
   svn_stream_t *contents;
   const svn_fs_x__id_t *id = &noderev->noderev_id;
 
-  *entries = apr_array_make(result_pool, 16, sizeof(svn_fs_x__dirent_t *));
+  /* Initialize the result. */
+  dir->entries = apr_array_make(result_pool, 16, sizeof(svn_fs_x__dirent_t *));
+  dir->txn_filesize = SVN_INVALID_FILESIZE;
+
+  /* Read dir contents - unless there is none in which case we are done. */
   if (noderev->data_rep
       && ! svn_fs_x__is_revision(noderev->data_rep->id.change_set))
     {
-      const char *filename
-        = svn_fs_x__path_txn_node_children(fs, id, scratch_pool,
-                                           scratch_pool);
+      /* Get location & current size of the directory representation. */
+      const char *filename;
+      apr_file_t *file;
+
+      filename = svn_fs_x__path_txn_node_children(fs, id, scratch_pool,
+                                                  scratch_pool);
 
       /* The representation is mutable.  Read the old directory
          contents from the mutable children file, followed by the
          changes we've made in this transaction. */
-      SVN_ERR(svn_stream_open_readonly(&contents, filename, scratch_pool,
-                                       scratch_pool));
-      SVN_ERR(read_dir_entries(*entries, contents, TRUE, id,
+      SVN_ERR(svn_io_file_open(&file, filename, APR_READ | APR_BUFFERED,
+                               APR_OS_DEFAULT, scratch_pool));
+
+      /* Obtain txn children file size. */
+      SVN_ERR(svn_io_file_size_get(&dir->txn_filesize, file, scratch_pool));
+
+      contents = svn_stream_from_aprfile2(file, FALSE, scratch_pool);
+      SVN_ERR(read_dir_entries(dir->entries, contents, TRUE, id,
                                result_pool, scratch_pool));
       SVN_ERR(svn_stream_close(contents));
     }
@@ -2518,7 +2561,7 @@ get_dir_contents(apr_array_header_t **en
 
       /* de-serialize hash */
       contents = svn_stream_from_stringbuf(text, scratch_pool);
-      SVN_ERR(read_dir_entries(*entries, contents, FALSE,  id,
+      SVN_ERR(read_dir_entries(dir->entries, contents, FALSE, id,
                                result_pool, scratch_pool));
     }
 
@@ -2568,22 +2611,35 @@ svn_fs_x__rep_contents_dir(apr_array_hea
                            apr_pool_t *scratch_pool)
 {
   svn_fs_x__id_t key;
+  svn_fs_x__dir_data_t *dir;
 
   /* find the cache we may use */
   svn_cache__t *cache = locate_dir_cache(fs, &key, noderev);
   svn_boolean_t found;
 
-  SVN_ERR(svn_cache__get((void **)entries_p, &found, cache, &key,
-                         result_pool));
+  SVN_ERR(svn_cache__get((void **)&dir, &found, cache, &key, result_pool));
   if (found)
-    return SVN_NO_ERROR;
+    {
+      /* Verify that the cached dir info is not stale
+       * (no-op for committed data). */
+      svn_filesize_t filesize;
+      SVN_ERR(get_txn_dir_info(&filesize, fs, noderev, scratch_pool));
+
+      if (filesize == dir->txn_filesize)
+        {
+          /* Still valid. Done. */
+          *entries_p = dir->entries;
+          return SVN_NO_ERROR;
+        }
+    }
 
   /* Read in the directory contents. */
-  SVN_ERR(get_dir_contents(entries_p, fs, noderev, result_pool,
-                           scratch_pool));
+  dir = apr_pcalloc(scratch_pool, sizeof(*dir));
+  SVN_ERR(get_dir_contents(dir, fs, noderev, result_pool, scratch_pool));
+  *entries_p = dir->entries;
 
   /* Update the cache, if we are to use one. */
-  SVN_ERR(svn_cache__set(cache, &key, *entries_p, scratch_pool));
+  SVN_ERR(svn_cache__set(cache, &key, dir, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -2613,10 +2669,15 @@ svn_fs_x__rep_contents_dir_entry(svn_fs_
   svn_fs_x__id_t key;
   svn_cache__t *cache = locate_dir_cache(fs, &key, noderev);
   svn_fs_x__ede_baton_t baton;
+
+  svn_filesize_t filesize;
+  SVN_ERR(get_txn_dir_info(&filesize, fs, noderev, scratch_pool));
+
+   /* Cache lookup. */
   baton.hint = *hint;
   baton.name = name;
+  baton.txn_filesize = filesize;
 
-  /* Cache lookup. */
   SVN_ERR(svn_cache__get_partial((void **)dirent,
                                  &found,
                                  cache,

Modified: subversion/trunk/subversion/libsvn_fs_x/fs.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs.h?rev=1709832&r1=1709831&r2=1709832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs.h Wed Oct 21 13:32:44 2015
@@ -552,6 +552,18 @@ typedef struct svn_fs_x__change_t
   svn_tristate_t mergeinfo_mod;
 } svn_fs_x__change_t;
 
+
+/*** Directory (only used at the cache interface) ***/
+typedef struct svn_fs_x__dir_data_t
+{
+  /* Contents, i.e. all directory entries, sorted by name. */
+  apr_array_header_t *entries;
+
+  /* SVN_INVALID_FILESIZE for committed data, otherwise the length of the
+   * in-txn on-disk representation of that directory. */
+  svn_filesize_t txn_filesize;
+} svn_fs_x__dir_data_t;
+
 
 #ifdef __cplusplus
 }

Modified: subversion/trunk/subversion/libsvn_fs_x/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/temp_serializer.c?rev=1709832&r1=1709831&r2=1709832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/temp_serializer.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/temp_serializer.c Wed Oct 21 13:32:44 2015
@@ -190,6 +190,10 @@ typedef struct dir_data_t
    * (it's int because the directory is an APR array) */
   int count;
 
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown (i.e. committed data). */
+  svn_filesize_t txn_filesize;
+
   /* number of unused dir entry buckets in the index */
   apr_size_t over_provision;
 
@@ -234,18 +238,19 @@ serialize_dir_entry(svn_temp_serializer_
   svn_temp_serializer__pop(context);
 }
 
-/* Utility function to serialize the ENTRIES into a new serialization
+/* Utility function to serialize the DIR into a new serialization
  * context to be returned.
  *
  * Temporary allocation will be made form SCRATCH_POOL.
  */
 static svn_temp_serializer__context_t *
-serialize_dir(apr_array_header_t *entries,
+serialize_dir(svn_fs_x__dir_data_t *dir,
               apr_pool_t *scratch_pool)
 {
   dir_data_t dir_data;
   int i = 0;
   svn_temp_serializer__context_t *context;
+  apr_array_header_t *entries = dir->entries;
 
   /* calculate sizes */
   int count = entries->nelts;
@@ -256,6 +261,7 @@ serialize_dir(apr_array_header_t *entrie
 
   /* copy the hash entries to an auxiliary struct of known layout */
   dir_data.count = count;
+  dir_data.txn_filesize = dir->txn_filesize;
   dir_data.over_provision = over_provision;
   dir_data.operations = 0;
   dir_data.entries = apr_palloc(scratch_pool, entries_len);
@@ -292,26 +298,32 @@ serialize_dir(apr_array_header_t *entrie
   return context;
 }
 
-/* Utility function to reconstruct a dir entries array from serialized data
+/* Utility function to reconstruct a dir entries struct from serialized data
  * in BUFFER and DIR_DATA. Allocation will be made form RESULT_POOL.
  */
-static apr_array_header_t *
+static svn_fs_x__dir_data_t *
 deserialize_dir(void *buffer,
                 dir_data_t *dir_data,
                 apr_pool_t *result_pool)
 {
-  apr_array_header_t *result = apr_array_make(result_pool, dir_data->count,
-                                              sizeof(svn_fs_x__dirent_t *));
+  svn_fs_x__dir_data_t *result;
   apr_size_t i;
   apr_size_t count;
   svn_fs_x__dirent_t *entry;
   svn_fs_x__dirent_t **entries;
 
+  /* Construct empty directory object. */
+  result = apr_pcalloc(result_pool, sizeof(*result));
+  result->entries
+    = apr_array_make(result_pool, dir_data->count,
+                     sizeof(svn_fs_x__dirent_t *));
+  result->txn_filesize = dir_data->txn_filesize;
+
   /* resolve the reference to the entries array */
   svn_temp_deserializer__resolve(buffer, (void **)&dir_data->entries);
   entries = dir_data->entries;
 
-  /* fixup the references within each entry and add it to the hash */
+  /* fixup the references within each entry and add it to the RESULT */
   for (i = 0, count = dir_data->count; i < count; ++i)
     {
       svn_temp_deserializer__resolve(entries, (void **)&entries[i]);
@@ -321,7 +333,7 @@ deserialize_dir(void *buffer,
       svn_temp_deserializer__resolve(entry, (void **)&entry->name);
 
       /* add the entry to the hash */
-      APR_ARRAY_PUSH(result, svn_fs_x__dirent_t *) = entry;
+      APR_ARRAY_PUSH(result->entries, svn_fs_x__dirent_t *) = entry;
     }
 
   /* return the now complete hash */
@@ -684,7 +696,7 @@ svn_fs_x__serialize_dir_entries(void **d
                                 void *in,
                                 apr_pool_t *pool)
 {
-  apr_array_header_t *dir = in;
+  svn_fs_x__dir_data_t *dir = in;
 
   /* serialize the dir content into a new serialization context
    * and return the serialized data */
@@ -723,6 +735,20 @@ svn_fs_x__get_sharded_offset(void **out,
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_x__extract_dir_filesize(void **out,
+                               const void *data,
+                               apr_size_t data_len,
+                               void *baton,
+                               apr_pool_t *pool)
+{
+  const dir_data_t *dir_data = data;
+
+  *(svn_filesize_t *)out = dir_data->txn_filesize;
+
+  return SVN_NO_ERROR;
+}
+
 /* Utility function that returns the lowest index of the first entry in
  * *ENTRIES that points to a dir entry with a name equal or larger than NAME.
  * If an exact match has been found, *FOUND will be set to TRUE. COUNT is
@@ -832,8 +858,9 @@ svn_fs_x__extract_dir_entry(void **out,
   if (found)
     b->hint = pos;
 
-  /* de-serialize that entry or return NULL, if no match has been found */
-  if (found)
+  /* de-serialize that entry or return NULL, if no match has been found.
+   * Be sure to check that the directory contents is still up-to-date. */
+  if (found && dir_data->txn_filesize == b->txn_filesize)
     {
       const svn_fs_x__dirent_t *source =
           svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]);
@@ -867,32 +894,34 @@ slowly_replace_dir_entry(void **data,
 {
   replace_baton_t *replace_baton = (replace_baton_t *)baton;
   dir_data_t *dir_data = (dir_data_t *)*data;
-  apr_array_header_t *dir;
+  svn_fs_x__dir_data_t *dir;
   int idx = -1;
   svn_fs_x__dirent_t *entry;
+  apr_array_header_t *entries;
 
   SVN_ERR(svn_fs_x__deserialize_dir_entries((void **)&dir,
                                             *data,
                                             dir_data->len,
                                             pool));
 
-  entry = svn_fs_x__find_dir_entry(dir, replace_baton->name, &idx);
+  entries = dir->entries;
+  entry = svn_fs_x__find_dir_entry(entries, replace_baton->name, &idx);
 
   /* Replacement or removal? */
   if (replace_baton->new_entry)
     {
       /* Replace ENTRY with / insert the NEW_ENTRY */
       if (entry)
-        APR_ARRAY_IDX(dir, idx, svn_fs_x__dirent_t *)
+        APR_ARRAY_IDX(entries, idx, svn_fs_x__dirent_t *)
           = replace_baton->new_entry;
       else
-        svn_sort__array_insert(dir, &replace_baton->new_entry, idx);
+        svn_sort__array_insert(entries, &replace_baton->new_entry, idx);
     }
   else
     {
       /* Remove the old ENTRY. */
       if (entry)
-        svn_sort__array_delete(dir, idx, 1);
+        svn_sort__array_delete(entries, idx, 1);
     }
 
   return svn_fs_x__serialize_dir_entries(data, data_len, dir, pool);
@@ -914,6 +943,12 @@ svn_fs_x__replace_dir_entry(void **data,
 
   svn_temp_serializer__context_t *context;
 
+  /* update the cached file length info.
+   * Because we are writing to the cache, it is fair to assume that the
+   * caller made sure that the current contents is consistent with the
+   * previous state of the directory file. */
+  dir_data->txn_filesize = replace_baton->txn_filesize;
+
   /* after quite a number of operations, let's re-pack everything.
    * This is to limit the number of wasted space as we cannot overwrite
    * existing data but must always append. */

Modified: subversion/trunk/subversion/libsvn_fs_x/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/temp_serializer.h?rev=1709832&r1=1709831&r2=1709832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/temp_serializer.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/temp_serializer.h Wed Oct 21 13:32:44 2015
@@ -129,7 +129,7 @@ svn_fs_x__deserialize_node_revision(void
                                     apr_pool_t *result_pool);
 
 /**
- * Implements #svn_cache__serialize_func_t for a directory contents array
+ * Implements #svn_cache__serialize_func_t for a #svn_fs_x__dir_data_t
  */
 svn_error_t *
 svn_fs_x__serialize_dir_entries(void **data,
@@ -138,7 +138,7 @@ svn_fs_x__serialize_dir_entries(void **d
                                 apr_pool_t *pool);
 
 /**
- * Implements #svn_cache__deserialize_func_t for a directory contents array
+ * Implements #svn_cache__deserialize_func_t for a #svn_fs_x__dir_data_t
  */
 svn_error_t *
 svn_fs_x__deserialize_dir_entries(void **out,
@@ -158,6 +158,18 @@ svn_fs_x__get_sharded_offset(void **out,
                              apr_pool_t *pool);
 
 /**
+ * Implements #svn_cache__partial_getter_func_t.
+ * Set (svn_filesize_t) @a *out to the filesize info stored with the
+ * serialized directory in @a data of @a data_len.  @a baton is unused.
+ */
+svn_error_t *
+svn_fs_x__extract_dir_filesize(void **out,
+                               const void *data,
+                               apr_size_t data_len,
+                               void *baton,
+                               apr_pool_t *pool);
+
+/**
  * Baton type to be used with svn_fs_x__extract_dir_entry. */
 typedef struct svn_fs_x__ede_baton_t
 {
@@ -166,12 +178,18 @@ typedef struct svn_fs_x__ede_baton_t
 
   /* Lookup hint [in / out] */
   apr_size_t hint;
+
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown. */
+  svn_filesize_t txn_filesize;
 } svn_fs_x__ede_baton_t;
 
 /**
  * Implements #svn_cache__partial_getter_func_t for a single
  * #svn_fs_x__dirent_t within a serialized directory contents hash,
- * identified by its name (given in @a svn_fs_x__ede_baton_t @a *baton).
+ * identified by its name (in (svn_fs_x__ede_baton_t *) @a *baton).
+ * If the filesize specified in the baton does not match the cached
+ * value for this directory, @a *out will be NULL as well.
  */
 svn_error_t *
 svn_fs_x__extract_dir_entry(void **out,
@@ -184,7 +202,10 @@ svn_fs_x__extract_dir_entry(void **out,
  * Describes the change to be done to a directory: Set the entry
  * identify by @a name to the value @a new_entry. If the latter is
  * @c NULL, the entry shall be removed if it exists. Otherwise it
- * will be replaced or automatically added, respectively.
+ * will be replaced or automatically added, respectively.  The
+ * @a filesize allows readers to identify stale cache data (e.g.
+ * due to concurrent access to txns); writers use it to update the
+ * cached file size info.
  */
 typedef struct replace_baton_t
 {
@@ -193,6 +214,10 @@ typedef struct replace_baton_t
 
   /** directory entry to insert instead */
   svn_fs_x__dirent_t *new_entry;
+
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown. */
+  svn_filesize_t txn_filesize;
 } replace_baton_t;
 
 /**

Modified: subversion/trunk/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/transaction.c?rev=1709832&r1=1709831&r2=1709832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/transaction.c Wed Oct 21 13:32:44 2015
@@ -1792,6 +1792,7 @@ svn_fs_x__set_entry(svn_fs_t *fs,
                                        scratch_pool, scratch_pool);
   apr_file_t *file;
   svn_stream_t *out;
+  svn_filesize_t filesize;
   svn_fs_x__data_t *ffd = fs->fsap_data;
   apr_pool_t *subpool = svn_pool_create(scratch_pool);
 
@@ -1828,20 +1829,73 @@ svn_fs_x__set_entry(svn_fs_t *fs,
     }
   else
     {
+      const svn_fs_x__id_t *key = &(parent_noderev->noderev_id);
+      svn_boolean_t found;
+      svn_filesize_t cached_filesize;
+
       /* The directory rep is already mutable, so just open it for append. */
       SVN_ERR(svn_io_file_open(&file, filename, APR_WRITE | APR_APPEND,
-                               APR_OS_DEFAULT, scratch_pool));
-      out = svn_stream_from_aprfile2(file, TRUE, scratch_pool);
+                               APR_OS_DEFAULT, subpool));
+      out = svn_stream_from_aprfile2(file, TRUE, subpool);
+
+      /* If the cache contents is stale, drop it.
+       *
+       * Note that the directory file is append-only, i.e. if the size
+       * did not change, the contents didn't either. */
+
+      /* Get the file size that corresponds to the cached contents
+       * (if any). */
+      SVN_ERR(svn_cache__get_partial((void **)&cached_filesize, &found,
+                                     ffd->dir_cache, key,
+                                     svn_fs_x__extract_dir_filesize,
+                                     NULL, subpool));
+
+      /* File size info still matches?
+       * If not, we need to drop the cache entry. */
+      if (found)
+        {
+          SVN_ERR(svn_io_file_size_get(&filesize, file, subpool));
+
+          if (cached_filesize != filesize)
+            SVN_ERR(svn_cache__set(ffd->dir_cache, key, NULL, subpool));
+        }
+    }
+
+  /* Append an incremental hash entry for the entry change. */
+  if (id)
+    {
+      svn_fs_x__dirent_t entry;
+      entry.name = name;
+      entry.id = *id;
+      entry.kind = kind;
+
+      SVN_ERR(unparse_dir_entry(&entry, out, subpool));
+    }
+  else
+    {
+      SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n",
+                                strlen(name), name));
     }
 
+  /* Flush APR buffers. */
+  SVN_ERR(svn_io_file_flush(file, subpool));
+
+  /* Obtain final file size to update txn_dir_cache. */
+  SVN_ERR(svn_io_file_size_get(&filesize, file, subpool));
+
+  /* Close file. */
+  SVN_ERR(svn_io_file_close(file, subpool));
+  svn_pool_clear(subpool);
+
   /* update directory cache */
     {
-      /* build parameters: (name, new entry) pair */
+      /* build parameters: name, new entry, new file size  */
       const svn_fs_x__id_t *key = &(parent_noderev->noderev_id);
       replace_baton_t baton;
 
       baton.name = name;
       baton.new_entry = NULL;
+      baton.txn_filesize = filesize;
 
       if (id)
         {
@@ -1856,25 +1910,7 @@ svn_fs_x__set_entry(svn_fs_t *fs,
                                      svn_fs_x__replace_dir_entry, &baton,
                                      subpool));
     }
-  svn_pool_clear(subpool);
 
-  /* Append an incremental hash entry for the entry change. */
-  if (id)
-    {
-      svn_fs_x__dirent_t entry;
-      entry.name = name;
-      entry.id = *id;
-      entry.kind = kind;
-
-      SVN_ERR(unparse_dir_entry(&entry, out, subpool));
-    }
-  else
-    {
-      SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n",
-                                strlen(name), name));
-    }
-
-  SVN_ERR(svn_io_file_close(file, subpool));
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }