예제 #1
0
파일: io.c 프로젝트: bhanug/harvey
static int
getlock(char *lock)
{
	char buf[ERRMAX];
	int i, fd;
	enum { SECS = 200 };

	for(i=0; i<SECS*10; i++){
		fd = wcreate(lock, ORDWR, DMEXCL|0666);
		if(fd >= 0)
			return fd;
		buf[0] = '\0';
		rerrstr(buf, sizeof buf);
		if(strstr(buf, "locked") == nil)
			break;
		sleep(1000/10);
	}
	werrstr("couldn't acquire lock %s: %r", lock);
	return -1;
}
/* insert word into a redblack tree */
int insert(char *word)
{
    TREEREC    *curr = ans->root, *par, *gpar, *prev = NULL, *wcreate();
    int		val;

    if( ans->root == NULL )
    {
	ans->ans = ans->root = wcreate(word, NULL);
	return 1;
    }
    while( curr != NULL && (val = scmp(word, curr->word)) != 0 )
    {
	prev = curr;
	if( val > 0 )
	    curr = curr->right;
	else
	    curr = curr->left;
    }

    ans->ans = curr;

    if( curr == NULL ) /* insert a new node, rotate up if necessary */
    {
	if( val > 0 )
	    curr = prev->right = wcreate(word, prev);
	else
	    curr = prev->left = wcreate(word, prev);

	curr->colour = RED;
	while( (par = curr->par) != NULL
		&& ( gpar = par->par ) != NULL
		&& curr->par->colour == RED )
	{
	    if( par == gpar->left )
	    {
		if( gpar->right!=NULL && gpar->right->colour == RED )
		{
		    par->colour = BLACK;
		    gpar->right->colour = BLACK;
		    gpar->colour = RED;
		    curr = gpar;
		}
		else
		{
		    if( curr == par->right )
		    {
			curr = par;
			leftrotate(ans, curr);
			par = curr->par;
		    }
		    par->colour = BLACK;
		    if( ( gpar=par->par ) != NULL )
		    {
			gpar->colour = RED;
			rightrotate(ans, gpar);
		    }
		}
	    }
	    else
	    {
		if( gpar->left!=NULL && gpar->left->colour == RED )
		{
		    par->colour = BLACK;
		    gpar->left->colour = BLACK;
		    gpar->colour = RED;
		    curr = gpar;
		}
		else
		{
		    if( curr == par->left )
		    {
			curr = par;
			rightrotate(ans, curr);
			par = curr->par;
		    }
		    par->colour = BLACK;
		    if( ( gpar=par->par ) != NULL )
		    {
			gpar->colour = RED;
			leftrotate(ans, gpar);
		    }
		}
	    }
	}
	if( curr->par == NULL )
	    ans->root = curr;
	ans->root->colour = BLACK;
        return 1;
    }
    
    return 0;
}
예제 #3
0
파일: io.c 프로젝트: bhanug/harvey
/*
 * Attempt to install a new page.  If t==0 we are creating.
 * Otherwise, we are editing and t must be set to the current
 * version (t is the version we started with) to avoid conflicting
 * writes.
 *
 * If there is a conflicting write, we still write the page to 
 * the history file, but mark it as a failed write.
 */
int
writepage(int num, uint32_t t, String *s, char *title)
{
	char tmp[40], tmplock[40], err[ERRMAX], hist[40], *p;
	int conflict, lfd, fd;
	Biobuf *b;
	String *os;

	sprint(tmp, "d/%d", num);
	sprint(tmplock, "d/L.%d", num);
	sprint(hist, "d/%d.hist", num);
	if((lfd = getlock(tmplock)) < 0)
		return -1;

	conflict = 0;
	if(b = wBopen(tmp, OREAD)){
		Brdline(b, '\n');	/* title */
		if(p = Brdline(b, '\n'))		/* version */
			p[Blinelen(b)-1] = '\0';
		if(p==nil || p[0] != 'D'){
			snprint(err, sizeof err, "bad format in extant file");
			conflict = 1;
		}else if(strtoul(p+1, 0, 0) != t){
			os = Brdstring(b);	/* why read the whole file? */
			p = strchr(s_to_c(s), '\n');
			if(p!=nil && strcmp(p+1, s_to_c(os))==0){	/* ignore dup write */
				close(lfd);
				s_free(os);
				Bterm(b);
				return 0;
			}
			s_free(os);
			snprint(err, sizeof err, "update conflict %lud != %s", t, p+1);
			conflict = 1;
		}
		Bterm(b);
	}else{
		if(t != 0){
			close(lfd);
			werrstr("did not expect to create");
			return -1;
		}
	}

	if((fd = wopen(hist, OWRITE)) < 0){
		if((fd = wcreate(hist, OWRITE, 0666)) < 0){
			close(lfd);
			return -1;
		}else
			fprint(fd, "%s\n", title);
	}
	if(seek(fd, 0, 2) < 0
	|| (conflict && write(fd, "X\n", 2) != 2)
	|| write(fd, s_to_c(s), s_len(s)) != s_len(s)){
		close(fd);
		close(lfd);
		return -1;
	}
	close(fd);

	if(conflict){
		close(lfd);
		voidcache(num);
		werrstr(err);
		return -1;
	}

	if((fd = wcreate(tmp, OWRITE, 0666)) < 0){
		close(lfd);
		voidcache(num);
		return -1;
	}
	if(write(fd, title, strlen(title)) != strlen(title)
	|| write(fd, "\n", 1) != 1
	|| write(fd, s_to_c(s), s_len(s)) != s_len(s)){
		close(fd);
		close(lfd);
		voidcache(num);
		return -1;
	}
	close(fd);
	close(lfd);
	voidcache(num);
	return 0;
}