<?xml version="1.0" encoding="UTF-8"?>
<wiki>
  <body>&lt;p&gt;The corner stone of razor is the &lt;em&gt;package set&lt;/em&gt; on-disk data structure / file format.  It is how razor represents the packages installed on the system and it&amp;#8217;s what razor downloads from upstream servers to find out what&amp;#8217;s available. It&amp;#8217;s a simple binary file format, somewhat inspired by the &lt;span class=&quot;caps&quot;&gt;ELF&lt;/span&gt; binary format.  It has a sorted list of all packages and a sorted list of all unique properties (requires/provides/conflicts/obsoletes).  Each package has a list of the properties associated with it (a list of indices into the list of all properties) and each property has a list of packages that it belongs to (as a list of indices into the package list).  Strings are stored in a string pool, and referred to by their byte index in the pool.&lt;/p&gt;
&lt;p&gt;Much of this is still changing, but as of June 13th, this write up from Dan Winship is reasonably accurate.&lt;/p&gt;
&lt;h2&gt;The repo file format / razor_set data structure&lt;/h2&gt;
&lt;p&gt;The repo starts with a header, containing some number of sections, terminated by a section with type 0:&lt;/p&gt;
&lt;pre&gt;
struct razor_set_header {
        uint32_t magic;
        uint32_t version;
        struct razor_set_section sections[0];
};

struct razor_set_section {
        uint32_t type;
        uint32_t offset;
        uint32_t size;
};
&lt;/pre&gt;
&lt;p&gt;razor_set_open() mmaps the repo file, and creates a struct razor_set:&lt;/p&gt;
&lt;pre&gt;
struct razor_set {
        struct array string_pool;
        struct array packages;
        struct array properties;
        struct array files;
        struct array package_pool;
        struct array property_pool;
        struct array file_pool;
        struct razor_set_header *header;
};
&lt;/pre&gt;
&lt;p&gt;by finding the sections with those IDs and creating &amp;#8220;struct array&amp;#8221;s&lt;br /&gt;
pointing to the right places in the mmap()ed data. (This is the only&lt;br /&gt;
processing needed when reading in the file; everything else is used&lt;br /&gt;
exactly as-is.)&lt;/p&gt;
&lt;h3&gt;The sections&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;RAZOR_STRING_POOL&lt;/li&gt;
&lt;/ul&gt;
Stores one copy of each string that appears in the repo. (At the moment, this is: package names, package versions, property names, property versions, and (basenames of) filenames.) The strings are arbitrarily-sized, 0-terminated, and not in any particular order (although the empty string always ends up being at offset 0).
&lt;ul&gt;
	&lt;li&gt;RAZOR_PACKAGES&lt;/li&gt;
&lt;/ul&gt;
Array of struct razor_package; one for each package in the set, sorted by name.
&lt;ul&gt;
	&lt;li&gt;RAZOR_PROPERTIES&lt;/li&gt;
