예제 #1
0
파일: client.c 프로젝트: aahud/harvey
static Packet *
vtRPC(VtSession *z, int op, Packet *p)
{
	uint8_t *hdr, buf[2];
	char *err;

	if(z == nil){
		vtSetError(ENotConnected);
		return nil;
	}

	/*
	 * single threaded for the momment
	 */
	vtLock(z->lk);
	if(z->cstate != VtStateConnected){
		vtSetError(ENotConnected);
		goto Err;
	}
	hdr = packetHeader(p, 2);
	hdr[0] = op;	/* op */
	hdr[1] = 0;	/* tid */
	vtDebug(z, "client send: ");
	vtDebugMesg(z, p, "\n");
	if(!vtSendPacket(z, p)) {
		p = nil;
		goto Err;
	}
	p = vtRecvPacket(z);
	if(p == nil)
		goto Err;
	vtDebug(z, "client recv: ");
	vtDebugMesg(z, p, "\n");
	if(!packetConsume(p, buf, 2))
		goto Err;
	if(buf[0] == VtRError) {
		if(!vtGetString(p, &err)) {
			vtSetError(EProtocolBotch);
			goto Err;
		}
		vtSetError(err);
		vtMemFree(err);
		packetFree(p);
		vtUnlock(z->lk);
		return nil;
	}
	if(buf[0] != op+1 || buf[1] != 0) {
		vtSetError(EProtocolBotch);
		goto Err;
	}
	vtUnlock(z->lk);
	return p;
Err:
	vtDebug(z, "vtRPC failed: %s\n", vtGetError());
	if(p != nil)
		packetFree(p);
	vtUnlock(z->lk);
	vtDisconnect(z, 1);
	return nil;
}
예제 #2
0
파일: periodic.c 프로젝트: CoryXie/nix-os
static void
periodicThread(void *a)
{
	Periodic *p = a;
	vlong t, ct, ts;		/* times in ms. */

	vtThreadSetName("periodic");

	ct = nsec() / 1000000;
	t = ct + p->msec;		/* call p->f at or after this time */

	for(;;){
		ts = t - ct;		/* ms. to next cycle's start */
		if(ts > 1000)
			ts = 1000;	/* bound sleep duration */
		if(ts > 0)
			sleep(ts);	/* wait for cycle's start */

		vtLock(p->lk);
		if(p->die){
			vtUnlock(p->lk);
			break;
		}
		ct = nsec() / 1000000;
		if(t <= ct){		/* due to call p->f? */
			p->f(p->a);
			ct = nsec() / 1000000;
			while(t <= ct)	/* advance t to future cycle start */
				t += p->msec;
		}
		vtUnlock(p->lk);
	}
	periodicFree(p);
}
예제 #3
0
static void
periodicThread(void *a)
{
	Periodic *p = a;
	double t, ct, ts;

	vtThreadSetName("periodic");

	ct = nsec()*1e-6;
	t = ct + p->msec;

	for(;;){
		/* skip missed */
		while(t <= ct)
			t += p->msec;

		ts = t - ct;
		if(ts > 1000)
			ts = 1000;
		sleep(ts);
		ct = nsec()*1e-6;
		vtLock(p->lk);
		if(p->die){
			vtUnlock(p->lk);
			break;
		}
		if(t <= ct){
			p->f(p->a);
			t += p->msec;
		}
		vtUnlock(p->lk);
	}
	periodicFree(p);
}
예제 #4
0
파일: fs.c 프로젝트: bhanug/harvey
int
fsEpochLow(Fs *fs, uint32_t low)
{
	Block *bs;
	Super super;

	vtLock(fs->elk);
	if(low > fs->ehi){
		vtSetError("bad low epoch (must be <= %ud)", fs->ehi);
		vtUnlock(fs->elk);
		return 0;
	}

	if((bs = superGet(fs->cache, &super)) == nil){
		vtUnlock(fs->elk);
		return 0;
	}

	super.epochLow = low;
	fs->elo = low;
	superWrite(bs, &super, 1);
	blockPut(bs);
	vtUnlock(fs->elk);

	return 1;
}
예제 #5
0
파일: 9excl.c 프로젝트: CoryXie/nix-os
int
exclAlloc(Fid* fid)
{
	ulong t;
	Excl *excl;

	assert(fid->excl == nil);

	t = time(0L);
	vtLock(ebox.lock);
	for(excl = ebox.head; excl != nil; excl = excl->next){
		if(excl->fsys != fid->fsys || excl->path != fid->qid.path)
			continue;
		/*
		 * Found it.
		 * Now, check if it's timed out.
		 * If not, return error, it's locked.
		 * If it has timed out, zap the old
		 * one and continue on to allocate a
		 * a new one.
		 */
		if(excl->time >= t){
			vtUnlock(ebox.lock);
			vtSetError("exclusive lock");
			return 0;
		}
		excl->fsys = nil;
	}

	/*
	 * Not found or timed-out.
	 * Alloc a new one and initialise.
	 */
	excl = vtMemAllocZ(sizeof(Excl));
	excl->fsys = fid->fsys;
	excl->path = fid->qid.path;
	excl->time = t+LifeTime;
	if(ebox.tail != nil){
		excl->prev = ebox.tail;
		ebox.tail->next = excl;
	}
	else{
		ebox.head = excl;
		excl->prev = nil;
	}
	ebox.tail = excl;
	excl->next = nil;
	vtUnlock(ebox.lock);

	fid->excl = excl;
	return 1;
}
예제 #6
0
파일: rpc.c 프로젝트: aahud/harvey
int
vtSetCompression(VtSession *z, int fd)
{
	vtLock(z->lk);
	if(z->cstate != VtStateAlloc) {
		vtSetError("bad state");
		vtUnlock(z->lk);
		return 0;
	}
	z->fd = fd;
	vtUnlock(z->lk);
	return 1;
}
예제 #7
0
파일: 9srv.c 프로젝트: aahud/harvey
static Srv*
srvAlloc(char* service, int mode, int fd)
{
	Dir *dir;
	Srv *srv;
	int srvfd;
	char *mntpnt;

	vtLock(sbox.lock);
	for(srv = sbox.head; srv != nil; srv = srv->next){
		if(strcmp(srv->service, service) != 0)
			continue;
		/*
		 * If the service exists, but is stale,
		 * free it up and let the name be reused.
		 */
		if((dir = dirfstat(srv->srvfd)) != nil){
			free(dir);
			vtSetError("srv: already serving '%s'", service);
			vtUnlock(sbox.lock);
			return nil;
		}
		srvFree(srv);
		break;
	}

	if((srvfd = srvFd(service, mode, fd, &mntpnt)) < 0){
		vtUnlock(sbox.lock);
		return nil;
	}
	close(fd);

	srv = vtMemAllocZ(sizeof(Srv));
	srv->srvfd = srvfd;
	srv->service = vtStrDup(service);
	srv->mntpnt = mntpnt;

	if(sbox.tail != nil){
		srv->prev = sbox.tail;
		sbox.tail->next = srv;
	}
	else{
		sbox.head = srv;
		srv->prev = nil;
	}
	sbox.tail = srv;
	vtUnlock(sbox.lock);

	return srv;
}
예제 #8
0
파일: rpc.c 프로젝트: aahud/harvey
int
vtSetFd(VtSession *z, int fd)
{
	vtLock(z->lk);
	if(z->cstate != VtStateAlloc) {
		vtSetError("bad state");
		vtUnlock(z->lk);
		return 0;
	}
	if(z->fd >= 0)
		vtFdClose(z->fd);
	z->fd = fd;
	vtUnlock(z->lk);
	return 1;
}
예제 #9
0
파일: rpc.c 프로젝트: aahud/harvey
Packet*
vtRecvPacket(VtSession *z)
{
	uint8_t buf[10], *b;
	int n;
	Packet *p;
	int size, len;

	if(z->cstate != VtStateConnected) {
		vtSetError("session not connected");
		return 0;
	}

	vtLock(z->inLock);
	p = z->part;
	/* get enough for head size */
	size = packetSize(p);
	while(size < 2) {
		b = packetTrailer(p, MaxFragSize);
		assert(b != nil);
		n = vtFdRead(z->fd, b, MaxFragSize);
		if(n <= 0)
			goto Err;
		size += n;
		packetTrim(p, 0, size);
	}

	if(!packetConsume(p, buf, 2))
		goto Err;
	len = (buf[0] << 8) | buf[1];
	size -= 2;

	while(size < len) {
		n = len - size;
		if(n > MaxFragSize)
			n = MaxFragSize;
		b = packetTrailer(p, n);
		if(!vtFdReadFully(z->fd, b, n))
			goto Err;
		size += n;
	}
	p = packetSplit(p, len);
	vtUnlock(z->inLock);
	return p;
Err:	
	vtUnlock(z->inLock);
	return nil;	
}
예제 #10
0
파일: 9lstn.c 프로젝트: 99years/plan9
static int
cmdLstn(int argc, char* argv[])
{
	int dflag, flags;
	Lstn *lstn;
	char *usage = "usage: listen [-dIN] [address]";

	dflag = 0;
	flags = 0;
	ARGBEGIN{
	default:
		return cliError(usage);
	case 'd':
		dflag = 1;
		break;
	case 'I':
		flags |= ConIPCheck;
		break;
	case 'N':
		flags |= ConNoneAllow;
		break;
	}ARGEND

	switch(argc){
	default:
		return cliError(usage);
	case 0:
		vtRLock(lbox.lock);
		for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
			consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
		vtRUnlock(lbox.lock);
		break;
	case 1:
		if(!dflag){
			if(lstnAlloc(argv[0], flags) == nil)
				return 0;
			break;
		}

		vtLock(lbox.lock);
		for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
			if(strcmp(lstn->address, argv[0]) != 0)
				continue;
			if(lstn->afd != -1){
				close(lstn->afd);
				lstn->afd = -1;
			}
			break;
		}
		vtUnlock(lbox.lock);

		if(lstn == nil){
			vtSetError("listen: '%s' not found", argv[0]);
			return 0;
		}
		break;
	}

	return 1;
}
예제 #11
0
파일: 9fid.c 프로젝트: 99years/plan9
void
fidClunkAll(Con* con)
{
	Fid *fid;
	u32int fidno;

	vtLock(con->fidlock);
	while(con->fhead != nil){
		fidno = con->fhead->fidno;
		vtUnlock(con->fidlock);
		if((fid = fidGet(con, fidno, FidFWlock)) != nil)
			fidClunk(fid);
		vtLock(con->fidlock);
	}
	vtUnlock(con->fidlock);
}
예제 #12
0
/*
 * Check whether the calling thread can validly lock b.
 * That is, check that the calling thread doesn't hold
 * locks for any of b's children.
 */
