xref: /plan9-contrib/sys/src/cmd/fossil/9excl.c (revision d7aba6c3b511bc618cf0c53345848188fc02611a)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier 
35e96a66cSDavid du Colombier #include "9.h"
45e96a66cSDavid du Colombier 
55e96a66cSDavid du Colombier static struct {
6*d7aba6c3SDavid du Colombier 	QLock	lock;
75e96a66cSDavid du Colombier 
85e96a66cSDavid du Colombier 	Excl*	head;
95e96a66cSDavid du Colombier 	Excl*	tail;
105e96a66cSDavid du Colombier } ebox;
115e96a66cSDavid du Colombier 
12e12a9870SDavid 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;
19e12a9870SDavid 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);
34*d7aba6c3SDavid du Colombier 	qlock(&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){
47*d7aba6c3SDavid du Colombier 			qunlock(&ebox.lock);
48*d7aba6c3SDavid du Colombier 			werrstr("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 	 */
58*d7aba6c3SDavid du Colombier 	excl = vtmallocz(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;
72*d7aba6c3SDavid du Colombier 	qunlock(&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);
87*d7aba6c3SDavid du Colombier 	qlock(&ebox.lock);
885e96a66cSDavid du Colombier 	if(excl->time < t || excl->fsys != fid->fsys){
89*d7aba6c3SDavid du Colombier 		qunlock(&ebox.lock);
90*d7aba6c3SDavid du Colombier 		werrstr("exclusive lock broken");
915e96a66cSDavid du Colombier 		return 0;
925e96a66cSDavid du Colombier 	}
935e96a66cSDavid du Colombier 	excl->time = t+LifeTime;
94*d7aba6c3SDavid du Colombier 	qunlock(&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 
108*d7aba6c3SDavid du Colombier 	qlock(&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;
117*d7aba6c3SDavid du Colombier 	qunlock(&ebox.lock);
1185e96a66cSDavid du Colombier 
119*d7aba6c3SDavid du Colombier 	vtfree(excl);
1205e96a66cSDavid du Colombier }
1215e96a66cSDavid du Colombier 
1225e96a66cSDavid du Colombier void
exclInit(void)1235e96a66cSDavid du Colombier exclInit(void)
1245e96a66cSDavid du Colombier {
1255e96a66cSDavid du Colombier }
126