Beispiel #1
0
/*
 * initialize the external bucket sorting data structures
 */
static IEBucks*
initiebucks(Part *part, int bits, uint32_t size)
{
	IEBucks *ib;
	int i;

	ib = MKZ(IEBucks);
	if(ib == nil){
		seterr(EOk, "out of memory");
		return nil;
	}
	ib->bits = bits;
	ib->nbucks = 1 << bits;
	ib->size = size;
	ib->usable = (size - U32Size) / IEntrySize * IEntrySize;
	ib->bucks = MKNZ(IEBuck, ib->nbucks);
	if(ib->bucks == nil){
		seterr(EOk, "out of memory allocation sorting buckets");
		freeiebucks(ib);
		return nil;
	}
	ib->xbuf = MKN(uint8_t, size * ((1 << bits)+1));
	ib->buf = (uint8_t*)(((uintptr)ib->xbuf+size-1)&~(uintptr)(size-1));
	if(ib->buf == nil){
		seterr(EOk, "out of memory allocating sorting buckets' buffers");
		freeiebucks(ib);
		return nil;
	}
	for(i = 0; i < ib->nbucks; i++){
		ib->bucks[i].head = TWID32;
		ib->bucks[i].buf = &ib->buf[i * size];
	}
	ib->part = part;
	return ib;
}
Beispiel #2
0
int
initlumpqueues(int nq)
{
	LumpQueue *q;

	int i;
	nqs = nq;

	lumpqs = MKNZ(LumpQueue, nq);

	for(i = 0; i < nq; i++){
		q = &lumpqs[i];
		q->full.l = &q->lock;
		q->empty.l = &q->lock;
		q->flush.l = &q->lock;

		if(vtproc(queueproc, q) < 0){
			seterr(EOk, "can't start write queue slave: %r");
			return -1;
		}
	}

	return 0;
}
Beispiel #3
0
void
threadmain(int argc, char *argv[])
{
	int vers;
	ArenaPart *ap;
	Part *part;
	Arena *arena;
	uint64_t addr, limit, asize, apsize;
	char *file, *name, aname[ANameSize];
	int i, n, blocksize, tabsize, zero;

	ventifmtinstall();
	statsinit();

	blocksize = 8 * 1024;
	asize = 512 * 1024 *1024;
	tabsize = 512 * 1024;		/* BUG: should be determine from number of arenas */
	zero = -1;
	vers = ArenaVersion5;
	ARGBEGIN{
	case 'D':
		settrace(EARGF(usage()));
		break;
	case 'a':
		asize = unittoull(EARGF(usage()));
		if(asize == TWID64)
			usage();
		break;
	case 'b':
		blocksize = unittoull(EARGF(usage()));
		if(blocksize == ~0)
			usage();
		if(blocksize > MaxDiskBlock){
			fprint(2, "block size too large, max %d\n", MaxDiskBlock);
			threadexitsall("usage");
		}
		break;
	case '4':
		vers = ArenaVersion4;
		break;
	case 'Z':
		zero = 0;
		break;
	default:
		usage();
		break;
	}ARGEND

	if(zero == -1){
		if(vers == ArenaVersion4)
			zero = 1;
		else
			zero = 0;
	}

	if(argc != 2)
		usage();

	name = argv[0];
	file = argv[1];

	if(nameok(name) < 0)
		sysfatal("illegal name template %s", name);

	part = initpart(file, ORDWR|ODIRECT);
	if(part == nil)
		sysfatal("can't open partition %s: %r", file);

	if(zero)
		zeropart(part, blocksize);

	maxblocksize = blocksize;
	initdcache(20*blocksize);

	ap = newarenapart(part, blocksize, tabsize);
	if(ap == nil)
		sysfatal("can't initialize arena: %r");

	apsize = ap->size - ap->arenabase;
	n = apsize / asize;
	if(apsize - (n * asize) >= MinArenaSize)
		n++;

	fprint(2, "fmtarenas %s: %,d arenas, %,lld bytes storage, %,d bytes for index map\n",
		file, n, apsize, ap->tabsize);

	ap->narenas = n;
	ap->map = MKNZ(AMap, n);
	ap->arenas = MKNZ(Arena*, n);

	addr = ap->arenabase;
	for(i = 0; i < n; i++){
		limit = addr + asize;
		if(limit >= ap->size || ap->size - limit < MinArenaSize){
			limit = ap->size;
			if(limit - addr < MinArenaSize)
				sysfatal("bad arena set math: runt arena at %lld,%lld %lld", addr, limit, ap->size);
		}

		snprint(aname, ANameSize, "%s%d", name, i);

		if(0) fprint(2, "adding arena %s at [%lld,%lld)\n", aname, addr, limit);

		arena = newarena(part, vers, aname, addr, limit - addr, blocksize);
		if(!arena)
			fprint(2, "can't make new arena %s: %r", aname);
		freearena(arena);

		ap->map[i].start = addr;
		ap->map[i].stop = limit;
		namecp(ap->map[i].name, aname);

		addr = limit;
	}

	if(wbarenapart(ap) < 0)
		fprint(2, "can't write back arena partition header for %s: %r\n", file);

	flushdcache();
	threadexitsall(0);
}
Beispiel #4
0
/*
 * initialize an entirely new index
 */
