Пример #1
0
static void *ileaf_resize(struct btree *btree, tuxkey_t inum, vleaf *base, unsigned newsize)
{
	assert(ileaf_sniff(btree, base));
	struct ileaf *leaf = base;
	assert(inum >= ibase(leaf));
	be_u16 *dict = base + btree->sb->blocksize;

	unsigned at = inum - ibase(leaf);
	if (at >= btree->entries_per_leaf)
		return NULL;

	unsigned extend_empty = at < icount(leaf) ? 0 : at - icount(leaf) + 1;
	unsigned offset = at && icount(leaf) ? from_be_u16(*(dict - (at < icount(leaf) ? at : icount(leaf)))) : 0;
	unsigned size = at < icount(leaf) ? from_be_u16(*(dict - at - 1)) - offset : 0;
	int more = newsize - size;
	if (more > 0 && sizeof(*dict) * extend_empty + more > ileaf_free(btree, leaf))
		return NULL;
	for (; extend_empty--; leaf->count = to_be_u16(from_be_u16(leaf->count) + 1))
		*(dict - icount(leaf) - 1) = to_be_u16(atdict(dict, icount(leaf)));
	assert(icount(leaf));
	unsigned itop = from_be_u16(*(dict - icount(leaf)));
	void *attrs = leaf->table + offset;
	printf("resize inum 0x%Lx at 0x%x from %x to %x\n", (L)inum, offset, size, newsize);

	assert(itop >= offset + size);
	memmove(attrs + newsize, attrs + size, itop - offset - size);
	for (int i = at + 1; i <= icount(leaf); i++)
		add_idict(dict - i, more);
	return attrs;
}
Пример #2
0
Move pb_probe(Pos *pos)
{
  Move m1 = 0;

  if (!enabled) return m1;
  if (!check_do_search(pos)) return m1;

  if (book_depth_count >= max_book_depth)
    return m1;

  Key key = polyglot_key(pos);

  int n = find_first_key(key);

  if (n < 1) {
    search_counter++;
    if (search_counter > 4) {
      // Stop searching after 4 times not in the book till position changes
      // according to check_do_search()
      do_search = false;
      search_counter = 0;
      book_depth_count = 0;
    }

    return m1;
  }

  book_depth_count++;

  ssize_t idx1 = use_best_book_move ? index_best : index_rand;

  m1 = pg_move_to_sf_move(pos, from_be_u16(polyhash[idx1].move));

  if (!is_draw(pos)) return m1; // 64
  if (n == 1) return m1;

  // Special case draw position and 2 moves available

  if (!check_draw(pos, m1))
    return m1;

  ssize_t idx2 = index_first;
  if (idx1 == idx2) idx2++;

  Move m2 = pg_move_to_sf_move(pos, from_be_u16(polyhash[idx2].move));

  if (!check_draw(pos, m2))
    return m2;

  return 0;
}
Пример #3
0
/* userland only */
void ileaf_merge(struct btree *btree, struct ileaf *leaf, struct ileaf *from)
{
	if (!icount(from))
		return;
	be_u16 *dict = (void *)leaf + btree->sb->blocksize;
	be_u16 *fromdict = (void *)from + btree->sb->blocksize;
	unsigned at = icount(leaf), free = atdict(dict, at), size = atdict(fromdict, icount(from));
	printf("copy in %i bytes\n", size);
	memcpy(leaf->table + free, from->table, size);
	leaf->count = to_be_u16(from_be_u16(leaf->count) + icount(from));
	veccopy(dict - icount(leaf), fromdict - icount(from), icount(from));
	for (int i = at + 1; at && i <= at + icount(from); i++)
		add_idict(dict - i, from_be_u16(*(dict - at)));
}
Пример #4
0
static void ileaf_dump(struct btree *btree, vleaf *vleaf)
{
	struct sb *sb = btree->sb;
	struct ileaf *leaf = vleaf;
	inum_t inum = ibase(leaf);
	be_u16 *dict = vleaf + sb->blocksize;
	unsigned offset = 0;
	printf("inode table block 0x%Lx/%i (%x bytes free)\n", (L)ibase(leaf), icount(leaf), ileaf_free(btree, leaf));
	//hexdump(dict - icount(leaf), icount(leaf) * 2);
	for (int i = -1; -i <= icount(leaf); i--, inum++) {
		int limit = from_be_u16(dict[i]), size = limit - offset;
		if (!size)
			continue;
		printf("  0x%Lx: ", (L)inum);
		//printf("[%x] ", offset);
		if (size < 0)
			printf("<corrupt>\n");
		else if (!size)
			printf("<empty>\n");
		else {
			/* FIXME: this doesn't work in kernel */
			struct inode inode = { .i_sb = vfs_sb(btree->sb) };
			unsigned xsize = decode_xsize(&inode, leaf->table + offset, size);
			tux_inode(&inode)->xcache = xsize ? new_xcache(xsize) : NULL;
			decode_attrs(&inode, leaf->table + offset, size);
			dump_attrs(&inode);
			xcache_dump(&inode);
			free(tux_inode(&inode)->xcache);
		}
		offset = limit;
	}
}

