pack-objects: use bitfield for object_entry::depth
[gitweb.git] / pack-objects.h
index 03f1191659dab55b2c4c440c347101a3cdbd4650..cdce1648de99fbc64b27a2980079ddb725d136dc 100644 (file)
@@ -1,6 +1,67 @@
 #ifndef PACK_OBJECTS_H
 #define PACK_OBJECTS_H
 
+#define OE_DFS_STATE_BITS      2
+#define OE_DEPTH_BITS          12
+
+/*
+ * State flags for depth-first search used for analyzing delta cycles.
+ *
+ * The depth is measured in delta-links to the base (so if A is a delta
+ * against B, then A has a depth of 1, and B a depth of 0).
+ */
+enum dfs_state {
+       DFS_NONE = 0,
+       DFS_ACTIVE,
+       DFS_DONE,
+       DFS_NUM_STATES
+};
+
+/*
+ * basic object info
+ * -----------------
+ * idx.oid is filled up before delta searching starts. idx.crc32 is
+ * only valid after the object is written out and will be used for
+ * generating the index. idx.offset will be both gradually set and
+ * used in writing phase (base objects get offset first, then deltas
+ * refer to them)
+ *
+ * "size" is the uncompressed object size. Compressed size of the raw
+ * data for an object in a pack is not stored anywhere but is computed
+ * and made available when reverse .idx is made.
+ *
+ * "hash" contains a path name hash which is used for sorting the
+ * delta list and also during delta searching. Once prepare_pack()
+ * returns it's no longer needed.
+ *
+ * source pack info
+ * ----------------
+ * The (in_pack, in_pack_offset) tuple contains the location of the
+ * object in the source pack. in_pack_header_size allows quickly
+ * skipping the header and going straight to the zlib stream.
+ *
+ * "type" and "in_pack_type" both describe object type. in_pack_type
+ * may contain a delta type, while type is always the canonical type.
+ *
+ * deltas
+ * ------
+ * Delta links (delta, delta_child and delta_sibling) are created to
+ * reflect that delta graph from the source pack then updated or added
+ * during delta searching phase when we find better deltas.
+ *
+ * delta_child and delta_sibling are last needed in
+ * compute_write_order(). "delta" and "delta_size" must remain valid
+ * at object writing phase in case the delta is not cached.
+ *
+ * If a delta is cached in memory and is compressed, delta_data points
+ * to the data and z_delta_size contains the compressed size. If it's
+ * uncompressed [1], z_delta_size must be zero. delta_size is always
+ * the uncompressed size and must be valid even if the delta is not
+ * cached.
+ *
+ * [1] during try_delta phase we don't bother with compressing because
+ * the delta could be quickly replaced with a better one.
+ */
 struct object_entry {
        struct pack_idx_entry idx;
        unsigned long size;     /* uncompressed size */
@@ -14,8 +75,9 @@ struct object_entry {
        void *delta_data;       /* cached delta (uncompressed) */
        unsigned long delta_size;       /* delta data size (uncompressed) */
        unsigned long z_delta_size;     /* delta data size (compressed) */
-       enum object_type type;
-       enum object_type in_pack_type;  /* could be delta */
+       unsigned type_:TYPE_BITS;
+       unsigned in_pack_type:TYPE_BITS; /* could be delta */
+       unsigned type_valid:1;
        uint32_t hash;                  /* name hint hash */
        unsigned int in_pack_pos;
        unsigned char in_pack_header_size;
@@ -27,19 +89,8 @@ struct object_entry {
        unsigned no_try_delta:1;
        unsigned tagged:1; /* near the very tip of refs */
        unsigned filled:1; /* assigned write-order */
-
-       /*
-        * State flags for depth-first search used for analyzing delta cycles.
-        *
-        * The depth is measured in delta-links to the base (so if A is a delta
-        * against B, then A has a depth of 1, and B a depth of 0).
-        */
-       enum {
-               DFS_NONE = 0,
-               DFS_ACTIVE,
-               DFS_DONE
-       } dfs_state;
-       int depth;
+       unsigned dfs_state:OE_DFS_STATE_BITS;
+       unsigned depth:OE_DEPTH_BITS;
 };
 
 struct packing_data {
@@ -78,4 +129,19 @@ static inline uint32_t pack_name_hash(const char *name)
        return hash;
 }
 
+static inline enum object_type oe_type(const struct object_entry *e)
+{
+       return e->type_valid ? e->type_ : OBJ_BAD;
+}
+
+static inline void oe_set_type(struct object_entry *e,
+                              enum object_type type)
+{
+       if (type >= OBJ_ANY)
+               BUG("OBJ_ANY cannot be set in pack-objects code");
+
+       e->type_valid = type >= OBJ_NONE;
+       e->type_ = (unsigned)type;
+}
+
 #endif