* dag.c (NR_HEADER, NR_PROP_KEY, NR_DATA_KEY, HDR_KIND, HDR_REV,
HDR_FLAGS): New macros. Use them everywhere, instead of unpacking
node revision skels by hand.
* structure: Notes on deltification.
git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/strings-reps-dev@839610 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/subversion/libsvn_fs/dag.c b/subversion/libsvn_fs/dag.c
index c21c0d0..f2e5718 100644
--- a/subversion/libsvn_fs/dag.c
+++ b/subversion/libsvn_fs/dag.c
@@ -31,6 +31,29 @@
#include "validate.h"
+/* Accessor macros. */
+
+
+/* Access the header of a node revision skel. */
+#define NR_HEADER(node_rev) (node_rev->children)
+
+/* Access the property rep key of a node revision skel. */
+#define NR_PROP_KEY(node_rev) (node_rev->children->next)
+
+/* Access the data rep key of a node revision skel. */
+#define NR_DATA_KEY(node_rev) (node_rev->children->next->next)
+
+/* Access the kind skel of a node revision header. */
+#define HDR_KIND(header) (header->children)
+
+/* Access the revision skel of a node revision header. */
+#define HDR_REV(header) (header->children->next)
+
+/* Access the flags skel of a node revision header. */
+#define HDR_FLAGS(header) (header->children->next->next)
+
+
+
/* Initializing a filesystem. */
/* Node types */
@@ -122,11 +145,8 @@
node_is_kind_p (skel_t *node_rev,
const char *kindstr)
{
- /* The first element of the header (which is the first element of
- the node-revision) should be an atom defining the node kind. */
- skel_t *kind = node_rev->children->children;
-
- return svn_fs__matches_atom (kind, kindstr);
+ skel_t *header = NR_HEADER (node_rev);
+ return svn_fs__matches_atom (HDR_KIND (header), kindstr);
}
@@ -136,17 +156,17 @@
static int
node_rev_has_mutable_flag (skel_t *node_content)
{
- /* The node "header" is the first element of a node-revision skel,
- itself a list. */
- skel_t *header = node_content->children;
-
- /* The 3rd element of the header, IF it exists, is the header's
- first `flag'. It could be NULL. */
- skel_t *flag = header->children->next->next;
+ skel_t *header = NR_HEADER (node_content);
+ skel_t *flag = HDR_FLAGS (header);
while (flag)
{
/* Looking for the `mutable' flag, which is itself a list. */
+ /* ### kff todo: note how node revision flags are different from
+ representation flags. A node rev flag is a list of two
+ elements, a rep flag is an atom. We may want to unify this
+ someday... I'm not sure that we're actually using the second
+ element (rev num) of node revision flags anyway. ? */
if (svn_fs__matches_atom (flag->children, "mutable"))
return TRUE;
@@ -194,9 +214,6 @@
}
-/* fooo put stuff here */
-
-
/* Clear NODE's cache of its node revision. */
static void
uncache_node_revision (void *baton)
@@ -393,19 +410,14 @@
skel_t *node_rev,
trail_t *trail)
{
- skel_t *header;
+ skel_t *header = NR_HEADER (node_rev);
- /* The node "header" is the first element of a node-revision skel,
- itself a list. */
- header = node_rev->children;
-
if (header)
{
/* Make sure we're looking at a directory node here */
- if (svn_fs__matches_atom (header->children, "dir"))
+ if (svn_fs__matches_atom (HDR_KIND (header), "dir"))
{
- /* The rep key is the 3rd element of the node rev skel. */
- skel_t *rep_key = header->next->next;
+ skel_t *rep_key = NR_DATA_KEY (node_rev);
skel_t *rep;
const char *key = apr_pstrndup (trail->pool,
rep_key->data,
@@ -546,8 +558,8 @@
SVN_ERR (get_node_revision (&parent_node_rev, parent, trail));
rep_key = apr_pstrndup (trail->pool,
- parent_node_rev->children->next->next->data,
- parent_node_rev->children->next->next->len);
+ (NR_DATA_KEY (parent_node_rev))->data,
+ (NR_DATA_KEY (parent_node_rev))->len);
/* Empty string is allowable, but null is not. */
assert (rep_key != NULL);
@@ -581,8 +593,8 @@
if (strcmp (rep_key, mutable_rep_key) != 0)
{
skel_t *new_node_rev = svn_fs__copy_skel (parent_node_rev, trail->pool);
- new_node_rev->children->next->next->data = mutable_rep_key;
- new_node_rev->children->next->next->len = strlen (mutable_rep_key);
+ (NR_DATA_KEY (new_node_rev))->data = mutable_rep_key;
+ (NR_DATA_KEY (new_node_rev))->len = strlen (mutable_rep_key);
SVN_ERR (set_node_revision (parent, new_node_rev, trail));
}
@@ -846,8 +858,8 @@
/* Go get a fresh NODE-REVISION for this node. */
SVN_ERR (get_node_revision (&node_rev, node, trail));
- /* Get rep_key_skel for properties. */
- rep_key_skel = node_rev->children->next;
+ /* Get key skel for properties. */
+ rep_key_skel = NR_PROP_KEY (node_rev);
/* Get the string associated with the property rep, parsing it as a
skel. */
@@ -902,9 +914,11 @@
/* Go get a fresh NODE-REVISION for this node. */
SVN_ERR (get_node_revision (&node_rev, node, trail));
+
+ /* Get the property rep key. */
orig_rep_key = apr_pstrndup (trail->pool,
- node_rev->children->next->data,
- node_rev->children->next->len);
+ (NR_PROP_KEY (node_rev))->data,
+ (NR_PROP_KEY (node_rev))->len);
/* Get a mutable version of this rep. */
SVN_ERR (svn_fs__get_mutable_rep (&mutable_rep_key, orig_rep_key,
@@ -925,8 +939,8 @@
/* If we made a new rep, record it in the node revision. */
if (strcmp (mutable_rep_key, orig_rep_key) != 0)
{
- node_rev->children->next->data = mutable_rep_key;
- node_rev->children->next->len = strlen (mutable_rep_key);
+ (NR_PROP_KEY (node_rev))->data = mutable_rep_key;
+ (NR_PROP_KEY (node_rev))->len = strlen (mutable_rep_key);
SVN_ERR (svn_fs__put_node_revision (node->fs, node->id,
node_rev, trail));
}
@@ -1171,8 +1185,8 @@
/* Get the key for this node's data representation. */
rep_key = apr_pstrndup (trail->pool,
- parent_node_rev->children->next->next->data,
- parent_node_rev->children->next->next->len);
+ (NR_DATA_KEY (parent_node_rev))->data,
+ (NR_DATA_KEY (parent_node_rev))->len);
/* No REP_KEY means no representation, and no representation means
no data, and no data means no enties...there's nothing here to
@@ -1189,8 +1203,8 @@
if (strcmp (rep_key, mutable_rep_key) != 0)
{
skel_t *new_node_rev = svn_fs__copy_skel (parent_node_rev, trail->pool);
- new_node_rev->children->next->next->data = mutable_rep_key;
- new_node_rev->children->next->next->len = strlen (mutable_rep_key);
+ (NR_DATA_KEY (new_node_rev))->data = mutable_rep_key;
+ (NR_DATA_KEY (new_node_rev))->len = strlen (mutable_rep_key);
SVN_ERR (set_node_revision (parent, new_node_rev, trail));
}
@@ -1309,8 +1323,8 @@
{
const char *prop_rep_key;
prop_rep_key = apr_pstrndup (trail->pool,
- node_rev->children->next->data,
- node_rev->children->next->len);
+ (NR_PROP_KEY (node_rev))->data,
+ (NR_PROP_KEY (node_rev))->len);
if (prop_rep_key[0] != '\0')
SVN_ERR (svn_fs__delete_rep_if_mutable (fs, prop_rep_key, trail));
}
@@ -1319,8 +1333,8 @@
{
const char *data_rep_key;
data_rep_key = apr_pstrndup (trail->pool,
- node_rev->children->next->next->data,
- node_rev->children->next->next->len);
+ (NR_DATA_KEY (node_rev))->data,
+ (NR_DATA_KEY (node_rev))->len);
if (data_rep_key[0] != '\0')
SVN_ERR (svn_fs__delete_rep_if_mutable (fs, data_rep_key, trail));
}
@@ -1528,8 +1542,8 @@
if (node_rev->children->next->next->len != 0)
{
rep_key = apr_pstrndup (trail->pool,
- node_rev->children->next->next->data,
- node_rev->children->next->next->len);
+ (NR_DATA_KEY (node_rev))->data,
+ (NR_DATA_KEY (node_rev))->len);
SVN_ERR (svn_fs__read_rep (&rep_skel, file->fs, rep_key, trail));
baton->rep = rep_skel;
@@ -1576,8 +1590,8 @@
{
skel_t *rep;
const char *rep_key = apr_pstrndup (trail->pool,
- node_rev->children->next->next->data,
- node_rev->children->next->next->len);
+ (NR_DATA_KEY (node_rev))->data,
+ (NR_DATA_KEY (node_rev))->len);
SVN_ERR (svn_fs__read_rep (&rep, file->fs, rep_key, trail));
str_key = svn_fs__string_key_from_rep (rep, trail->pool);
@@ -1625,8 +1639,8 @@
const char *old_key, *new_key;
old_key = apr_pstrndup (trail->pool,
- node_rev_skel->children->next->next->data,
- node_rev_skel->children->next->next->len);
+ (NR_DATA_KEY (node_rev_skel))->data,
+ (NR_DATA_KEY (node_rev_skel))->len);
SVN_ERR (svn_fs__get_mutable_rep (&new_key, old_key, file->fs, trail));
@@ -1642,8 +1656,8 @@
if (strcmp (old_key, new_key) != 0)
{
/* We made a new rep, so update the node revision. */
- node_rev_skel->children->next->next = svn_fs__str_atom (new_key,
- trail->pool);
+ (NR_DATA_KEY (node_rev_skel))->data = new_key;
+ (NR_DATA_KEY (node_rev_skel))->len = strlen (new_key);
SVN_ERR (svn_fs__put_node_revision (file->fs, file->id,
node_rev_skel, trail));
}
@@ -1929,15 +1943,15 @@
node_rev = svn_fs__copy_skel (node_rev, trail->pool);
/* The HEADER is the first element of the node-revision skel. */
- header = node_rev->children;
+ header = NR_HEADER (node_rev);
/* The PROP-KEY is the second element. */
{
const char *prop_rep_key;
prop_rep_key = apr_pstrndup (trail->pool,
- node_rev->children->next->data,
- node_rev->children->next->len);
+ (NR_PROP_KEY (node_rev))->data,
+ (NR_PROP_KEY (node_rev))->len);
if (prop_rep_key && prop_rep_key[0] != '\0')
SVN_ERR (svn_fs__make_rep_immutable (node->fs, prop_rep_key, trail));
}
@@ -1947,8 +1961,8 @@
const char *data_rep_key;
data_rep_key = apr_pstrndup (trail->pool,
- node_rev->children->next->next->data,
- node_rev->children->next->next->len);
+ (NR_DATA_KEY (node_rev))->data,
+ (NR_DATA_KEY (node_rev))->len);
if (data_rep_key && data_rep_key[0] != '\0')
SVN_ERR (svn_fs__make_rep_immutable (node->fs, data_rep_key, trail));
}
diff --git a/subversion/libsvn_fs/structure b/subversion/libsvn_fs/structure
index b5cb2ec..6d50f6a 100644
--- a/subversion/libsvn_fs/structure
+++ b/subversion/libsvn_fs/structure
@@ -109,19 +109,6 @@
-
- #######################################################################
- ### ###
- ### Note: everything from here on down documents new filesystem ###
- ### internals that have not been completely implemented yet. If ###
- ### you want documentation that reflects the code as it is right ###
- ### now, read revision 1.36 or earlier of this file. When the new ###
- ### implementation is complete, this notice will be removed. ###
- ### ###
- #######################################################################
-
-
-
NODE-REVISION and HEADER: how we represent a node revision
We represent a given revision of a file or directory node using a list
@@ -401,6 +388,38 @@
whatever parameter we care about --- storage size, speed, robustness,
etc.
+A Note For The Near Future: How To Deltify:
+-------------------------------------------
+
+When a representation is deltified, it is changed in place, along with
+its underlying string. That is, the node revision referring to that
+representation will not be changed; instead, the same rep key will now
+be associated with different value. That way, we get reader locking
+for free: if someone's trying to read a file as Subversion is
+deltifying it, one of the two sides will get a DB_DEADLOCK and
+svn_fs__retry_txn() will retry.
+
+[todo: the reps will deadlock, but not sure that the strings locking
+will happen properly as things are currently structured. Needs to be
+investigated.]
+
+When a rep is deltified, we must also make sure that a fulltext is
+reachable from it. For example, suppose rep "2342" looks like this:
+
+ (("fulltext") "50956")
+
+So it's saying to use string "50956" and treat it as fulltext. Now we
+deltify that rep, so it looks like this:
+
+ (("delta") "2343" ("svndiff" "50956") ...)
+
+Before making this change, we must examine rep "2343". If it is a
+fulltext, then we're okay. If it is not, we must recurse into 2343's
+base rep, and so on, until we reach a fulltext (we'll check for cycles
+as we go). If we never reach a fulltext, there's a big problem in the
+filesystem, and we shouldn't add to it by committing another delta rep
+against the mess.
+
The Berkeley DB "nodes" table