4 #include "pack-objects.h"
8 static uint32_t locate_object_entry_hash(struct packing_data
*pdata
,
9 const unsigned char *sha1
,
12 uint32_t i
, mask
= (pdata
->index_size
- 1);
14 i
= sha1hash(sha1
) & mask
;
16 while (pdata
->index
[i
] > 0) {
17 uint32_t pos
= pdata
->index
[i
] - 1;
19 if (!hashcmp(sha1
, pdata
->objects
[pos
].idx
.oid
.hash
)) {
31 static inline uint32_t closest_pow2(uint32_t v
)
42 static void rehash_objects(struct packing_data
*pdata
)
45 struct object_entry
*entry
;
47 pdata
->index_size
= closest_pow2(pdata
->nr_objects
* 3);
48 if (pdata
->index_size
< 1024)
49 pdata
->index_size
= 1024;
52 pdata
->index
= xcalloc(pdata
->index_size
, sizeof(*pdata
->index
));
54 entry
= pdata
->objects
;
56 for (i
= 0; i
< pdata
->nr_objects
; i
++) {
58 uint32_t ix
= locate_object_entry_hash(pdata
,
63 BUG("Duplicate object in hash");
65 pdata
->index
[ix
] = i
+ 1;
70 struct object_entry
*packlist_find(struct packing_data
*pdata
,
71 const unsigned char *sha1
,
77 if (!pdata
->index_size
)
80 i
= locate_object_entry_hash(pdata
, sha1
, &found
);
88 return &pdata
->objects
[pdata
->index
[i
] - 1];
91 static void prepare_in_pack_by_idx(struct packing_data
*pdata
)
93 struct packed_git
**mapping
, *p
;
94 int cnt
= 0, nr
= 1U << OE_IN_PACK_BITS
;
96 ALLOC_ARRAY(mapping
, nr
);
98 * oe_in_pack() on an all-zero'd object_entry
99 * (i.e. in_pack_idx also zero) should return NULL.
101 mapping
[cnt
++] = NULL
;
102 for (p
= get_packed_git(the_repository
); p
; p
= p
->next
, cnt
++) {
110 pdata
->in_pack_by_idx
= mapping
;
114 * A new pack appears after prepare_in_pack_by_idx() has been
115 * run. This is likely a race.
117 * We could map this new pack to in_pack_by_idx[] array, but then we
118 * have to deal with full array anyway. And since it's hard to test
119 * this fall back code, just stay simple and fall back to using
122 void oe_map_new_pack(struct packing_data
*pack
,
123 struct packed_git
*p
)
127 REALLOC_ARRAY(pack
->in_pack
, pack
->nr_alloc
);
129 for (i
= 0; i
< pack
->nr_objects
; i
++)
130 pack
->in_pack
[i
] = oe_in_pack(pack
, pack
->objects
+ i
);
132 FREE_AND_NULL(pack
->in_pack_by_idx
);
135 /* assume pdata is already zero'd by caller */
136 void prepare_packing_data(struct packing_data
*pdata
)
138 if (git_env_bool("GIT_TEST_FULL_IN_PACK_ARRAY", 0)) {
140 * do not initialize in_pack_by_idx[] to force the
141 * slow path in oe_in_pack()
144 prepare_in_pack_by_idx(pdata
);
147 pdata
->oe_size_limit
= git_env_ulong("GIT_TEST_OE_SIZE",
149 pdata
->oe_delta_size_limit
= git_env_ulong("GIT_TEST_OE_DELTA_SIZE",
150 1UL << OE_DELTA_SIZE_BITS
);
152 pthread_mutex_init(&pdata
->lock
, NULL
);
156 struct object_entry
*packlist_alloc(struct packing_data
*pdata
,
157 const unsigned char *sha1
,
160 struct object_entry
*new_entry
;
162 if (pdata
->nr_objects
>= pdata
->nr_alloc
) {
163 pdata
->nr_alloc
= (pdata
->nr_alloc
+ 1024) * 3 / 2;
164 REALLOC_ARRAY(pdata
->objects
, pdata
->nr_alloc
);
166 if (!pdata
->in_pack_by_idx
)
167 REALLOC_ARRAY(pdata
->in_pack
, pdata
->nr_alloc
);
168 if (pdata
->delta_size
)
169 REALLOC_ARRAY(pdata
->delta_size
, pdata
->nr_alloc
);
172 new_entry
= pdata
->objects
+ pdata
->nr_objects
++;
174 memset(new_entry
, 0, sizeof(*new_entry
));
175 hashcpy(new_entry
->idx
.oid
.hash
, sha1
);
177 if (pdata
->index_size
* 3 <= pdata
->nr_objects
* 4)
178 rehash_objects(pdata
);
180 pdata
->index
[index_pos
] = pdata
->nr_objects
;
183 pdata
->in_pack
[pdata
->nr_objects
- 1] = NULL
;