&lt;/ul&gt;
Array of struct razor_property; one for each unique property in the set, sorted by type, then name, then relation type (eg,
&amp;#8220;&amp;lt;&amp;#8221; or &amp;#8220;&amp;gt;=&amp;#8221;), then version. (Properties with no version have relation type RAZOR_VERSION_EQUAL, and version &amp;quot;&amp;quot;.)
&lt;ul&gt;
	&lt;li&gt;RAZOR_FILES&lt;/li&gt;
&lt;/ul&gt;
Array of struct razor_entry; one for each file owned by any package in the set. The current sort order (which is subject to change) is breadth-first, sorted by basename. So eg: /, /bin, /dev, /etc, /bin/false, /bin/true, /dev/null, /etc/passwd.
&lt;ul&gt;
	&lt;li&gt;RAZOR_PACKAGE_POOL&lt;/li&gt;
&lt;/ul&gt;
Array of struct list, with each list item containing the index of a struct razor_package in the packages section. See the discussion of lists below.
&lt;ul&gt;
	&lt;li&gt;RAZOR_PROPERTY_POOL&lt;/li&gt;
&lt;/ul&gt;
Array of struct list, with each list item containing the index of a struct razor_property in the properties section. See the discussion of lists below.
&lt;ul&gt;
	&lt;li&gt;RAZOR_FILE_POOL&lt;/li&gt;
&lt;/ul&gt;
Array of struct list, with each list item containing the index o f a struct razor_entry in the files section. See the discussion of lists below.
&lt;h3&gt;Data types&lt;/h3&gt;
&lt;p&gt;Note that the exact layout of bits involves some historical accidents. (Particularly the fact that the &amp;#8220;name&amp;#8221; field in most structs loses its&lt;br /&gt;
high bits to a flags field.)&lt;/p&gt;
&lt;pre&gt;
struct list_head {
        uint list_ptr : 24;
        uint flags    : 8;
};

struct list {
        uint data  : 24;
        uint flags : 8;
};
&lt;/pre&gt;
&lt;p&gt;Used to store lists of package, property, or file IDs. &amp;#8220;struct list_head&amp;#8221; stores the head of the list, which points to one or more &amp;#8220;struct list&amp;#8221;s in the appropriate &amp;#8220;pool&amp;#8221; section. (&amp;#8220;struct list&amp;#8221; should probably be called &amp;#8220;struct list_item&amp;#8221;.)&lt;/p&gt;
&lt;p&gt;&amp;#8220;list_first(&amp;amp;head, &amp;amp;pool)&amp;#8221; returns a &amp;#8220;struct list *&amp;#8221; pointing to the first element of the list (or &lt;span class=&quot;caps&quot;&gt;NULL&lt;/span&gt; for an empty list), and &amp;#8220;list_next(list)&amp;#8221; will return successive elements, until &lt;span class=&quot;caps&quot;&gt;NULL&lt;/span&gt; is returned. Each &amp;#8220;list&amp;#8594;data&amp;#8221; contains the index of a package, property, or file in the corresponding section of the set.&lt;/p&gt;
&lt;p&gt;Peeking underneath the abstraction, a list_head&amp;#8217;s &amp;#8220;flags&amp;#8221; is 0xff if the list is empty, 0&amp;#215;80 if it contains a single element, or 0&amp;#215;00 if it contains more than one element. In the single-element case, that element is actually stored in the list_head directly rather than being stored in a pool (and so list_first() just casts the list_head* to a list* and returns it). For multi-element lists, list_ptr is the index in the pool of the first element of this list; the list continues through successive elements of the pool until one with non-zero flags is reached, indicating the end of the list.&lt;/p&gt;
&lt;pre&gt;
struct razor_package {
        uint name    : 24;
        uint flags   : 8;
        uint version : 32;
        struct list_head properties;
        struct list_head files;
};
&lt;/pre&gt;
&lt;p&gt;name and version are indexes into string_pool. properties is a list of all of the package&amp;#8217;s properties, and files is a list of its files. flags is currently only used during razor_set merging, to keep track of which set a package came from.&lt;/p&gt;
&lt;pre&gt;
struct razor_property
        uint name     : 24;
        uint flags    : 6;
        uint type     : 2;
        uint relation : 32;
        uint version  : 32;
        struct list_head packages;
&lt;/pre&gt;
&lt;p&gt;name and version are indexes into string_pool. type is an enum razor_property_type (eg, RAZOR_PROPERTY_REQUIRES), and relation is an enum razor_version_relation (eg, RAZOR_VERSION_GREATER_OR_EQUAL). packages is a list of the packages that have this property. flags is currently unused.&lt;/p&gt;
&lt;pre&gt;
struct razor_entry {
        uint name  : 24;
        uint flags : 8;
        uint start : 32;
        struct list_head packages;
};
&lt;/pre&gt;
&lt;p&gt;name is an index into string_pool, giving the basename of the file. start is either 0, or an index pointing to another razor_entry that is the first child of this entry (for a non-empty directory). (Entry 0 is always the root of the tree, so no entry could have entry 0 as a child.) flags is 0&amp;#215;80 (RAZOR_ENTRY_LAST) if an entry is the last entry in its directory. Otherwise it is 0.&lt;/p&gt;
&lt;p&gt;Note that given a pointer to a struct_razor_entry (eg, from a package&amp;#8217;s &amp;#8220;files&amp;#8221; list), there is no way to reconstruct its full name without walking the entire files array up to that point. Because of this and other problems (fix_file_map()), it seems like razor_entry should be modified to include a pointer to its parent. (Storing full paths instead of just basenames would also fix this problem, but that would use much more memory.)&lt;/p&gt;</body>
  <created-at type="datetime">2008-06-13T10:19:28-07:00</created-at>
  <id type="integer">26641</id>
  <permalink>razor-design</permalink>
  <repository-id type="integer">14128</repository-id>
  <title>Razor Design</title>
  <updated-at type="datetime">2008-06-13T10:43:28-07:00</updated-at>
  <user-id type="integer">9175</user-id>
</wiki>
