xref: /plan9/sys/src/cmd/fossil/9excl.c (revision e12a987081f10894b49298514b3a97b41db862b0)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier 
35e96a66cSDavid du Colombier #include "9.h"
45e96a66cSDavid du Colombier 
55e96a66cSDavid du Colombier static struct {
65e96a66cSDavid du Colombier 	VtLock*	lock;
75e96a66cSDavid du Colombier 
85e96a66cSDavid du Colombier 	Excl*	head;
95e96a66cSDavid du Colombier 	Excl*	tail;
105e96a66cSDavid du Colombier } ebox;
115e96a66cSDavid du Colombier 
12*e12a9870SDavid du Colombier struct Excl {
135e96a66cSDavid du Colombier 	Fsys*	fsys;
145e96a66cSDavid du Colombier 	uvlong	path;
155e96a66cSDavid du Colombier 	ulong	time;
165e96a66cSDavid du Colombier 
175e96a66cSDavid du Colombier 	Excl*	next;
185e96a66cSDavid du Colombier 	Excl*	prev;
19*e12a9870SDavid du Colombier };
205e96a66cSDavid du Colombier 
215e96a66cSDavid du Colombier enum {
225e96a66cSDavid du Colombier 	LifeTime	= (5*60),
235e96a66cSDavid du Colombier };
245e96a66cSDavid du Colombier 
255e96a66cSDavid du Colombier int
exclAlloc(Fid * fid)265e96a66cSDavid du Colombier exclAlloc(Fid* fid)
275e96a66cSDavid du Colombier {
285e96a66cSDavid du Colombier 	ulong t;
295e96a66cSDavid du Colombier 	Excl *excl;
305e96a66cSDavid du Colombier 
315e96a66cSDavid du Colombier 	assert(fid->excl == nil);
325e96a66cSDavid du Colombier 
335e96a66cSDavid du Colombier 	t = time(0L);
345e96a66cSDavid du Colombier 	vtLock(ebox.lock);
355e96a66cSDavid du Colombier 	for(excl = ebox.head; excl != nil; excl = excl->next){
365e96a66cSDavid du Colombier 		if(excl->fsys != fid->fsys || excl->path != fid->qid.path)
375e96a66cSDavid du Colombier 			continue;
385e96a66cSDavid du Colombier 		/*
395e96a66cSDavid du Colombier 		 * Found it.
405e96a66cSDavid du Colombier 		 * Now, check if it's timed out.
415e96a66cSDavid du Colombier 		 * If not, return error, it's locked.
425e96a66cSDavid du Colombier 		 * If it has timed out, zap the old
435e96a66cSDavid du Colombier 		 * one and continue on to allocate a
445e96a66cSDavid du Colombier 		 * a new one.
455e96a66cSDavid du Colombier 		 */
465e96a66cSDavid du Colombier 		if(excl->time >= t){
475e96a66cSDavid du Colombier 			vtUnlock(ebox.lock);
485e96a66cSDavid du Colombier 			vtSetError("exclusive lock");
495e96a66cSDavid du Colombier 			return 0;
505e96a66cSDavid du Colombier 		}
515e96a66cSDavid du Colombier 		excl->fsys = nil;
525e96a66cSDavid du Colombier 	}
535e96a66cSDavid du Colombier 
545e96a66cSDavid du Colombier 	/*
555e96a66cSDavid du Colombier 	 * Not found or timed-out.
565e96a66cSDavid du Colombier 	 * Alloc a new one and initialise.
575e96a66cSDavid du Colombier 	 */
585e96a66cSDavid du Colombier 	excl = vtMemAllocZ(sizeof(Excl));
595e96a66cSDavid du Colombier 	excl->fsys = fid->fsys;
605e96a66cSDavid du Colombier 	excl->path = fid->qid.path;
615e96a66cSDavid du Colombier 	excl->time = t+LifeTime;
625e96a66cSDavid du Colombier 	if(ebox.tail != nil){
635e96a66cSDavid du Colombier 		excl->prev = ebox.tail;
645e96a66cSDavid du Colombier 		ebox.tail->next = excl;
655e96a66cSDavid du Colombier 	}
665e96a66cSDavid du Colombier 	else{
675e96a66cSDavid du Colombier 		ebox.head = excl;
685e96a66cSDavid du Colombier 		excl->prev = nil;
695e96a66cSDavid du Colombier 	}
705e96a66cSDavid du Colombier 	ebox.tail = excl;
715e96a66cSDavid du Colombier 	excl->next = nil;
725e96a66cSDavid du Colombier 	vtUnlock(ebox.lock);
735e96a66cSDavid du Colombier 
745e96a66cSDavid du Colombier 	fid->excl = excl;
755e96a66cSDavid du Colombier 	return 1;
765e96a66cSDavid du Colombier }
775e96a66cSDavid du Colombier 
785e96a66cSDavid du Colombier int
exclUpdate(Fid * fid)795e96a66cSDavid du Colombier exclUpdate(Fid* fid)
805e96a66cSDavid du Colombier {
815e96a66cSDavid du Colombier 	ulong t;
825e96a66cSDavid du Colombier 	Excl *excl;
835e96a66cSDavid du Colombier 
845e96a66cSDavid du Colombier 	excl = fid->excl;
855e96a66cSDavid du Colombier 
865e96a66cSDavid du Colombier 	t = time(0L);
875e96a66cSDavid du Colombier 	vtLock(ebox.lock);
885e96a66cSDavid du Colombier 	if(excl->time < t || excl->fsys != fid->fsys){
895e96a66cSDavid du Colombier 		vtUnlock(ebox.lock);
905e96a66cSDavid du Colombier 		vtSetError("exclusive lock broken");
915e96a66cSDavid du Colombier 		return 0;
925e96a66cSDavid du Colombier 	}
935e96a66cSDavid du Colombier 	excl->time = t+LifeTime;
945e96a66cSDavid du Colombier 	vtUnlock(ebox.lock);
955e96a66cSDavid du Colombier 
965e96a66cSDavid du Colombier 	return 1;
975e96a66cSDavid du Colombier }
985e96a66cSDavid du Colombier 
995e96a66cSDavid du Colombier void
exclFree(Fid * fid)1005e96a66cSDavid du Colombier exclFree(Fid* fid)
1015e96a66cSDavid du Colombier {
1025e96a66cSDavid du Colombier 	Excl *excl;
1035e96a66cSDavid du Colombier 
1045e96a66cSDavid du Colombier 	if((excl = fid->excl) == nil)
1055e96a66cSDavid du Colombier 		return;
1065e96a66cSDavid du Colombier 	fid->excl = nil;
1075e96a66cSDavid du Colombier 
1085e96a66cSDavid du Colombier 	vtLock(ebox.lock);
1095e96a66cSDavid du Colombier 	if(excl->prev != nil)
1105e96a66cSDavid du Colombier 		excl->prev->next = excl->next;
1115e96a66cSDavid du Colombier 	else
1125e96a66cSDavid du Colombier 		ebox.head = excl->next;
1135e96a66cSDavid du Colombier 	if(excl->next != nil)
1145e96a66cSDavid du Colombier 		excl->next->prev = excl->prev;
1155e96a66cSDavid du Colombier 	else
1165e96a66cSDavid du Colombier 		ebox.tail = excl->prev;
1175e96a66cSDavid du Colombier 	vtUnlock(ebox.lock);
1185e96a66cSDavid du Colombier 
1195e96a66cSDavid du Colombier 	vtMemFree(excl);
1205e96a66cSDavid du Colombier }
1215e96a66cSDavid du Colombier 
1225e96a66cSDavid du Colombier void
exclInit(void)1235e96a66cSDavid du Colombier exclInit(void)
1245e96a66cSDavid du Colombier {
1255e96a66cSDavid du Colombier 	ebox.lock = vtLockAlloc();
1265e96a66cSDavid du Colombier }
127