]> git.ozlabs.org Git - ccan-lca-2011.git/commitdiff
lca2011: avoid loops during dumping.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 25 Jan 2011 00:31:25 +0000 (11:01 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 25 Jan 2011 00:31:25 +0000 (11:01 +1030)
CDUMP_IGNORE the client->oserver back-pointer, and switch the subclient
and oracle to be indices into oserver->clients[] rather than pointers.

ccan/oserver/oserver.c
ccan/oserver/oserver_types.h

index 317a01cc5e2f177bcf7b9337c88560958b85d035..0ec1b6840ee40ea1ae548e9e300590e44f7d1f3d 100644 (file)
@@ -86,9 +86,9 @@ static bool get_subclient(struct client *me)
                struct client *c = me->oserver->clients[i];
                if (!c || c == me)
                        continue;
-               if (c->oracle == NULL && input_finished(c->question)) {
-                       me->subclient = c;
-                       c->oracle = me;
+               if (c->oracle == -1 && input_finished(c->question)) {
+                       me->subclient = c->id;
+                       c->oracle = me->id;
                        return true;
                }
        }
@@ -103,9 +103,9 @@ static bool get_oracle(struct client *me)
                struct client *c = me->oserver->clients[i];
                if (!c || c == me)
                        continue;
-               if (c->subclient == NULL && input_finished(c->question)) {
-                       me->oracle = c;
-                       c->subclient = me;
+               if (c->subclient == -1 && input_finished(c->question)) {
+                       me->oracle = c->id;
+                       c->subclient = me->id;
                        return true;
                }
        }
@@ -136,27 +136,29 @@ static void service_client(struct tevent_context *ev,
                        set_state(c, SENDING_OTHER_QUESTION_PREFIX);
                break;
        case SENDING_OTHER_QUESTION_PREFIX:
-               if (!c->subclient)
+               if (c->subclient == -1)
                        goto need_subclient;
                if (!send_string(c, "While the Oracle ponders,"
                                 " please answer the following question:\n"))
                        goto fail;
                break;
        case SENDING_OTHER_QUESTION:
-               if (!c->subclient)
+               if (c->subclient == -1)
                        goto need_subclient;
-               if (!send_string(c, c->subclient->question))
+               if (!send_string(c,
+                                c->oserver->clients[c->subclient]->question))
                        goto fail;
                break;
        case RECEIVING_OTHER_ANSWER:
-               if (!c->subclient)
+               if (c->subclient == -1)
                        goto need_subclient;
-               len = read_string(c->fd, &c->subclient->answer);
+               len = read_string(c->fd,
+                                 &c->oserver->clients[c->subclient]->answer);
                if (len <= 0)
                        goto fail;
-               if (input_finished(c->subclient->answer)) {
+               if (input_finished(c->oserver->clients[c->subclient]->answer)) {
                        set_state(c, SENDING_ANSWER_PREFIX);
-                       wakeup(c->subclient);
+                       wakeup(c->oserver->clients[c->subclient]);
                }
                break;
        case SENDING_ANSWER_PREFIX:
@@ -185,14 +187,14 @@ need_subclient:
                tevent_fd_set_flags(c->fde, 0);
        } else
                /* In case they are waiting... */
-               wakeup(c->subclient);
+               wakeup(c->oserver->clients[c->subclient]);
        return;
 
 need_answer:
        /* If we don't have an oracle and find one, that's OK. */
-       if (!c->oracle && get_oracle(c)) {
+       if (c->oracle == -1 && get_oracle(c)) {
                /* In case they are waiting... */
-               wakeup(c->oracle);
+               wakeup(c->oserver->clients[c->oracle]);
                return;
        }
 
@@ -202,25 +204,18 @@ need_answer:
 
 static int cleanup_client(struct client *client)
 {
-       unsigned int i;
 
        /* We were an oracle? */
-       if (client->subclient)
-               client->subclient->oracle = NULL;
+       if (client->subclient >= 0)
+               client->oserver->clients[client->subclient]->oracle = -1;
 
        /* We had an oracle? */
-       if (client->oracle)
-               client->oracle->subclient = NULL;
-
-       for (i = 0; i < ARRAY_SIZE(client->oserver->clients); i++) {
-               if (client->oserver->clients[i] == client) {
-                       client->oserver->clients[i] = NULL;
-                       tevent_fd_set_flags(client->oserver->fde,
-                                           TEVENT_FD_READ);
-                       return 0;
-               }
-       }
-       abort();
+       if (client->oracle >= 0)
+               client->oserver->clients[client->oracle]->subclient = -1;
+
+       assert(client->oserver->clients[client->id] == client);
+       client->oserver->clients[client->id] = NULL;
+       return 0;
 }
 
 static void add_client(struct tevent_context *ev,
@@ -228,7 +223,6 @@ static void add_client(struct tevent_context *ev,
 {
        struct oserver *oserver = _oserver;
        struct client *client;
-       unsigned int i;
 
        client = talloc(oserver, struct client);
        client->fd = accept(oserver->fd, NULL, 0);
@@ -239,8 +233,8 @@ static void add_client(struct tevent_context *ev,
        client->bytes_sent = 0;
        client->question = talloc_strdup(client, "");
        client->oserver = oserver;
-       client->oracle = NULL;
-       client->subclient = NULL;
+       client->oracle = -1;
+       client->subclient = -1;
        client->answer = talloc_strdup(client, "");
        client->fde = tevent_add_fd(ev, client, client->fd,
                                    state_flag_map[client->state],
@@ -248,12 +242,12 @@ static void add_client(struct tevent_context *ev,
        tevent_fd_set_auto_close(client->fde);
 
        /* Find empty slot in array for this client. */
-       for (i = 0; oserver->clients[i]; i++);
-       oserver->clients[i] = client;
+       for (client->id = 0; oserver->clients[client->id]; client->id++);
+       oserver->clients[client->id] = client;
        talloc_set_destructor(client, cleanup_client);
 
        /* Full?  Stop listening... */
-       if (i == ARRAY_SIZE(oserver->clients)-1)
+       if (client->id == ARRAY_SIZE(oserver->clients)-1)
                tevent_fd_set_flags(oserver->fde, 0);
 }
 
index 4eabc67a06a6c0e155f27c3f8856db51fd5b9bbb..72717e89733ddf1793fd514988f7976b8740e4bc 100644 (file)
@@ -20,6 +20,8 @@ CDUMP_SAVED struct client {
        /* Our event info, and the file descriptor. */
        struct tevent_fd *fde CDUMP_IGNORE;
        int fd;
+       /* Position in oserver's clients array. */
+       unsigned int id;
        /* The question we read from client. */
        char *question;
        /* The answer to the client. */
@@ -27,11 +29,11 @@ CDUMP_SAVED struct client {
        /* How many bytes of the reply we sent so far. */
        size_t bytes_sent;
        /* Our server. */
-       struct oserver *oserver;
-       /* Whose question this client is answering. */
-       struct client *subclient;
-       /* Who is answering our question. */
-       struct client *oracle;
+       struct oserver *oserver CDUMP_IGNORE;
+       /* Whose question this client is answering (-1 for none) */
+       int subclient;
+       /* Who is answering our question (-1 for none) */
+       int oracle;
 };
 
 CDUMP_SAVED struct oserver {