Пример #1
0
/*
 * Some of this logic is duplicated in hdisk.c
 */
Packet*
readlump(u8int *score, int type, u32int size, int *cached)
{
	Lump *u;
	Packet *p;
	IAddr ia;
	u32int n;

	trace(TraceLump, "readlump enter");
/*
	qlock(&stats.lock);
	stats.lumpreads++;
	qunlock(&stats.lock);
*/
	if(scorecmp(score, zeroscore) == 0)
		return packetalloc();
	u = lookuplump(score, type);
	if(u->data != nil){
		trace(TraceLump, "readlump lookuplump hit");
		if(cached)
			*cached = 1;
		n = packetsize(u->data);
		if(n > size){
			seterr(EOk, "read too small: asked for %d need at least %d", size, n);
			putlump(u);

			return nil;
		}
		p = packetdup(u->data, 0, n);
		putlump(u);
		return p;
	}

	if(cached)
		*cached = 0;

	if(lookupscore(score, type, &ia) < 0){
		/* ZZZ place to check for someone trying to guess scores */
		seterr(EOk, "no block with score %V/%d exists", score, type);

		putlump(u);
		return nil;
	}
	if(ia.size > size){
		seterr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);

		putlump(u);
		return nil;
	}

	trace(TraceLump, "readlump readilump");
	p = readilump(u, &ia, score);
	putlump(u);

	trace(TraceLump, "readlump exit");
	return p;
}
Пример #2
0
Packet*
zblock2packet(ZBlock *zb, uint32_t size)
{
	Packet *p;

	if(zb == nil)
		return nil;
	p = packetalloc();
	packetappend(p, zb->data, size);
	return p;
}
Пример #3
0
Packet *
packetsplit(Packet *p, int n)
{
	Packet *pp;
	Frag *f, *ff;

	NOTFREE(p);
	if(n < 0 || n > p->size) {
		werrstr(EPacketSize);
		return nil;
	}

	pp = packetalloc();
	pp->pc = getcallerpc(&p);
	if(n == 0){
		NOTFREE(pp);
		return pp;
	}

	pp->size = n;
	p->size -= n;
	ff = nil;
	for(f=p->first; n > 0 && n >= FRAGSIZE(f); f=f->next) {
		n -= FRAGSIZE(f);
		p->asize -= FRAGASIZE(f);
		pp->asize += FRAGASIZE(f);
		f->p = pp;
		ff = f;
	}

	/* split shared frag */
	if(n > 0) {
		f->p = pp;
		ff = f;
		f = fragdup(p, ff);
		pp->asize += FRAGASIZE(ff);
		ff->wp = ff->rp + n;
		f->rp += n;
	}

	pp->first = p->first;
	pp->last = ff;
	ff->next = nil;
	p->first = f;
	if(f == nil || f->next == nil)
		p->last = f;
	NOTFREE(pp);
	NOTFREE(p);
	return pp;
}
Пример #4
0
Packet *
packetdup(Packet *p, int offset, int n)
{	
	Frag *f, *ff;
	Packet *pp;

	NOTFREE(p);
	if(offset < 0 || n < 0 || offset+n > p->size) {
		werrstr(EBadSize);
		return nil;
	}

	pp = packetalloc();
	pp->pc = getcallerpc(&p);
	if(n == 0){
		NOTFREE(pp);
		return pp;
	}

	pp->size = n;

	/* skip offset */
	for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
		offset -= FRAGSIZE(f);
	
	/* first frag */
	ff = fragdup(pp, f);
	ff->rp += offset;
	pp->first = ff;
	n -= FRAGSIZE(ff);
	pp->asize += FRAGASIZE(ff);

	/* the remaining */
	while(n > 0) {
		f = f->next;
		ff->next = fragdup(pp, f);
		ff = ff->next;
		n -= FRAGSIZE(ff);
		pp->asize += FRAGASIZE(ff);
	}
	
	/* fix up last frag: note n <= 0 */
	ff->wp += n;
	ff->next = nil;
	pp->last = ff;

	NOTFREE(pp);
	NOTFREE(p);
	return pp;
}
Пример #5
0
VtConn*
vtconn(int infd, int outfd)
{
	VtConn *z;
	NetConnInfo *nci;

	z = vtmallocz(sizeof(VtConn));
	z->tagrend.l = &z->lk;
	z->rpcfork.l = &z->lk;
	z->infd = infd;
	z->outfd = outfd;
	z->part = packetalloc();
	nci = getnetconninfo(nil, infd);
	if(nci == nil)
		snprint(z->addr, sizeof z->addr, "/dev/fd/%d", infd);
	else{
		strecpy(z->addr, z->addr+sizeof z->addr, nci->raddr);
		freenetconninfo(nci);
	}
	return z;
}
Пример #6
0
Packet*
packetforeign(uint8_t *buf, int n, void (*free)(void *a), void *a)
{
	Packet *p;
	Frag *f;

	p = packetalloc();
	p->pc = getcallerpc(&buf);
	f = fragalloc(p, 0, 0, nil);
	f->free = free;
	f->a = a;
	f->next = nil;
	f->rp = buf;
	f->wp = buf+n;

	p->first = f;
	p->last = f;
	p->size = n;
	NOTFREE(p);
	return p;
}
Пример #7
0
int
myvtwrite(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n)
{
	WriteReq wr;

	if(nwritethread == 0){
		n = vtwrite(z, score, type, buf, n);
		if(n < 0)
			sysfatal("vtwrite: %r");
		return n;
	}

	wr.p = packetalloc();
	packetappend(wr.p, buf, n);
	packetsha1(wr.p, score);
	memmove(wr.score, score, VtScoreSize);
	wr.type = type;
	nsend++;
	send(writechan, &wr);
	return 0;
}
Пример #8
0
static void
ventiserver(void *v)
{
	Packet *p;
	VtReq *r;
	char err[ERRMAX];
	uint ms;
	int ok;
	struct map *m;

	USED(v);
	threadsetname("ventiserver");
	trace(TraceWork, "start");
	while((r = vtgetreq(ventisrv)) != nil){
		trace(TraceWork, "finish");
		trace(TraceWork, "start request %F", &r->tx);
		trace(TraceRpc, "<- %F", &r->tx);
		r->rx.msgtype = r->tx.msgtype+1;
		addstat(StatRpcTotal, 1);
		if(0) print("req (arenas[0]=%p sects[0]=%p) %F\n",
			mainindex->arenas[0], mainindex->sects[0], &r->tx);
		switch(r->tx.msgtype){
		default:
			vtrerror(r, "unknown request");
			break;
		case VtTread:
			ms = msec();
			m = findscore(r->tx.score);
			//fprint(2, "findscore says %p\n", m);
			if (m) {
				//fprint(2, "Found the block\n");
				r->rx.data = packetalloc();
				packetappend(r->rx.data, m->data, m->len);
				r->rx.blocktype = m->blocktype;
			} else {
				r->rx.data = nil;
			}
			ms = msec() - ms;
			addstat2(StatRpcRead, 1, StatRpcReadTime, ms);
			if(r->rx.data == nil){
				addstat(StatRpcReadFail, 1);
				rerrstr(err, sizeof err);
				vtrerror(r, err);
			}else{
				addstat(StatRpcReadBytes, packetsize(r->rx.data));
				addstat(StatRpcReadOk, 1);
				addstat2(StatRpcReadCached, 1, StatRpcReadCachedTime, ms);
				r->rx.msgtype = VtRread;
				r->rx.error = nil;
			}
			break;
		case VtTwrite:
			if(readonly){
				vtrerror(r, "read only");
				break;
			}
			p = r->tx.data;
			r->tx.data = nil;
			addstat(StatRpcWriteBytes, packetsize(p));
			ms = msec();
			/* todo: check for overflow of file */
			ok = putscore(p, r->rx.score, r->tx.blocktype);
			ms = msec() - ms;
			addstat2(StatRpcWrite, 1, StatRpcWriteTime, ms);

			if(ok < 0){
				addstat(StatRpcWriteFail, 1);
				rerrstr(err, sizeof err);
				vtrerror(r, err);
			} else {
				r->rx.msgtype = VtRwrite;
				r->rx.error = nil;
			}
			break;
		case VtTsync:
			/* nonsense. Write synchronously. For now. Later, have a helper thread and VtTsync will just write a Fence to it and wait for it to come back. */
			break;
		}
		trace(TraceRpc, "-> %F", &r->rx);
		vtrespond(r);
		trace(TraceWork, "start");
	}
	threadexitsall(0);
}