Sun Dec  4 19:12:47 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  tagged 0.16
Sun Dec  4 19:12:26 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Version 0.16
Wed Nov  9 20:40:01 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Handle network errors in net_wakeup() and friends.
Wed Nov  9 20:38:57 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Brown paper bag bug: fix list_mult_add().
Wed Nov  9 20:34:50 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Remove trailing whitespace from libold.c.
Thu Sep 22 02:21:15 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Fix directory permissions in Makefile's install.
  'make install' changes the permissions to the man directories to 644, while it
  should be 744.
  
  Thanks to Carlo Strozzi for the report.
Mon Mar  7 13:00:31 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Updates to the release script.
Mon Mar  7 12:50:51 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Add a release script.
Mon Mar  7 12:33:20 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  tagged 0.15
diff -rN -u old-old/lib/libold.c new-old/lib/libold.c
--- old-old/lib/libold.c	2005-12-04 19:16:00.000000000 -0300
+++ new-old/lib/libold.c	2005-12-04 19:16:00.000000000 -0300
@@ -24,7 +24,7 @@
 	char header[4];
 	char ver = 1;
 	unsigned int ulen;
-	
+
 	/* just to simplify the code, if the lenght is lower than 0 it means
 	 * that it's a string and we should measure its lenght (we include the
 	 * ending \0)*/
@@ -40,15 +40,15 @@
 	header[1] = ((op << 4) & 0xF0) + ((ulen & 0xFF0000) >> 16);
 	header[2] = (ulen & 0x00FF00) >> 8;
 	header[3] = ulen & 0x0000FF;
-	
+
 	if (unlikely(write(fd, header, 4) != 4)) {
 		return 0;
 	}
-	
+
 	if (unlikely(write(fd, payload, ulen) != ulen)) {
 		return 0;
 	}
-	
+
 	return 1;
 }
 
@@ -56,20 +56,20 @@
 	ssize_t s;
 	struct net_cmd *cmd = NULL;
 	char buf[4];
-	
+
 	/* first get the header (which is 4 bytes) */
 	s = read(fd, buf, 4);
 	if (unlikely(s != 4)) {
 		return NULL;
 	}
-		
+
 	/* parse it */
 	cmd = (struct net_cmd *) malloc(sizeof(struct net_cmd));
 	if (unlikely(cmd == NULL))
 		return NULL;
 
 	memset(cmd, 0, sizeof(struct net_cmd));
-	
+
 	cmd->ver = buf[0] >> 4;
 	cmd->op = ((buf[0] & 0x0F ) << 4) + ((buf[1] & 0xF0) >> 4);
 	cmd->len = ( ((int) buf[1] & 0x0F) << 16) +
@@ -79,7 +79,7 @@
 		free(cmd);
 		return NULL;
 	}
-	
+
 	if (likely(cmd->len)) {
 		cmd->payload = (char *) malloc(cmd->len);
 		if (unlikely(cmd->payload == NULL)) {
@@ -92,18 +92,18 @@
 	}
 
 	/* and now, with the header done, read the payload */
-	
+
 	if (unlikely(cmd->len == 0)) {
 		/* a command without payload, just return it */
 		return cmd;
 	}
-	
+
 	s = read(fd, cmd->payload, cmd->len);
 	if (unlikely(s != cmd->len)) {
 		free(cmd);
 		return NULL;
 	}
-	
+
 	/* the command is complete! */
 	return cmd;
 }
@@ -111,13 +111,13 @@
 int old_lock(int fd, char *s) {
 	/* gets a lock */
 	struct net_cmd *cmd;
-	
+
 	send_cmd(fd, REQ_ACQ_LOCK, s, -1);
 	cmd = get_cmd(fd);
-	
+
 	if (unlikely(cmd == NULL))
 		return -1;
-	
+
 	if (cmd->op == REP_ACK)
 		/* if we get an ACK, just wait for a definitive answer */
 		cmd = get_cmd(fd);
@@ -127,20 +127,20 @@
 
 	if (cmd->op == REP_LOCK_ACQUIRED)
 		return 1;
-	
+
 	return 0;
 }
 
 int old_unlock(int fd, char *s) {
 	/* releases a lock */
 	struct net_cmd *cmd;
-	
+
 	send_cmd(fd, REQ_REL_LOCK, s, -1);
 	cmd = get_cmd(fd);
-	
+
 	if (unlikely(cmd == NULL))
 		return -1;
-	
+
 	if (cmd->op == REP_LOCK_RELEASED)
 		return 1;
 
@@ -150,13 +150,13 @@
 int old_trylock(int fd, char *s) {
 	/* tries to get a lock */
 	struct net_cmd *cmd;
-	
+
 	send_cmd(fd, REQ_TRY_LOCK, s, -1);
 	cmd = get_cmd(fd);
-	
+
 	if (unlikely(cmd == NULL))
 		return -1;
-	
+
 	if (cmd->op == REP_LOCK_ACQUIRED)
 		return 1;
 
@@ -173,26 +173,26 @@
 	if (hinfo == NULL) {
 		return -1;
 	}
-	
+
 	sa.sin_family = AF_INET;
 	sa.sin_port = htons(port);
 	sa.sin_addr = *((struct in_addr *) hinfo->h_addr_list[0]);
-	
+
 	fd = socket(PF_INET, SOCK_STREAM, 0);
 
 	rv = 1;
 	if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &rv, sizeof(rv)) < 0 ) {
 		return -1;
 	}
