* 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