void
bwatchLock(Block *b)
{
	int i;
	WThread *w;

	if(bwatchDisabled)
		return;

	if(b->part != PartData)
		return;

	vtLock(map.lk);
	w = getWThread();
	for(i=0; i<w->nb; i++){
		if(lockConflicts(w->b[i]->score, b->score)){
			fprint(2, "%d: have block %V; shouldn't lock %V\n",
				w->pid, w->b[i]->score, b->score);
			stop();
		}
	}
	vtUnlock(map.lk);
	if(w->nb >= MaxLock){
		fprint(2, "%d: too many blocks held\n", w->pid);
		stop();
	}else
		w->b[w->nb++] = b;
}
예제 #13
0
/*
 * Derive dependencies from the contents of b.
 */
void
bwatchDependency(Block *b)
{
	int i, epb, ppb;
	Entry e;

	if(bwatchDisabled)
		return;

	vtLock(map.lk);
	_bwatchResetParent(b->score);

	switch(b->l.type){
	case BtData:
		break;

	case BtDir:
		epb = blockSize / VtEntrySize;
		for(i=0; i<epb; i++){
			entryUnpack(&e, b->data, i);
			if(!(e.flags & VtEntryActive))
				continue;
			addChild(b->score, e.score, i);
		}
		break;

	default:
		ppb = blockSize / VtScoreSize;
		for(i=0; i<ppb; i++)
			addChild(b->score, b->data+i*VtScoreSize, i);
		break;
	}
	vtUnlock(map.lk);
}
예제 #14
0
파일: fs.c 프로젝트: bhanug/harvey
static void
snapEvent(void *v)
{
	Snap *s;
	uint32_t now, min;
	Tm tm;
	int need;
	uint32_t snaplife;

	s = v;

	now = time(0)/60;
	vtLock(s->lk);

	/*
	 * Snapshots happen every snapMinutes minutes.
	 * If we miss a snapshot (for example, because we
	 * were down), we wait for the next one.
	 */
	if(s->snapMinutes != ~0 && s->snapMinutes != 0
	&& now%s->snapMinutes==0 && now != s->lastSnap){
		if(!fsSnapshot(s->fs, nil, nil, 0))
			fprint(2, "%s: fsSnapshot snap: %R\n", argv0);
		s->lastSnap = now;
	}

	/*
	 * Archival snapshots happen at archMinute.
	 * If we miss an archive (for example, because we
	 * were down), we do it as soon as possible.
	 */
	tm = *localtime(now*60);
	min = tm.hour*60+tm.min;
	if(s->archMinute != ~0){
		need = 0;
		if(min == s->archMinute && now != s->lastArch)
			need = 1;
		if(s->lastArch == 0){
			s->lastArch = 1;
			if(fsNeedArch(s->fs, s->archMinute))
				need = 1;
		}
		if(need){
			fsSnapshot(s->fs, nil, nil, 1);
			s->lastArch = now;
		}
	}

	/*
	 * Snapshot cleanup happens every snaplife or every day.
	 */
	snaplife = s->snapLife;
	if(snaplife == ~0)
		snaplife = 24*60;
	if(s->lastCleanup+snaplife < now){
		fsSnapshotCleanup(s->fs, s->snapLife);
		s->lastCleanup = now;
	}
	vtUnlock(s->lk);
}
예제 #15
0
파일: 9lstn.c 프로젝트: 99years/plan9
static Lstn*
lstnAlloc(char* address, int flags)
{
	int afd;
	Lstn *lstn;
	char dir[NETPATHLEN];

	vtLock(lbox.lock);
	for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
		if(strcmp(lstn->address, address) != 0)
			continue;
		vtSetError("listen: already serving '%s'", address);
		vtUnlock(lbox.lock);
		return nil;
	}

	if((afd = announce(address, dir)) < 0){
		vtSetError("listen: announce '%s': %r", address);
		vtUnlock(lbox.lock);
		return nil;
	}

	lstn = vtMemAllocZ(sizeof(Lstn));
	lstn->afd = afd;
	lstn->address = vtStrDup(address);
	lstn->flags = flags;
	memmove(lstn->dir, dir, NETPATHLEN);

	if(lbox.tail != nil){
		lstn->prev = lbox.tail;
		lbox.tail->next = lstn;
	}
	else{
		lbox.head = lstn;
		lstn->prev = nil;
	}
	lbox.tail = lstn;
	vtUnlock(lbox.lock);

	if(vtThread(lstnListen, lstn) < 0){
		vtSetError("listen: thread '%s': %r", lstn->address);
		lstnFree(lstn);
		return nil;
	}

	return lstn;
}
예제 #16
0
void
bwatchReset(uchar score[VtScoreSize])
{
	vtLock(map.lk);
	_bwatchResetParent(score);
	_bwatchResetChild(score);
	vtUnlock(map.lk);
}
예제 #17
0
파일: periodic.c 프로젝트: CoryXie/nix-os
void
periodicKill(Periodic *p)
{
	if(p == nil)
		return;
	vtLock(p->lk);
	p->die = 1;
	vtUnlock(p->lk);
}
예제 #18
0
파일: fs.c 프로젝트: bhanug/harvey
int
fsUnhalt(Fs *fs)
{
	if(!fs->halted)
		return 0;
	fs->halted = 0;
	vtUnlock(fs->elk);
	return 1;
}
예제 #19
0
파일: fs.c 프로젝트: bhanug/harvey
int
fsSync(Fs *fs)
{
	vtLock(fs->elk);
	fileMetaFlush(fs->file, 1);
	cacheFlush(fs->cache, 1);
	vtUnlock(fs->elk);
	return 1;
}
예제 #20
0
파일: rpc.c 프로젝트: aahud/harvey
int
vtSetDebug(VtSession *z, int debug)
{
	int old;
	vtLock(z->lk);
	old = z->debug;
	z->debug = debug;
	vtUnlock(z->lk);
	return old;
}
예제 #21
0
파일: source.c 프로젝트: npe9/harvey
void
sourceClose(Source *r)
{
    if(r == nil)
        return;
    vtLock(r->lk);
    r->ref--;
    if(r->ref) {
        vtUnlock(r->lk);
        return;
    }
    assert(r->ref == 0);
    vtUnlock(r->lk);
    if(r->parent)
        sourceClose(r->parent);
    vtLockFree(r->lk);
    memset(r, ~0, sizeof(*r));
    vtMemFree(r);
}
예제 #22
0
파일: 9excl.c 프로젝트: CoryXie/nix-os
int
exclUpdate(Fid* fid)
{
	ulong t;
	Excl *excl;

	excl = fid->excl;

	t = time(0L);
	vtLock(ebox.lock);
	if(excl->time < t || excl->fsys != fid->fsys){
		vtUnlock(ebox.lock);
		vtSetError("exclusive lock broken");
		return 0;
	}
	excl->time = t+LifeTime;
	vtUnlock(ebox.lock);

	return 1;
}
예제 #23
0
파일: archive.c 프로젝트: 99years/plan9
void
archKick(Arch *a)
{
	if(a == nil){
		fprint(2, "warning: archKick nil\n");
		return;
	}
	vtLock(a->lk);
	vtWakeup(a->starve);
	vtUnlock(a->lk);
}
예제 #24
0
파일: rpc.c 프로젝트: aahud/harvey
void
vtReset(VtSession *z)
{
	vtLock(z->lk);
	z->cstate = VtStateAlloc;
	if(z->fd >= 0){
		vtFdClose(z->fd);
		z->fd = -1;
	}
	vtUnlock(z->lk);
}
예제 #25
0
파일: fs.c 프로젝트: bhanug/harvey
void
snapSetTimes(Snap *s, uint32_t arch, uint32_t snap, uint32_t snaplen)
{
	if(s == nil)
		return;

	vtLock(s->lk);
	s->snapMinutes = snap;
	s->archMinute = arch;
	s->snapLife = snaplen;
	vtUnlock(s->lk);
}
예제 #26
0
파일: 9fid.c 프로젝트: 99years/plan9
static void
fidUnlock(Fid* fid)
{
	if(!(fid->flags & FidFCreate))
		fsysFsRUnlock(fid->fsys);
	if(fid->flags & FidFWlock){
		fid->flags = 0;
		vtUnlock(fid->lock);
		return;
	}
	vtRUnlock(fid->lock);
}
예제 #27
0
파일: client.c 프로젝트: aahud/harvey
int
vtHello(VtSession *z)
{
	Packet *p;
	uint8_t buf[10];
	char *sid;
	int crypto, codec;

	sid = nil;

	p = packetAlloc();
	if(!vtAddString(p, vtGetVersion(z)))
		goto Err;
	if(!vtAddString(p, vtGetUid(z)))
		goto Err;
	buf[0] = vtGetCryptoStrength(z);
	buf[1] = 0;
	buf[2] = 0;
	packetAppend(p, buf, 3);
	p = vtRPC(z, VtQHello, p);
	if(p == nil)
		return 0;
	if(!vtGetString(p, &sid))
		goto Err;
	if(!packetConsume(p, buf, 2))
		goto Err;
	if(packetSize(p) != 0) {
		vtSetError(EProtocolBotch);
		goto Err;
	}
	crypto = buf[0];
	codec = buf[1];

	USED(crypto);
	USED(codec);

	packetFree(p);

	vtLock(z->lk);
	z->sid = sid;
	z->auth.state = VtAuthOK;
	vtSha1Free(z->inHash);
	z->inHash = nil;
	vtSha1Free(z->outHash);
	z->outHash = nil;
	vtUnlock(z->lk);

	return 1;
Err:
	packetFree(p);
	vtMemFree(sid);
	return 0;
}
예제 #28
0
파일: 9fid.c 프로젝트: 99years/plan9
static void
fidFree(Fid* fid)
{
	if(fid->file != nil){
		fileDecRef(fid->file);
		fid->file = nil;
	}
	if(fid->db != nil){
		dirBufFree(fid->db);
		fid->db = nil;
	}
	fidUnlock(fid);

	if(fid->uid != nil){
		vtMemFree(fid->uid);
		fid->uid = nil;
	}
	if(fid->uname != nil){
		vtMemFree(fid->uname);
		fid->uname = nil;
	}
	if(fid->excl != nil)
		exclFree(fid);
	if(fid->rpc != nil){
		close(fid->rpc->afd);
		auth_freerpc(fid->rpc);
		fid->rpc = nil;
	}
	if(fid->fsys != nil){
		fsysPut(fid->fsys);
		fid->fsys = nil;
	}
	if(fid->cuname != nil){
		vtMemFree(fid->cuname);
		fid->cuname = nil;
	}

	vtLock(fbox.lock);
	fbox.inuse--;
	if(fbox.nfree < 10){
		fid->hash = fbox.free;
		fbox.free = fid;
		fbox.nfree++;
	}
	else{
		vtLockFree(fid->alock);
		vtLockFree(fid->lock);
		vtMemFree(fid);
	}
	vtUnlock(fbox.lock);
}
예제 #29
0
파일: 9fid.c 프로젝트: 99years/plan9
void
fidPut(Fid* fid)
{
	vtLock(fid->con->fidlock);
	assert(fid->ref > 0);
	fid->ref--;
	vtUnlock(fid->con->fidlock);

	if(fid->ref == 0 && fid->fidno == NOFID){
		fidFree(fid);
		return;
	}
	fidUnlock(fid);
}
예제 #30
0
파일: archive.c 프로젝트: 99years/plan9
void
archFree(Arch *a)
{
	/* kill slave */
	vtLock(a->lk);
	a->die = vtRendezAlloc(a->lk);
	vtWakeup(a->starve);
	while(a->ref > 1)
		vtSleep(a->die);
	vtUnlock(a->lk);
	vtRendezFree(a->starve);
	vtRendezFree(a->die);
	vtLockFree(a->lk);
	vtMemFree(a);
}