1 #include "git-compat-util.h"
5 #include "pack-objects.h"
9 static uint32_t locate_object_entry_hash(struct packing_data
*pdata
,
10 const struct object_id
*oid
,
13 uint32_t i
, mask
= (pdata
->index_size
- 1);
15 i
= oidhash(oid
) & mask
;
17 while (pdata
->index
[i
] > 0) {
18 uint32_t pos
= pdata
->index
[i
] - 1;
20 if (oideq(oid
, &pdata
->objects
[pos
].idx
.oid
)) {
32 static inline uint32_t closest_pow2(uint32_t v
)
43 static void rehash_objects(struct packing_data
*pdata
)
46 struct object_entry
*entry
;
48 pdata
->index_size
= closest_pow2(pdata
->nr_objects
* 3);
49 if (pdata
->index_size
< 1024)
50 pdata
->index_size
= 1024;
53 CALLOC_ARRAY(pdata
->index
, pdata
->index_size
);
55 entry
= pdata
->objects
;
57 for (i
= 0; i
< pdata
->nr_objects
; i
++) {
59 uint32_t ix
= locate_object_entry_hash(pdata
,
64 BUG("Duplicate object in hash");
66 pdata
->index
[ix
] = i
+ 1;
71 struct object_entry
*packlist_find(struct packing_data
*pdata
,
72 const struct object_id
*oid
)
77 if (!pdata
->index_size
)
80 i
= locate_object_entry_hash(pdata
, oid
, &found
);
85 return &pdata
->objects
[pdata
->index
[i
] - 1];
88 static void prepare_in_pack_by_idx(struct packing_data
*pdata
)
90 struct packed_git
**mapping
, *p
;
91 int cnt
= 0, nr
= 1U << OE_IN_PACK_BITS
;
93 ALLOC_ARRAY(mapping
, nr
);
95 * oe_in_pack() on an all-zero'd object_entry
96 * (i.e. in_pack_idx also zero) should return NULL.
98 mapping
[cnt
++] = NULL
;
99 for (p
= get_all_packs(pdata
->repo
); p
; p
= p
->next
, cnt
++) {
107 pdata
->in_pack_by_idx
= mapping
;
111 * A new pack appears after prepare_in_pack_by_idx() has been
112 * run. This is likely a race.
114 * We could map this new pack to in_pack_by_idx[] array, but then we
115 * have to deal with full array anyway. And since it's hard to test
116 * this fall back code, just stay simple and fall back to using
119 void oe_map_new_pack(struct packing_data
*pack
)
124 BUG("packing_data has already been converted to pack array");
126 ALLOC_ARRAY(pack
->in_pack
, pack
->nr_alloc
);
128 for (i
= 0; i
< pack
->nr_objects
; i
++)
129 pack
->in_pack
[i
] = oe_in_pack(pack
, pack
->objects
+ i
);
131 FREE_AND_NULL(pack
->in_pack_by_idx
);
134 /* assume pdata is already zero'd by caller */
135 void prepare_packing_data(struct repository
*r
, struct packing_data
*pdata
)
139 if (git_env_bool("GIT_TEST_FULL_IN_PACK_ARRAY", 0)) {
141 * do not initialize in_pack_by_idx[] to force the
142 * slow path in oe_in_pack()
145 prepare_in_pack_by_idx(pdata
);
148 pdata
->oe_size_limit
= git_env_ulong("GIT_TEST_OE_SIZE",
150 pdata
->oe_delta_size_limit
= git_env_ulong("GIT_TEST_OE_DELTA_SIZE",
151 1UL << OE_DELTA_SIZE_BITS
);
152 init_recursive_mutex(&pdata
->odb_lock
);
155 struct object_entry
*packlist_alloc(struct packing_data
*pdata
,
156 const struct object_id
*oid
)
158 struct object_entry
*new_entry
;
160 if (pdata
->nr_objects
>= pdata
->nr_alloc
) {
161 pdata
->nr_alloc
= (pdata
->nr_alloc
+ 1024) * 3 / 2;
162 REALLOC_ARRAY(pdata
->objects
, pdata
->nr_alloc
);
164 if (!pdata
->in_pack_by_idx
)
165 REALLOC_ARRAY(pdata
->in_pack
, pdata
->nr_alloc
);
166 if (pdata
->delta_size
)
167 REALLOC_ARRAY(pdata
->delta_size
, pdata
->nr_alloc
);
169 if (pdata
->tree_depth
)
170 REALLOC_ARRAY(pdata
->tree_depth
, pdata
->nr_alloc
);
173 REALLOC_ARRAY(pdata
->layer
, pdata
->nr_alloc
);
175 if (pdata
->cruft_mtime
)
176 REALLOC_ARRAY(pdata
->cruft_mtime
, pdata
->nr_alloc
);
179 new_entry
= pdata
->objects
+ pdata
->nr_objects
++;
181 memset(new_entry
, 0, sizeof(*new_entry
));
182 oidcpy(&new_entry
->idx
.oid
, oid
);
184 if (pdata
->index_size
* 3 <= pdata
->nr_objects
* 4)
185 rehash_objects(pdata
);
188 uint32_t pos
= locate_object_entry_hash(pdata
,
192 BUG("duplicate object inserted into hash");
193 pdata
->index
[pos
] = pdata
->nr_objects
;
197 pdata
->in_pack
[pdata
->nr_objects
- 1] = NULL
;
199 if (pdata
->tree_depth
)
200 pdata
->tree_depth
[pdata
->nr_objects
- 1] = 0;
203 pdata
->layer
[pdata
->nr_objects
- 1] = 0;
205 if (pdata
->cruft_mtime
)
206 pdata
->cruft_mtime
[pdata
->nr_objects
- 1] = 0;
211 void oe_set_delta_ext(struct packing_data
*pdata
,
212 struct object_entry
*delta
,
213 const struct object_id
*oid
)
215 struct object_entry
*base
;
217 ALLOC_GROW(pdata
->ext_bases
, pdata
->nr_ext
+ 1, pdata
->alloc_ext
);
218 base
= &pdata
->ext_bases
[pdata
->nr_ext
++];
219 memset(base
, 0, sizeof(*base
));
220 oidcpy(&base
->idx
.oid
, oid
);
222 /* These flags mark that we are not part of the actual pack output. */
223 base
->preferred_base
= 1;
227 delta
->delta_idx
= base
- pdata
->ext_bases
+ 1;