Index *
newindex(char *name, ISect **sects, int n)
{
	Index *ix;
	AMap *smap;
	u64int nb;
	u32int div, ub, xb, start, stop, blocksize, tabsize;
	int i, j;

	if(n < 1){
		seterr(EOk, "creating index with no index sections");
		return nil;
	}

	/*
	 * compute the total buckets available in the index,
	 * and the total buckets which are used.
	 */
	nb = 0;
	blocksize = sects[0]->blocksize;
	tabsize = sects[0]->tabsize;
	for(i = 0; i < n; i++){
		/*
		 * allow index, start, and stop to be set if index is correct
		 * and start and stop are what we would have picked.
		 * this allows calling fmtindex to reformat the index after
		 * replacing a bad index section with a freshly formatted one.
		 * start and stop are checked below.
		 */
		if(sects[i]->index[0] != '\0' && strcmp(sects[i]->index, name) != 0){
			seterr(EOk, "creating new index using non-empty section %s", sects[i]->name);
			return nil;
		}
		if(blocksize != sects[i]->blocksize){
			seterr(EOk, "mismatched block sizes in index sections");
			return nil;
		}
		if(tabsize != sects[i]->tabsize){
			seterr(EOk, "mismatched config table sizes in index sections");
			return nil;
		}
		nb += sects[i]->blocks;
	}

	/*
	 * check for duplicate names
	 */
	for(i = 0; i < n; i++){
		for(j = i + 1; j < n; j++){
			if(namecmp(sects[i]->name, sects[j]->name) == 0){
				seterr(EOk, "duplicate section name %s for index %s", sects[i]->name, name);
				return nil;
			}
		}
	}

	if(nb >= ((u64int)1 << 32)){
		fprint(2, "%s: index is 2^32 blocks or more; ignoring some of it\n",
			argv0);
		nb = ((u64int)1 << 32) - 1;
	}

	div = (((u64int)1 << 32) + nb - 1) / nb;
	if(div < 100){
		fprint(2, "%s: index divisor %d too coarse; "
			"index larger than needed, ignoring some of it\n",
			argv0, div);
		div = 100;
		nb = (((u64int)1 << 32) - 1) / (100 - 1);
	}
	ub = (((u64int)1 << 32) - 1) / div + 1;
	if(ub > nb){
		seterr(EBug, "index initialization math wrong");
		return nil;
	}
	xb = nb - ub;

	/*
	 * initialize each of the index sections
	 * and the section map table
	 */
	smap = MKNZ(AMap, n);
	if(smap == nil){
		seterr(EOk, "can't create new index: out of memory");
		return nil;
	}
	start = 0;
	for(i = 0; i < n; i++){
		stop = start + sects[i]->blocks - xb / n;
		if(i == n - 1)
			stop = ub;

		if(sects[i]->start != 0 || sects[i]->stop != 0)
		if(sects[i]->start != start || sects[i]->stop != stop){
			seterr(EOk, "creating new index using non-empty section %s", sects[i]->name);
			return nil;
		}

		sects[i]->start = start;
		sects[i]->stop = stop;
		namecp(sects[i]->index, name);

		smap[i].start = start;
		smap[i].stop = stop;
		namecp(smap[i].name, sects[i]->name);
		start = stop;
	}

	/*
	 * initialize the index itself
	 */
	ix = MKZ(Index);
	if(ix == nil){
		seterr(EOk, "can't create new index: out of memory");
		free(smap);
		return nil;
	}
	ix->version = IndexVersion;
	namecp(ix->name, name);
	ix->sects = sects;
	ix->smap = smap;
	ix->nsects = n;
	ix->blocksize = blocksize;
	ix->buckets = ub;
	ix->tabsize = tabsize;
	ix->div = div;

	if(initindex1(ix) < 0){
		free(smap);
		return nil;
	}

	return ix;
}