void *ileaf_lookup(struct btree *btree, inum_t inum, struct ileaf *leaf, unsigned *result)
{
	assert(inum >= ibase(leaf));
	assert(inum < ibase(leaf) + btree->entries_per_leaf);
	unsigned at = inum - ibase(leaf), size = 0;
	void *attrs = NULL;
	printf("lookup inode 0x%Lx, %Lx + %x\n", (L)inum, (L)ibase(leaf), at);
	if (at < icount(leaf)) {
		be_u16 *dict = (void *)leaf + btree->sb->blocksize;
		unsigned offset = atdict(dict, at);
		if ((size = from_be_u16(*(dict - at - 1)) - offset))
			attrs = leaf->table + offset;
	}
	*result = size;
	return attrs;
}
Пример #5
0
inum_t find_empty_inode(struct btree *btree, struct ileaf *leaf, inum_t goal)
{
	assert(goal >= ibase(leaf));
	goal -= ibase(leaf);
	//printf("find empty inode starting at %Lx, base %Lx\n", (L)goal, (L)ibase(leaf));
	be_u16 *dict = (void *)leaf + btree->sb->blocksize;
	unsigned i, offset = goal && goal < icount(leaf) ? from_be_u16(*(dict - goal)) : 0;
	for (i = goal; i < icount(leaf); i++) {
		unsigned limit = from_be_u16(*(dict - i - 1));
		if (offset == limit)
			break;
		offset = limit;
	}
	return i + ibase(leaf);
}
Пример #6
0
static void ileaf_trim(struct btree *btree, struct ileaf *leaf)
{
	be_u16 *dict = (void *)leaf + btree->sb->blocksize;
	while (icount(leaf) > 1 && *(dict - icount(leaf)) == *(dict - icount(leaf) + 1))
		leaf->count = to_be_u16(from_be_u16(leaf->count) - 1);
	if (icount(leaf) == 1 && !*(dict - 1))
		leaf->count = 0;
}
Пример #7
0
static int isinorder(struct btree *btree, struct ileaf *leaf)
{
	be_u16 *dict = (void *)leaf + btree->sb->blocksize;
	for (int i = 0, offset = 0, limit; --i >= -icount(leaf); offset = limit)
		if ((limit = from_be_u16(dict[i])) < offset)
			return 0;
	return 1;
}
Пример #8
0
int ileaf_purge(struct btree *btree, inum_t inum, struct ileaf *leaf)
{
	if (inum < ibase(leaf) || inum - ibase(leaf) >= btree->entries_per_leaf)
		return -EINVAL;
	be_u16 *dict = (void *)leaf + btree->sb->blocksize;
	unsigned at = inum - ibase(leaf);
	unsigned offset = atdict(dict, at);
	unsigned size = from_be_u16(*(dict - at - 1)) - offset;
	printf("delete inode %Lx from %p[%x/%x]\n", (L)inum, leaf, at, size);
	if (!size)
		return -ENOENT;
	unsigned free = from_be_u16(*(dict - icount(leaf))), tail = free - offset - size;
	assert(offset + size + tail <= free);
	memmove(leaf->table + offset, leaf->table + offset + size, tail);
	for (int i = at + 1; i <= icount(leaf); i++)
		add_idict(dict - i, -size);
	ileaf_trim(btree, leaf);
	return 0;
}
Пример #9
0
static tuxkey_t ileaf_split(struct btree *btree, tuxkey_t inum, vleaf *from, vleaf *into)
{
	assert(ileaf_sniff(btree, from));
	struct ileaf *leaf = from, *dest = into;
	be_u16 *dict = from + btree->sb->blocksize, *destdict = into + btree->sb->blocksize;

#ifdef SPLIT_AT_INUM
	printf("split at inum 0x%Lx\n", (L)inum);
	assert(inum >= ibase(leaf));
	unsigned at = inum - ibase(leaf) < icount(leaf) ? inum - ibase(leaf) : icount(leaf);
#else
	/* binsearch inum starting nearest middle of block */
	unsigned at = 1, hi = icount(leaf);
	while (at < hi) {
		int mid = (at + hi) / 2;
		if (*(dict - mid) < (btree->sb->blocksize / 2))
			at = mid + 1;
		else
			hi = mid;
	}
#endif
	/* should trim leading empty inodes on copy */
	unsigned split = atdict(dict, at), free = from_be_u16(*(dict - icount(leaf)));
	printf("split at %x of %x\n", at, icount(leaf));
	printf("copy out %x bytes at %x\n", free - split, split);
	assert(free >= split);
	memcpy(dest->table, leaf->table + split, free - split);
	dest->count = to_be_u16(icount(leaf) - at);
	veccopy(destdict - icount(dest), dict - icount(leaf), icount(dest));
	for (int i = 1; i <= icount(dest); i++)
		add_idict(destdict - i, -split);
#ifdef SPLIT_AT_INUM
	/* round down to multiple of 64 above ibase */
	inum_t round = inum & ~(inum_t)(btree->entries_per_leaf - 1);
	dest->ibase = to_be_u64(round > ibase(leaf) + icount(leaf) ? round : inum);
#else
	dest->ibase = to_be_u64(ibase(leaf) + at);
#endif
	leaf->count = to_be_u16(at);
	memset(leaf->table + split, 0, (char *)(dict - icount(leaf)) - (leaf->table + split));
	ileaf_trim(btree, leaf);
	return ibase(dest);
}
Пример #10
0
static int get_key_data(void)
{
  int best_weight = from_be_u16(polyhash[index_first].weight);
  index_weight_count = best_weight;
  uint64_t key = polyhash[index_first].key;

  index_count = 1;
  index_best = index_first;

  for (ssize_t i = index_first + 1; i < keycount; i++) {
    if (polyhash[i].key != key)
      break;

    index_count++;
    index_weight_count += from_be_u16(polyhash[i].weight);
    if (from_be_u16(polyhash[i].weight) > best_weight) {
      best_weight = from_be_u16(polyhash[i].weight);
      index_best = i;
    }
  }

  int rand_pos = prng_rand(&sr) % index_weight_count;
  int weight_count = 0;
  index_rand = index_best;

  for (ssize_t i = index_first; i < index_first + index_count; i++) {
    if (   rand_pos >= weight_count
        && rand_pos < weight_count + from_be_u16(polyhash[i].weight))
    {
      index_rand = i;
      break;
    }
    weight_count += from_be_u16(polyhash[i].weight);
  }

  return index_count;
}
Пример #11
0
static inline unsigned icount(struct ileaf *leaf)
{
	return from_be_u16(leaf->count);
}
Пример #12
0
static inline void add_idict(be_u16 *dict, int n)
{
	*dict = to_be_u16(from_be_u16(*dict) + n);
}
Пример #13
0
static inline unsigned atdict(be_u16 *dict, unsigned at)
{
	return at ? from_be_u16(*(dict - at)) : 0;
}