diff options
author | cinap_lenrek <cinap_lenrek@rei2.9hal> | 2012-01-10 17:26:31 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@rei2.9hal> | 2012-01-10 17:26:31 +0100 |
commit | 62fb4f97177d8e76f1fd49bb9d0073007b7c9bcc (patch) | |
tree | a40d70ac8dc0d968a60e28a5ff5334fb5899a4d1 /sys/src/libc | |
parent | 76918f348fbe29f0fc3a997106c644470023532e (diff) |
libc: restoring simple sequential version of dial()
Diffstat (limited to 'sys/src/libc')
-rw-r--r-- | sys/src/libc/9sys/dial.c | 356 |
1 files changed, 41 insertions, 315 deletions
diff --git a/sys/src/libc/9sys/dial.c b/sys/src/libc/9sys/dial.c index 74fc6e6ae..41a1e329e 100644 --- a/sys/src/libc/9sys/dial.c +++ b/sys/src/libc/9sys/dial.c @@ -1,24 +1,16 @@ -/* - * dial - connect to a service (parallel version) - */ #include <u.h> #include <libc.h> -typedef struct Conn Conn; -typedef struct Dest Dest; typedef struct DS DS; +static int call(char*, char*, DS*); +static int csdial(DS*); +static void _dial_string_parse(char*, DS*); + enum { Maxstring = 128, Maxpath = 256, - - Maxcsreply = 64*80, /* this is probably overly generous */ - /* - * this should be a plausible slight overestimate for non-interactive - * use even if it's ridiculously long for interactive use. - */ - Maxconnms = 20*60*1000, /* 20 minutes */ }; struct DS { @@ -34,42 +26,12 @@ struct DS { int *cfdp; }; -/* - * malloc these; they need to be writable by this proc & all children. - * the stack is private to each proc, and static allocation in the data - * segment would not permit concurrent dials within a multi-process program. - */ -struct Conn { - int pid; - int dead; - - int dfd; - int cfd; - char dir[NETPATHLEN]; - char err[ERRMAX]; -}; -struct Dest { - Conn *conn; /* allocated array */ - Conn *connend; - int nkid; - - QLock winlck; - int winner; /* index into conn[] */ - - char *nextaddr; - char addrlist[Maxcsreply]; -}; - -static int call(char*, char*, DS*, Dest*, Conn*); -static int csdial(DS*); -static void _dial_string_parse(char*, DS*); - /* * the dialstring is of the form '[/net/]proto!dest' */ -static int -dialimpl(char *dest, char *local, char *dir, int *cfdp) +int +dial(char *dest, char *local, char *dir, int *cfdp) { DS ds; int rv; @@ -107,224 +69,11 @@ dialimpl(char *dest, char *local, char *dir, int *cfdp) return rv; } -/* - * the thread library can't cope with rfork(RFMEM|RFPROC), - * so it must override this with a private version of dial. - */ -int (*_dial)(char *, char *, char *, int *) = dialimpl; - -int -dial(char *dest, char *local, char *dir, int *cfdp) -{ - return (*_dial)(dest, local, dir, cfdp); -} - -static int -connsalloc(Dest *dp, int addrs) -{ - free(dp->conn); - dp->connend = nil; - assert(addrs > 0); - - dp->conn = mallocz(addrs * sizeof *dp->conn, 1); - if(dp->conn == nil) - return -1; - dp->connend = dp->conn + addrs; - return 0; -} - -static void -freedest(Dest *dp) -{ - if (dp != nil) { - free(dp->conn); - free(dp); - } -} - -static void -closeopenfd(int *fdp) -{ - if (*fdp > 0) { - close(*fdp); - *fdp = -1; - } -} - -static void -notedeath(Dest *dp, char *exitsts) -{ - int i, n, pid; - char *fields[5]; /* pid + 3 times + error */ - Conn *conn; - - for (i = 0; i < nelem(fields); i++) - fields[i] = ""; - n = tokenize(exitsts, fields, nelem(fields)); - if (n < 4) - return; - pid = atoi(fields[0]); - if (pid <= 0) - return; - for (conn = dp->conn; conn < dp->connend; conn++) - if (conn->pid == pid && !conn->dead) { /* it's one we know? */ - if (conn - dp->conn != dp->winner) { - closeopenfd(&conn->dfd); - closeopenfd(&conn->cfd); - } - strncpy(conn->err, fields[4], sizeof conn->err); - conn->dead = 1; - return; - } - /* not a proc that we forked */ -} - -static int -outstandingprocs(Dest *dp) -{ - Conn *conn; - - for (conn = dp->conn; conn < dp->connend; conn++) - if (!conn->dead) - return 1; - return 0; -} - -static int -reap(Dest *dp) -{ - char exitsts[2*ERRMAX]; - - if (outstandingprocs(dp) && await(exitsts, sizeof exitsts) >= 0) { - notedeath(dp, exitsts); - return 0; - } - return -1; -} - -static int -fillinds(DS *ds, Dest *dp) -{ - Conn *conn; - - if (dp->winner < 0) - return -1; - conn = &dp->conn[dp->winner]; - if (ds->cfdp) - *ds->cfdp = conn->cfd; - if (ds->dir) - strncpy(ds->dir, conn->dir, NETPATHLEN); - return conn->dfd; -} - -static int -connectwait(Dest *dp, char *besterr) -{ - Conn *conn; - - /* wait for a winner or all attempts to time out */ - while (dp->winner < 0 && reap(dp) >= 0) - ; - - /* kill all of our still-live kids & reap them */ - for (conn = dp->conn; conn < dp->connend; conn++) - if (!conn->dead) - postnote(PNPROC, conn->pid, "die"); - while (reap(dp) >= 0) - ; - - /* rummage about and report some error string */ - for (conn = dp->conn; conn < dp->connend; conn++) - if (conn - dp->conn != dp->winner && conn->dead && - conn->err[0]) { - strncpy(besterr, conn->err, ERRMAX); - break; - } - return dp->winner; -} - -static int -parsecs(Dest *dp, char **clonep, char **destp) -{ - char *dest, *p; - - dest = strchr(dp->nextaddr, ' '); - if(dest == nil) - return -1; - *dest++ = '\0'; - p = strchr(dest, '\n'); - if(p == nil) - return -1; - *p++ = '\0'; - *clonep = dp->nextaddr; - *destp = dest; - dp->nextaddr = p; /* advance to next line */ - return 0; -} - -static void -pickuperr(char *besterr, char *err) -{ - err[0] = '\0'; - errstr(err, ERRMAX); - if(strstr(err, "does not exist") == 0) - strcpy(besterr, err); -} - -/* - * try all addresses in parallel and take the first one that answers; - * this helps when systems have ip v4 and v6 addresses but are - * only reachable from here on one (or some) of them. - */ -static int -dialmulti(DS *ds, Dest *dp) -{ - int rv, kid, kidme; - char *clone, *dest; - char err[ERRMAX], besterr[ERRMAX]; - - dp->winner = -1; - dp->nkid = 0; - while(dp->winner < 0 && *dp->nextaddr != '\0' && - parsecs(dp, &clone, &dest) >= 0) { - kidme = dp->nkid++; /* make private copy on stack */ - kid = rfork(RFPROC|RFMEM); /* spin off a call attempt */ - if (kid < 0) - --dp->nkid; - else if (kid == 0) { - alarm(Maxconnms); - *besterr = '\0'; - rv = call(clone, dest, ds, dp, &dp->conn[kidme]); - if(rv < 0) - pickuperr(besterr, err); - _exits(besterr); /* avoid atexit callbacks */ - } - } - rv = connectwait(dp, besterr); - if(rv < 0 && *besterr) - werrstr("%s", besterr); - else - werrstr("%s", err); - return rv; -} - static int csdial(DS *ds) { - int n, fd, rv, addrs, bleft; - char c; - char *addrp, *clone2, *dest; - char buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX]; - Dest *dp; - - dp = mallocz(sizeof *dp, 1); - if(dp == nil) - return -1; - dp->winner = -1; - if (connsalloc(dp, 1) < 0) { /* room for a single conn. */ - freedest(dp); - return -1; - } + int n, fd, rv; + char *p, buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX]; /* * open connection server @@ -334,10 +83,7 @@ csdial(DS *ds) if(fd < 0){ /* no connection server, don't translate */ snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto); - rv = call(clone, ds->rem, ds, dp, &dp->conn[0]); - fillinds(ds, dp); - freedest(dp); - return rv; + return call(clone, ds->rem, ds); } /* @@ -346,57 +92,41 @@ csdial(DS *ds) snprint(buf, sizeof(buf), "%s!%s", ds->proto, ds->rem); if(write(fd, buf, strlen(buf)) < 0){ close(fd); - freedest(dp); return -1; } /* - * read all addresses from the connection server. + * loop through each address from the connection server till + * we get one that works. */ + *besterr = 0; + rv = -1; seek(fd, 0, 0); - addrs = 0; - addrp = dp->nextaddr = dp->addrlist; - bleft = sizeof dp->addrlist - 2; /* 2 is room for \n\0 */ - while(bleft > 0 && (n = read(fd, addrp, bleft)) > 0) { - if (addrp[n-1] != '\n') - addrp[n++] = '\n'; - addrs++; - addrp += n; - bleft -= n; + while((n = read(fd, buf, sizeof(buf) - 1)) > 0){ + buf[n] = 0; + p = strchr(buf, ' '); + if(p == 0) + continue; + *p++ = 0; + rv = call(buf, p, ds); + if(rv >= 0) + break; + err[0] = '\0'; + errstr(err, sizeof err); + if(strstr(err, "does not exist") == 0) + strcpy(besterr, err); } - /* - * if we haven't read all of cs's output, assume the last line might - * have been truncated and ignore it. we really don't expect this - * to happen. - */ - if (addrs > 0 && bleft <= 0 && read(fd, &c, 1) == 1) - addrs--; close(fd); - *besterr = 0; - rv = -1; /* pessimistic default */ - if (addrs == 0) - werrstr("no address to dial"); - else if (addrs == 1) { - /* common case: dial one address without forking */ - if (parsecs(dp, &clone2, &dest) >= 0 && - (rv = call(clone2, dest, ds, dp, &dp->conn[0])) < 0) { - pickuperr(besterr, err); - werrstr("%s", besterr); - } - } else if (connsalloc(dp, addrs) >= 0) - rv = dialmulti(ds, dp); - - /* fill in results */ - if (rv >= 0 && dp->winner >= 0) - rv = fillinds(ds, dp); - - freedest(dp); + if(rv < 0 && *besterr) + werrstr("%s", besterr); + else + werrstr("%s", err); return rv; } static int -call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) +call(char *clone, char *dest, DS *ds) { int fd, cfd, n; char cname[Maxpath], name[Maxpath], data[Maxpath], *p; @@ -412,15 +142,14 @@ call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) p = clone; snprint(cname, sizeof cname, "%s/%s", ds->netdir, p); - conn->pid = getpid(); - conn->cfd = cfd = open(cname, ORDWR); + cfd = open(cname, ORDWR); if(cfd < 0) return -1; /* get directory name */ n = read(cfd, name, sizeof(name)-1); if(n < 0){ - closeopenfd(&conn->cfd); + close(cfd); return -1; } name[n] = 0; @@ -430,7 +159,7 @@ call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) p = strrchr(cname, '/'); *p = 0; if(ds->dir) - snprint(conn->dir, NETPATHLEN, "%s/%s", cname, name); + snprint(ds->dir, NETPATHLEN, "%s/%s", cname, name); snprint(data, sizeof(data), "%s/%s/data", cname, name); /* connect */ @@ -439,23 +168,20 @@ call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) else snprint(name, sizeof(name), "connect %s", dest); if(write(cfd, name, strlen(name)) < 0){ - closeopenfd(&conn->cfd); + close(cfd); return -1; } /* open data connection */ - conn->dfd = fd = open(data, ORDWR); + fd = open(data, ORDWR); if(fd < 0){ - closeopenfd(&conn->cfd); + close(cfd); return -1; } - if(ds->cfdp == nil) - closeopenfd(&conn->cfd); - - qlock(&dp->winlck); - if (dp->winner < 0 && conn < dp->connend) - dp->winner = conn - dp->conn; - qunlock(&dp->winlck); + if(ds->cfdp) + *ds->cfdp = cfd; + else + close(cfd); return fd; } |