* 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