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;
}