- add some explanation of how the dirpool works
authorMichael Schroeder <mls@suse.de>
Mon, 28 Mar 2011 12:48:14 +0000 (14:48 +0200)
committerMichael Schroeder <mls@suse.de>
Mon, 28 Mar 2011 12:48:14 +0000 (14:48 +0200)
src/dirpool.c
src/dirpool.h

index afccf50..85197e4 100644 (file)
 
 #define DIR_BLOCK 127
 
+/* directories are stored as components,
+ * components are simple ids from the string pool
+ *   /usr/bin   ->  "", "usr", "bin"
+ *   /usr/lib   ->  "", "usr", "lib"
+ *   foo/bar    ->  "foo", "bar"
+ *   /usr/games ->  "", "usr", "games"
+ *
+ * all directories are stores in the "dirs" array
+ *   dirs[id] > 0 : component string pool id
+ *   dirs[id] <= 0 : -(parent directory id)
+ *
+ * Directories with the same parent are stored as
+ * multiple blocks. We need multiple blocks, because
+ * we cannot insert entries into old blocks, as that
+ * would shift the ids of already used directories.
+ * Each block starts with (-parent_dirid) and contains
+ * component ids of the directory entries.
+ * (The (-parent_dirid) entry is not a valid directory
+ * id, it's just used internally)
+ *
+ * There is also the aux "dirtraverse" array, which
+ * is created on demand to speed things up a bit.
+ * if dirs[id] > 0, dirtravers[id] points to the first
+ * entry in the last block with parent id
+ * if dirs[id] <= 0, dirtravers[id] points to the entry
+ * in the previous block with the same parent.
+ * (Thus it acts as a linked list that starts at the
+ * parent dirid and chains all the blocks with that
+ * parent.)
+ *
+ *  id    dirs[id]  dirtraverse[id]
+ *   0     0           8       [block#0 no parent]
+ *   1    ""           3
+ *   2    -1                   [block#0 parent 1, /]
+ *   3    "usr"       12
+ *   4    -3                   [block#0 parent 3, /usr]
+ *   5    "bin"
+ *   6    "lib"
+ *   7     0           1       [block#1 no parent]
+ *   8    "foo"       10
+ *   9    -8                   [block#0 parent 8, foo]
+ *  10    "bar"
+ *  11    -3           5       [block#1 parent 3, /usr]
+ *  12    "games"
+ *   
+ * to find all children of dirid 3, "/usr", follow the
+ * dirtraverse link to 12 -> "games". Then follow the
+ * dirtraverse link of this block to 5 -> "bin", "lib"
+ */
+
 void
 dirpool_init(Dirpool *dp)
 {
@@ -64,6 +114,8 @@ dirpool_add_dir(Dirpool *dp, Id parent, Id comp, int create)
     return 1;
   if (!dp->dirtraverse)
     dirpool_make_dirtraverse(dp);
+  /* check all entries with this parent if we
+   * already have this component */
   dirtraverse = dp->dirtraverse;
   ds = dirtraverse[parent];
   while (ds)
@@ -74,7 +126,7 @@ dirpool_add_dir(Dirpool *dp, Id parent, Id comp, int create)
        {
          if (dp->dirs[d] == comp)
            return d;
-         if (dp->dirs[d] <= 0)
+         if (dp->dirs[d] <= 0) /* reached end of this block */
            break;
        }
       if (ds)
index 2dec7e6..189156f 100644 (file)
@@ -23,6 +23,7 @@ void dirpool_free(Dirpool *dp);
 void dirpool_make_dirtraverse(Dirpool *dp);
 Id dirpool_add_dir(Dirpool *dp, Id parent, Id comp, int create);
 
+/* return the parent directory of child did */
 static inline Id dirpool_parent(Dirpool *dp, Id did)
 {
   if (!did)
@@ -32,11 +33,15 @@ static inline Id dirpool_parent(Dirpool *dp, Id did)
   return -dp->dirs[did];
 }
 
+/* return the next child entry of child did */
 static inline Id
 dirpool_sibling(Dirpool *dp, Id did)
 {
+  /* if this block contains another entry, simply return it */
   if (did + 1 < dp->ndirs && dp->dirs[did + 1] > 0)
     return did + 1;
+  /* end of block reached, rewind to get to the block's
+   * dirtraverse entry */
   while (dp->dirs[--did] > 0)
     ;
   /* need to special case did == 0 to prevent looping */
@@ -47,6 +52,7 @@ dirpool_sibling(Dirpool *dp, Id did)
   return dp->dirtraverse[did];
 }
 
+/* return the first child entry of directory did */
 static inline Id
 dirpool_child(Dirpool *dp, Id did)
 {