This patch is against revision 705.  There was a bug causing excessive
retries.  I originally thought it was a problem with revision 705, but
it wasn't.  This patch fixes that bug and fixes a few things with the
worker scheduling logic.

Index: xget.c
===================================================================
--- xget.c	(revision 705)
+++ xget.c	(working copy)
@@ -1002,13 +1002,15 @@
 static void
 respondreqs(File *f)
 {
-	int fd;
+	int fd, n;
 	Req *req, *nreq;
 	Spfcall *rc;
 	u8 *buf;
 	u64 count;
 
 	req = f->reqs;
+	fd = -1;
+	buf = NULL;
 	while (req != NULL) {
 		count = f->datalen - req->offset;
 		if (count < 0)
@@ -1017,32 +1019,27 @@
 		if (count > req->count)
 			count = req->count;
 		
-		if (f->datalen == f->datasize || (count>4096 && req->offset + count <= f->datalen) ) {
+		if (f->datalen == f->datasize || (count>4096 && req->offset + count < f->datalen)) {
 			/* if we haven't got the whole file and can send back
 			   only small chunk, don't respond, wait for more */
 			
 			buf = sp_malloc(count);
-			if ((fd = open(f->lname, O_RDONLY)) == -1) {
-				xget_uerror(errno);
-				free(buf);
-				continue;
-			}
+			if (!buf)
+				goto error;
+
+			if ((fd = open(f->lname, O_RDONLY)) == -1)
+				goto error;
 				
-			if ((lseek(fd, req->offset, SEEK_SET)) == (off_t)-1) {
-				xget_uerror(errno);
-				free(buf);
-				close(fd);
-				continue;
-			}
+			if ((lseek(fd, req->offset, SEEK_SET)) == (off_t)-1) 
+				goto error;
 			
-			if ((read(fd, buf, count)) < count) {
-				xget_uerror(errno);
-				free(buf);
-				close(fd);
-				continue;
-			}
+			if ((n = read(fd, buf, count)) < 0)
+				goto error;
 			
 			close(fd);
+			if (n < count)
+				count = n;
+
 			rc = sp_create_rread(count, buf);
 			free(buf);
 			sp_respond(req->req, rc);
@@ -1059,6 +1056,15 @@
 		} else
 			req = req->next;
 	}
+
+	return;
+
+error:
+	xget_uerror(errno);
+	if (buf)
+		free(buf);
+	if (fd > 0)
+		close(fd);
 }
 
 static void
@@ -1636,7 +1642,6 @@
 	}
 
 	signal(SIGHUP, reload);
-
 	if (netaddress) {
 		if (netmount(netaddress, user, port) < 0) {
 			fprintf(stderr, "Could not connect to server\n");
@@ -1814,6 +1819,9 @@
 
 	numconnects++;
 	debug(Dbgsrvfn, "Client %s connects %d\n", conn->address, numconnects);
+	if (netaddress)
+		return;
+
 	n = strlen(conn->address) + 1;
 	c = sp_malloc(sizeof(Client) + n + sizeof(int) * (maxlevels - 1));
 	if (!c)
@@ -1851,6 +1859,8 @@
 	
 	numconnects--;
 	debug(Dbgsrvfn, "Client %s disconnects %d\n", conn->address, numconnects);	
+	if (netaddress)
+		return;
 
 	for (c = clients; c != NULL; c = c->next) {
 		if (!strcmp(c->caddress, conn->address))
@@ -1884,7 +1894,7 @@
 static int
 redir_read(Spfilefid *fid, u64 offset, u32 count, u8 *data, Spreq *req)
 {
-	int n, m, i, j, q;
+	int n, dl, conns, level;
 	char buf[128];
 	File *f;
 	Worker *w, *p, *t;
@@ -1897,49 +1907,56 @@
 		return 0;
 
 	memset(buf, 0, sizeof(buf));
-	m = 0;
-	for (c = clients; c != NULL; c = c->next) {
+	dl = 0; //The desired level in the tree
+
+	//Find this client and determine the desired level
+	for (c = clients; c != NULL; c = c->next) { 
 		if (!strcmp(c->caddress, fid->fid->conn->address)) {
-			for (i = 1; i < maxlevels - 1; i++) {
-				if (c->clevels[m] > c->clevels[i])
-					m = i;
+			for (n = 1; n < maxlevels - 1; n++) {
+				if (c->clevels[dl] > c->clevels[n])
+					dl = n;
 			}
 			
 			break;
 		}
 	}
 
+	dl++;
 	if (!c) 
 		return -1;
 
-	q = 1;
-	j = 0;
-	if (!f->nextworker) {
+	level = 1;
+	conns = 0;
+	if (!f->nextworker)
 		snprintf(buf, sizeof(buf), "me");
-		c->clevels[0]++;
-	} else {
+	else {
 		p = f->nextworker;
 		t = NULL;
 		for (w = f->nextworker; w != NULL; ) {
 			if (w->slevel >= maxlevels) {
 				continue;
 			}
+			
+			/*Try to find a worker with the desired level and the least number
+			  of connections.  If the desired level cannot be found, just find
+			  a worker with the least number of connections. */
 
-			if (!t && w->server->conns < maxconnections) 
+			if (!t) {
+				if (w->server->conns < maxconnections &&
+				    dl == w->slevel)
 					t = w;
+				
+				else if (w->server->conns < maxconnections) 
+					t = w;
+			}
 			else {
-				if (t) {
-					if (t->server->conns > w->server->conns && 
-					    m == w->slevel - 1)
-						t = w;
-				} else {
-					if (w->server->conns < maxconnections &&
-					    m == w->slevel - 1)
-						t = w;
-				}
+				if (t->server->conns > w->server->conns && 
+				    dl == w->slevel)
+					t = w;
 				
-				if (t && t->server->conns == 0)
-					break;
+				else if (t->slevel != dl && t->server->conns >
+					 w->server->conns)
+					t = w;
 			}
 
 			if (!w->next && p == f->firstworker)
@@ -1950,10 +1967,8 @@
 				break;
 			else
 				w = w->next;
-			
-			continue;
 		}
-			
+
 		if (t) {
 			snprintf(buf, sizeof(buf), "%s", t->server->saddress);
 			if (t == f->lastworker)
@@ -1962,8 +1977,8 @@
 				f->nextworker = t->next;
 			
 			c->clevels[t->slevel - 1]++;
-			j = t->server->conns + 1;
-			q = t->slevel;
+			conns = t->server->conns + 1;
+			level = t->slevel;
 			uw = sp_malloc(sizeof(Usedworker));
 			if (!uw) 
 				return -1;
@@ -1976,10 +1991,8 @@
 
 			c->workersused = uw;
 		}
-		else {
+		else
 			snprintf(buf, sizeof(buf), "me");
-			c->clevels[0]++;
-		}
 	}
 	
 	n = strlen(buf);
@@ -1988,7 +2001,7 @@
 
 	memcpy(data, buf, count);
 	debug(Dbgsrvfn, "Client %s redirected to %s with conns: %d and level: %d" 
-	      " for file: %s\n", fid->fid->conn->address, buf, j, q, f->nname);
+	      " for file: %s\n", fid->fid->conn->address, buf, conns, level, f->nname);
 
 	return count;
 }

Reply via email to