/* * 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; }
Packet* zblock2packet(ZBlock *zb, uint32_t size) { Packet *p; if(zb == nil) return nil; p = packetalloc(); packetappend(p, zb->data, size); return p; }
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; }
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; }
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; }
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; }
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; }
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); }