static struct pack_list * add_pack(struct packed_git *p) { struct pack_list l; unsigned long off = 0, step; const unsigned char *base; if (!p->pack_local && !(alt_odb || verbose)) return NULL; l.pack = p; llist_init(&l.all_objects); if (open_pack_index(p)) return NULL; base = p->index_data; base += 256 * 4 + ((p->index_version < 2) ? 4 : 8); step = the_hash_algo->rawsz + ((p->index_version < 2) ? 4 : 0); while (off < p->num_objects * step) { llist_insert_back(l.all_objects, (const struct object_id *)(base + off)); off += step; } /* this list will be pruned in cmp_two_packs later */ l.unique_objects = llist_copy(l.all_objects); if (p->pack_local) return pack_list_insert(&local_packs, &l); else return pack_list_insert(&altodb_packs, &l); }
static int is_superset(struct pack_list *pl, struct llist *list) { struct llist *diff; diff = llist_copy(list); while (pl) { llist_sorted_difference_inplace(diff, pl->all_objects); if (diff->size == 0) { /* we're done */ llist_free(diff); return 1; } pl = pl->next; } llist_free(diff); return 0; }
int cllist_copy(void *newCllist, void *oldCllist) { cLinkedList *_newCllist = (cLinkedList *)newCllist; cLinkedList *_oldCllist = (cLinkedList *)oldCllist; int returnVal; pthread_mutex_lock(&(_newCllist->mutex)); pthread_mutex_lock(&(_oldCllist->mutex)); returnVal = llist_copy(_newCllist->llist, _oldCllist->llist); pthread_mutex_unlock(&(_newCllist->mutex)); pthread_mutex_unlock(&(_oldCllist->mutex)); return returnVal; }
static void minimize(struct pack_list **min) { struct pack_list *pl, *unique = NULL, *non_unique = NULL, *min_perm = NULL; struct pll *perm, *perm_all, *perm_ok = NULL, *new_perm; struct llist *missing; off_t min_perm_size = 0, perm_size; int n; pl = local_packs; while (pl) { if (pl->unique_objects->size) pack_list_insert(&unique, pl); else pack_list_insert(&non_unique, pl); pl = pl->next; } /* find out which objects are missing from the set of unique packs */ missing = llist_copy(all_objects); pl = unique; while (pl) { llist_sorted_difference_inplace(missing, pl->all_objects); pl = pl->next; } /* return if there are no objects missing from the unique set */ if (missing->size == 0) { *min = unique; free(missing); return; } /* find the permutations which contain all missing objects */ for (n = 1; n <= pack_list_size(non_unique) && !perm_ok; n++) { perm_all = perm = get_permutations(non_unique, n); while (perm) { if (is_superset(perm->pl, missing)) { new_perm = xmalloc(sizeof(struct pll)); memcpy(new_perm, perm, sizeof(struct pll)); new_perm->next = perm_ok; perm_ok = new_perm; } perm = perm->next; } if (perm_ok) break; pll_free(perm_all); } if (perm_ok == NULL) die("Internal error: No complete sets found!"); /* find the permutation with the smallest size */ perm = perm_ok; while (perm) { perm_size = pack_set_bytecount(perm->pl); if (!min_perm_size || min_perm_size > perm_size) { min_perm_size = perm_size; min_perm = perm->pl; } perm = perm->next; } *min = min_perm; /* add the unique packs to the list */ pl = unique; while (pl) { pack_list_insert(min, pl); pl = pl->next; } }