-			
-	
+
+
 	rv = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
 	if (rv != 0) {
 		return -1;
 	}
 
 	return fd;
-	
+
 }
 
 
diff -rN -u old-old/list.c new-old/list.c
--- old-old/list.c	2005-12-04 19:16:00.000000000 -0300
+++ new-old/list.c	2005-12-04 19:16:00.000000000 -0300
@@ -19,8 +19,18 @@
 }
 
 struct list *list_mult_add(struct list *head, struct list *new) {
-	new->next = head;
-	return new;
+	struct list *p;
+
+	/* append the new list at the end of the current one */
+	if (head == NULL) {
+		head = new;
+	} else {
+		for (p = head; p->next != NULL; p = p->next)
+			;
+		p->next = new;
+	}
+
+	return head;
 }
 
 struct list *list_remove(struct list *head, char *name) {
diff -rN -u old-old/lock.c new-old/lock.c
--- old-old/lock.c	2005-12-04 19:16:00.000000000 -0300
+++ new-old/lock.c	2005-12-04 19:16:00.000000000 -0300
@@ -59,11 +59,17 @@
 	if (h) {
 		h->locked = 0;
 		rv = h->fd;
-		if (h->wq != NULL)
-			net_wakeup(h);
-		else
-			/* if noone is waiting on this, destroy it */
+		if (h->wq == NULL) {
 			hash_del(s);
+		} else {
+			/* It's possible that net_wakeup tried to wake
+			 * everybody but for some reason (network failure,
+			 * etc.) there was no answer. In that case, we need to
+			 * free the entry since there are no more waiters. */
+			if (net_wakeup(h) == 0) {
+				hash_del(s);
+			}
+		}
 	} else {
 		rv = 0;
 	}
diff -rN -u old-old/Make.conf new-old/Make.conf
--- old-old/Make.conf	2005-12-04 19:16:00.000000000 -0300
+++ new-old/Make.conf	2005-12-04 19:16:00.000000000 -0300
@@ -1,5 +1,5 @@
 
-VERSION = "0.15"
+VERSION = "0.16"
 
 CC = gcc
 CFLAGS += -Wall -O6 -D_XOPEN_SOURCE=500 -D_BSD_SOURCE=1 -D_SVID_SOURCE=1
diff -rN -u old-old/Makefile new-old/Makefile
--- old-old/Makefile	2005-12-04 19:16:00.000000000 -0300
+++ new-old/Makefile	2005-12-04 19:16:00.000000000 -0300
@@ -34,9 +34,9 @@
 
 # manpages
 man_install:
-	install -g root -o root -m 0644 -d $(PREFIX)/man/man1
+	install -g root -o root -m 0755 -d $(PREFIX)/man/man1
 	install -g root -o root -m 0644 doc/old.1 $(PREFIX)/man/man1/
-	install -g root -o root -m 0644 -d $(PREFIX)/man/man3
+	install -g root -o root -m 0755 -d $(PREFIX)/man/man3
 	install -g root -o root -m 0644 doc/libold.3 $(PREFIX)/man/man3/
 
 cleanobj:
diff -rN -u old-old/net.c new-old/net.c
--- old-old/net.c	2005-12-04 19:16:00.000000000 -0300
+++ new-old/net.c	2005-12-04 19:16:00.000000000 -0300
@@ -303,6 +303,7 @@
 	header[3] = ulen & 0x0000FF;
 
 	//printf(">>> %hhu %hhu %hhu %hhu\n", header[0], header[1], header[2], header[3]);
+	//printf(">>> v:%d l:%u op:%u\n\n", ver, ulen, op);
 
 	if (unlikely(write(fd, header, 4) != 4)) {
 		clean_buffer(fd);
@@ -358,6 +359,8 @@
 
 		//printf("VER: %d, LEN: %d\n", cmd->ver, cmd->len);
 		//printf("<<< %hhu %hhu %hhu %hhu\n", b->tmp[0], b->tmp[1], b->tmp[2], b->tmp[3]);
+		//printf("<<< v:%d l:%u op:%u\n\n", cmd->ver, cmd->len, cmd->op);
+
 		if (unlikely(cmd->ver != 1 || cmd->len > MAX_PAYLOAD)) {
 			free(cmd);
 			clean_buffer(fd);
@@ -540,43 +543,60 @@
 
 /* wakes up the first fd waiting on the given hash entry */
 int net_wakeup(struct hentry *h) {
-	int fd;
+	int fd, rv;
 	struct wqentry *p;
 
-	/* get the fd from the first of the list */
-	fd = h->wq->fd;
-	active_fd[fd] = 1;
-
-	/* then remove it from the waitqueue */
-	p = h->wq->next;
-	free(h->wq);
-	h->wq = p;
-	h->fd = fd;
-
-	/* of course, mark it locked */
-	h->locked = 1;
-
-	/* add the open lock; the caller will take care to remove from the
-	 * other queue */
-	olocks[fd] = list_add(olocks[fd], h->objname);
+	do {
+		/* get the fd from the first of the list */
+		fd = h->wq->fd;
+		active_fd[fd] = 1;
+
+		/* then remove it from the waitqueue */
+		p = h->wq->next;
+		free(h->wq);
+		h->wq = p;
+		h->fd = fd;
+
+		rv = net_send_cmd(fd, REP_LOCK_ACQUIRED, h->objname, h->len);
+		if (!rv) {
+			/* the send failed; clean everything up and retry with
+			 * the next entry */
+			clean_buffer(fd);
+			net_close(fd);
+			perror("send failed:");
+			continue;
+		}
+
+		/* of course, mark it locked */
+		h->locked = 1;
 
-	/* and send the reply */
-	net_send_cmd(fd, REP_LOCK_ACQUIRED, h->objname, h->len);
-	return 1;
+		/* add the open lock; the caller will take care to remove from the
+		 * other queue */
+		olocks[fd] = list_add(olocks[fd], h->objname);
+		return 1;
+
+	} while (p != NULL);
+
+	return 0;
 }
 
 
 /* clean the orphan lists by releasing the locks - the code is taken from the
  * command parser */
 static void clean_orphans() {
-	struct list *p;
+	struct list *p, *next;
+
+	p = orphans;
+	while (p != NULL) {
+		next = p->next;
 
-	for (p = orphans; p != NULL; p = p->next) {
 		hash_lock_chain(p->name);
 		lock_release(p->name);
 		hash_unlock_chain(p->name);
 		/* this goes down here, otherwise we would free(p->name) */
 		orphans = list_remove(orphans, p->name);
+
+		p = next;
 	}
 }
 
diff -rN -u old-old/utils/release new-old/utils/release
--- old-old/utils/release	1969-12-31 21:00:00.000000000 -0300
+++ new-old/utils/release	2005-12-04 19:16:00.000000000 -0300
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+PKG=old
+
+if [ "$1" == "" -o "$2" == "" ]; then
+	echo "Use: release OLDREL NEWREL"
+	echo "Run from the repo root"
+	exit
+fi
+
+OLDREL=$1
+NEWREL=$2
+
+TARGZBALL="$PKG-$NEWREL.tar.gz"
+TARBZBALL="$PKG-$NEWREL.tar.bz2"
+RELDIR="../$NEWREL"
+
+if [ -d $RELDIR ]; then
+	echo "$RELDIR already exists!"
+	exit
+fi
+
+echo "* making $RELDIR"
+mkdir $RELDIR > /dev/null 2> /dev/null
+
+echo "* darcs dist"
+darcs dist -d $PKG-$NEWREL
+mv $TARGZBALL $RELDIR
+
+echo "* darcs changes"
+darcs changes --from-tag $OLDREL > $RELDIR/Changelog-$NEWREL
+
+echo "* darcs diff"
+darcs diff -u --from-tag $OLDREL > $RELDIR/$PKG-$NEWREL.patch
+
+echo "* unpack"
+cd $RELDIR
+tar -zxf $TARGZBALL
+
+echo "* tar.bz2"
+tar -cjf $TARBZBALL $PKG-$NEWREL
+


