pack-objects.hon commit pack-objects: move in_pack_pos out of struct object_entry (06af3bb)
   1#ifndef PACK_OBJECTS_H
   2#define PACK_OBJECTS_H
   3
   4#define OE_DFS_STATE_BITS       2
   5#define OE_DEPTH_BITS           12
   6
   7/*
   8 * State flags for depth-first search used for analyzing delta cycles.
   9 *
  10 * The depth is measured in delta-links to the base (so if A is a delta
  11 * against B, then A has a depth of 1, and B a depth of 0).
  12 */
  13enum dfs_state {
  14        DFS_NONE = 0,
  15        DFS_ACTIVE,
  16        DFS_DONE,
  17        DFS_NUM_STATES
  18};
  19
  20/*
  21 * basic object info
  22 * -----------------
  23 * idx.oid is filled up before delta searching starts. idx.crc32 is
  24 * only valid after the object is written out and will be used for
  25 * generating the index. idx.offset will be both gradually set and
  26 * used in writing phase (base objects get offset first, then deltas
  27 * refer to them)
  28 *
  29 * "size" is the uncompressed object size. Compressed size of the raw
  30 * data for an object in a pack is not stored anywhere but is computed
  31 * and made available when reverse .idx is made.
  32 *
  33 * "hash" contains a path name hash which is used for sorting the
  34 * delta list and also during delta searching. Once prepare_pack()
  35 * returns it's no longer needed.
  36 *
  37 * source pack info
  38 * ----------------
  39 * The (in_pack, in_pack_offset) tuple contains the location of the
  40 * object in the source pack. in_pack_header_size allows quickly
  41 * skipping the header and going straight to the zlib stream.
  42 *
  43 * "type" and "in_pack_type" both describe object type. in_pack_type
  44 * may contain a delta type, while type is always the canonical type.
  45 *
  46 * deltas
  47 * ------
  48 * Delta links (delta, delta_child and delta_sibling) are created to
  49 * reflect that delta graph from the source pack then updated or added
  50 * during delta searching phase when we find better deltas.
  51 *
  52 * delta_child and delta_sibling are last needed in
  53 * compute_write_order(). "delta" and "delta_size" must remain valid
  54 * at object writing phase in case the delta is not cached.
  55 *
  56 * If a delta is cached in memory and is compressed, delta_data points
  57 * to the data and z_delta_size contains the compressed size. If it's
  58 * uncompressed [1], z_delta_size must be zero. delta_size is always
  59 * the uncompressed size and must be valid even if the delta is not
  60 * cached.
  61 *
  62 * [1] during try_delta phase we don't bother with compressing because
  63 * the delta could be quickly replaced with a better one.
  64 */
  65struct object_entry {
  66        struct pack_idx_entry idx;
  67        unsigned long size;     /* uncompressed size */
  68        struct packed_git *in_pack;     /* already in pack */
  69        off_t in_pack_offset;
  70        struct object_entry *delta;     /* delta base object */
  71        struct object_entry *delta_child; /* deltified objects who bases me */
  72        struct object_entry *delta_sibling; /* other deltified objects who
  73                                             * uses the same base as me
  74                                             */
  75        void *delta_data;       /* cached delta (uncompressed) */
  76        unsigned long delta_size;       /* delta data size (uncompressed) */
  77        unsigned long z_delta_size;     /* delta data size (compressed) */
  78        unsigned type_:TYPE_BITS;
  79        unsigned in_pack_type:TYPE_BITS; /* could be delta */
  80        unsigned type_valid:1;
  81        uint32_t hash;                  /* name hint hash */
  82        unsigned char in_pack_header_size;
  83        unsigned preferred_base:1; /*
  84                                    * we do not pack this, but is available
  85                                    * to be used as the base object to delta
  86                                    * objects against.
  87                                    */
  88        unsigned no_try_delta:1;
  89        unsigned tagged:1; /* near the very tip of refs */
  90        unsigned filled:1; /* assigned write-order */
  91        unsigned dfs_state:OE_DFS_STATE_BITS;
  92        unsigned depth:OE_DEPTH_BITS;
  93};
  94
  95struct packing_data {
  96        struct object_entry *objects;
  97        uint32_t nr_objects, nr_alloc;
  98
  99        int32_t *index;
 100        uint32_t index_size;
 101
 102        unsigned int *in_pack_pos;
 103};
 104
 105struct object_entry *packlist_alloc(struct packing_data *pdata,
 106                                    const unsigned char *sha1,
 107                                    uint32_t index_pos);
 108
 109struct object_entry *packlist_find(struct packing_data *pdata,
 110                                   const unsigned char *sha1,
 111                                   uint32_t *index_pos);
 112
 113static inline uint32_t pack_name_hash(const char *name)
 114{
 115        uint32_t c, hash = 0;
 116
 117        if (!name)
 118                return 0;
 119
 120        /*
 121         * This effectively just creates a sortable number from the
 122         * last sixteen non-whitespace characters. Last characters
 123         * count "most", so things that end in ".c" sort together.
 124         */
 125        while ((c = *name++) != 0) {
 126                if (isspace(c))
 127                        continue;
 128                hash = (hash >> 2) + (c << 24);
 129        }
 130        return hash;
 131}
 132
 133static inline enum object_type oe_type(const struct object_entry *e)
 134{
 135        return e->type_valid ? e->type_ : OBJ_BAD;
 136}
 137
 138static inline void oe_set_type(struct object_entry *e,
 139                               enum object_type type)
 140{
 141        if (type >= OBJ_ANY)
 142                BUG("OBJ_ANY cannot be set in pack-objects code");
 143
 144        e->type_valid = type >= OBJ_NONE;
 145        e->type_ = (unsigned)type;
 146}
 147
 148static inline unsigned int oe_in_pack_pos(const struct packing_data *pack,
 149                                          const struct object_entry *e)
 150{
 151        return pack->in_pack_pos[e - pack->objects];
 152}
 153
 154static inline void oe_set_in_pack_pos(const struct packing_data *pack,
 155                                      const struct object_entry *e,
 156                                      unsigned int pos)
 157{
 158        pack->in_pack_pos[e - pack->objects] = pos;
 159}
 160
 161#endif