[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] PATCH: 3 of 5: Remove virNetworkObjPtr linked list



This patch removes the linked list in the virNetworkObjPtr object, and
adds a new virNetworkObjList struct to track domains as an array. The
virtual network & test drivers get updated to account for this API
change.


 network_conf.c   |   88 +++++++++++++++++++++++-----------------
 network_conf.h   |   20 +++++----
 network_driver.c |  120 ++++++++++++++++++++++++-------------------------------
 test.c           |   75 ++++++++++++----------------------
 4 files changed, 145 insertions(+), 158 deletions(-)


Daniel

diff -r 25b5be9d400e src/network_conf.c
--- a/src/network_conf.c	Fri Oct 03 12:58:03 2008 +0100
+++ b/src/network_conf.c	Fri Oct 03 12:58:27 2008 +0100
@@ -69,28 +69,26 @@
 }
 
 
-virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjPtr nets,
+virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
                                       const unsigned char *uuid)
 {
-    virNetworkObjPtr net = nets;
-    while (net) {
-        if (!memcmp(net->def->uuid, uuid, VIR_UUID_BUFLEN))
-            return net;
-        net = net->next;
-    }
+    unsigned int i;
+
+    for (i = 0 ; i < nets->count ; i++)
+        if (!memcmp(nets->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
+            return nets->objs[i];
 
     return NULL;
 }
 
-virNetworkObjPtr virNetworkFindByName(const virNetworkObjPtr nets,
+virNetworkObjPtr virNetworkFindByName(const virNetworkObjListPtr nets,
                                       const char *name)
 {
-    virNetworkObjPtr net = nets;
-    while (net) {
-        if (STREQ(net->def->name, name))
-            return net;
-        net = net->next;
-    }
+    unsigned int i;
+
+    for (i = 0 ; i < nets->count ; i++)
+        if (STREQ(nets->objs[i]->def->name, name))
+            return nets->objs[i];
 
     return NULL;
 }
@@ -141,13 +139,24 @@
     VIR_FREE(net);
 }
 
+void virNetworkObjListFree(virNetworkObjListPtr nets)
+{
+    unsigned int i;
+
+    for (i = 0 ; i < nets->count ; i++)
+        virNetworkObjFree(nets->objs[i]);
+
+    VIR_FREE(nets->objs);
+    nets->count = 0;
+}
+
 virNetworkObjPtr virNetworkAssignDef(virConnectPtr conn,
-                                     virNetworkObjPtr *nets,
+                                     virNetworkObjListPtr nets,
                                      const virNetworkDefPtr def)
 {
     virNetworkObjPtr network;
 
-    if ((network = virNetworkFindByName(*nets, def->name))) {
+    if ((network = virNetworkFindByName(nets, def->name))) {
         if (!virNetworkIsActive(network)) {
             virNetworkDefFree(network->def);
             network->def = def;
@@ -166,34 +175,41 @@
     }
 
     network->def = def;
-    network->next = *nets;
 
-    *nets = network;
+    if (VIR_REALLOC_N(nets->objs, nets->count + 1) < 0) {
+        virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
+        VIR_FREE(network);
+        return NULL;
+    }
+
+    nets->objs[nets->count] = network;
+    nets->count++;
 
     return network;
 
 }
 
-void virNetworkRemoveInactive(virNetworkObjPtr *nets,
+void virNetworkRemoveInactive(virNetworkObjListPtr nets,
                               const virNetworkObjPtr net)
 {
-    virNetworkObjPtr prev = NULL;
-    virNetworkObjPtr curr = *nets;
+    unsigned int i;
 
-    while (curr &&
-           curr != net) {
-        prev = curr;
-        curr = curr->next;
+    for (i = 0 ; i < nets->count ; i++) {
+        if (nets->objs[i] == net) {
+            virNetworkObjFree(nets->objs[i]);
+
+            if (i < (nets->count - 1))
+                memmove(nets->objs + i, nets->objs + i + 1,
+                        sizeof(*(nets->objs)) * (nets->count - (i + 1)));
+
+            if (VIR_REALLOC_N(nets->objs, nets->count - 1) < 0) {
+                ; /* Failure to reduce memory allocation isn't fatal */
+            }
+            nets->count--;
+
+            break;
+        }
     }
-
-    if (curr) {
-        if (prev)
-            prev->next = curr->next;
-        else
-            *nets = curr->next;
-    }
-
-    virNetworkObjFree(net);
 }
 
 
@@ -699,7 +715,7 @@
 }
 
 virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn,
-                                      virNetworkObjPtr *nets,
+                                      virNetworkObjListPtr nets,
                                       const char *configDir,
                                       const char *autostartDir,
                                       const char *file)
@@ -753,7 +769,7 @@
 }
 
 int virNetworkLoadAllConfigs(virConnectPtr conn,
-                             virNetworkObjPtr *nets,
+                             virNetworkObjListPtr nets,
                              const char *configDir,
                              const char *autostartDir)
 {
diff -r 25b5be9d400e src/network_conf.h
--- a/src/network_conf.h	Fri Oct 03 12:58:03 2008 +0100
+++ b/src/network_conf.h	Fri Oct 03 12:58:27 2008 +0100
@@ -88,8 +88,13 @@
 
     virNetworkDefPtr def; /* The current definition */
     virNetworkDefPtr newDef; /* New definition to activate at shutdown */
+};
 
-    virNetworkObjPtr next;
+typedef struct _virNetworkObjList virNetworkObjList;
+typedef virNetworkObjList *virNetworkObjListPtr;
+struct _virNetworkObjList {
+    unsigned int count;
+    virNetworkObjPtr *objs;
 };
 
 static inline int
@@ -99,19 +104,20 @@
 }
 
 
-virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjPtr nets,
+virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
                                       const unsigned char *uuid);
-virNetworkObjPtr virNetworkFindByName(const virNetworkObjPtr nets,
+virNetworkObjPtr virNetworkFindByName(const virNetworkObjListPtr nets,
                                       const char *name);
 
 
 void virNetworkDefFree(virNetworkDefPtr def);
 void virNetworkObjFree(virNetworkObjPtr net);
+void virNetworkObjListFree(virNetworkObjListPtr vms);
 
 virNetworkObjPtr virNetworkAssignDef(virConnectPtr conn,
-                                     virNetworkObjPtr *nets,
+                                     virNetworkObjListPtr nets,
                                      const virNetworkDefPtr def);
-void virNetworkRemoveInactive(virNetworkObjPtr *nets,
+void virNetworkRemoveInactive(virNetworkObjListPtr nets,
                               const virNetworkObjPtr net);
 
 virNetworkDefPtr virNetworkDefParseString(virConnectPtr conn,
@@ -132,13 +138,13 @@
                          virNetworkObjPtr net);
 
 virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn,
-                                      virNetworkObjPtr *nets,
+                                      virNetworkObjListPtr nets,
                                       const char *configDir,
                                       const char *autostartDir,
                                       const char *file);
 
 int virNetworkLoadAllConfigs(virConnectPtr conn,
-                             virNetworkObjPtr *nets,
+                             virNetworkObjListPtr nets,
                              const char *configDir,
                              const char *autostartDir);
 
diff -r 25b5be9d400e src/network_driver.c
--- a/src/network_driver.c	Fri Oct 03 12:58:03 2008 +0100
+++ b/src/network_driver.c	Fri Oct 03 12:58:27 2008 +0100
@@ -58,7 +58,7 @@
 
 /* Main driver state */
 struct network_driver {
-    virNetworkObjPtr networks;
+    virNetworkObjList networks;
 
     iptablesContext *iptables;
     brControl *brctl;
@@ -114,23 +114,18 @@
 static struct network_driver *driverState = NULL;
 
 
-static
-void networkAutostartConfigs(struct network_driver *driver) {
-    virNetworkObjPtr network;
+static void
+networkAutostartConfigs(struct network_driver *driver) {
+    unsigned int i;
 
-    network = driver->networks;
-    while (network != NULL) {
-        virNetworkObjPtr next = network->next;
-
-        if (network->autostart &&
-            !virNetworkIsActive(network) &&
-            networkStartNetworkDaemon(NULL, driver, network) < 0) {
+    for (i = 0 ; i < driver->networks.count ; i++) {
+        if (driver->networks.objs[i]->autostart &&
+            !virNetworkIsActive(driver->networks.objs[i]) &&
+            networkStartNetworkDaemon(NULL, driver, driver->networks.objs[i]) < 0) {
             virErrorPtr err = virGetLastError();
             networkLog(NETWORK_ERR, _("Failed to autostart network '%s': %s\n"),
-                     network->def->name, err->message);
+                       driver->networks.objs[i]->def->name, err->message);
         }
-
-        network = next;
     }
 }
 
@@ -212,6 +207,9 @@
  */
 static int
 networkReload(void) {
+    if (!driverState)
+        return 0;
+
     virNetworkLoadAllConfigs(NULL,
                              &driverState->networks,
                              driverState->networkConfigDir,
@@ -238,13 +236,14 @@
  */
 static int
 networkActive(void) {
-    virNetworkObjPtr net = driverState->networks;
+    unsigned int i;
 
-    while (net) {
-        if (virNetworkIsActive(net))
+    if (!driverState)
+        return 0;
+
+    for (i = 0 ; i < driverState->networks.count ; i++)
+        if (virNetworkIsActive(driverState->networks.objs[i]))
             return 1;
-        net = net->next;
-    }
 
     /* Otherwise we're happy to deal with a shutdown */
     return 0;
@@ -257,28 +256,19 @@
  */
 static int
 networkShutdown(void) {
-    virNetworkObjPtr network;
+    unsigned int i;
 
     if (!driverState)
         return -1;
 
     /* shutdown active networks */
-    network = driverState->networks;
-    while (network) {
-        virNetworkObjPtr next = network->next;
-        if (virNetworkIsActive(network))
-            networkShutdownNetworkDaemon(NULL, driverState, network);
-        network = next;
-    }
+    for (i = 0 ; i < driverState->networks.count ; i++)
+        if (virNetworkIsActive(driverState->networks.objs[i]))
+            networkShutdownNetworkDaemon(NULL, driverState,
+                                         driverState->networks.objs[i]);
 
     /* free inactive networks */
-    network = driverState->networks;
-    while (network) {
-        virNetworkObjPtr next = network->next;
-        virNetworkObjFree(network);
-        network = next;
-    }
-    driverState->networks = NULL;
+    virNetworkObjListFree(&driverState->networks);
 
     VIR_FREE(driverState->logDir);
     VIR_FREE(driverState->networkConfigDir);
@@ -840,7 +830,7 @@
 static virNetworkPtr networkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
                                               const unsigned char *uuid) {
     struct network_driver *driver = (struct network_driver *)conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, uuid);
     virNetworkPtr net;
 
     if (!network) {
@@ -855,7 +845,7 @@
 static virNetworkPtr networkLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED,
                                               const char *name) {
     struct network_driver *driver = (struct network_driver *)conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByName(driver->networks, name);
+    virNetworkObjPtr network = virNetworkFindByName(&driver->networks, name);
     virNetworkPtr net;
 
     if (!network) {
@@ -885,31 +875,29 @@
 }
 
 static int networkNumNetworks(virConnectPtr conn) {
-    int nactive = 0;
+    int nactive = 0, i;
     struct network_driver *driver = (struct network_driver *)conn->networkPrivateData;
-    virNetworkObjPtr net = driver->networks;
-    while (net) {
-        if (virNetworkIsActive(net))
+
+    for (i = 0 ; i < driver->networks.count ; i++)
+        if (virNetworkIsActive(driver->networks.objs[i]))
             nactive++;
-        net = net->next;
-    }
+
     return nactive;
 }
 
 static int networkListNetworks(virConnectPtr conn, char **const names, int nnames) {
     struct network_driver *driver = (struct network_driver *)conn->networkPrivateData;
-    virNetworkObjPtr network = driver->networks;
     int got = 0, i;
-    while (network && got < nnames) {
-        if (virNetworkIsActive(network)) {
-            if (!(names[got] = strdup(network->def->name))) {
+
+    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
+        if (virNetworkIsActive(driver->networks.objs[i])) {
+            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
                 networkReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                     "%s", _("failed to allocate space for VM name string"));
+                                   "%s", _("failed to allocate space for VM name string"));
                 goto cleanup;
             }
             got++;
         }
-        network = network->next;
     }
     return got;
 
@@ -920,31 +908,29 @@
 }
 
 static int networkNumDefinedNetworks(virConnectPtr conn) {
-    int ninactive = 0;
+    int ninactive = 0, i;
     struct network_driver *driver = (struct network_driver *)conn->networkPrivateData;
-    virNetworkObjPtr net = driver->networks;
-    while (net) {
-        if (!virNetworkIsActive(net))
+
+    for (i = 0 ; i < driver->networks.count ; i++)
+        if (!virNetworkIsActive(driver->networks.objs[i]))
             ninactive++;
-        net = net->next;
-    }
+
     return ninactive;
 }
 
 static int networkListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
     struct network_driver *driver = (struct network_driver *)conn->networkPrivateData;
-    virNetworkObjPtr network = driver->networks;
     int got = 0, i;
-    while (network && got < nnames) {
-        if (!virNetworkIsActive(network)) {
-            if (!(names[got] = strdup(network->def->name))) {
+
+    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
+        if (!virNetworkIsActive(driver->networks.objs[i])) {
+            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
                 networkReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
-                     "%s", _("failed to allocate space for VM name string"));
+                                   "%s", _("failed to allocate space for VM name string"));
                 goto cleanup;
             }
             got++;
         }
-        network = network->next;
     }
     return got;
 
@@ -1009,7 +995,7 @@
 
 static int networkUndefine(virNetworkPtr net) {
     struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid);
 
     if (!network) {
         networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_DOMAIN,
@@ -1034,7 +1020,7 @@
 
 static int networkStart(virNetworkPtr net) {
     struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid);
 
     if (!network) {
         networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@@ -1047,7 +1033,7 @@
 
 static int networkDestroy(virNetworkPtr net) {
     struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid);
     int ret;
 
     if (!network) {
@@ -1063,7 +1049,7 @@
 
 static char *networkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) {
     struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid);
 
     if (!network) {
         networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@@ -1076,7 +1062,7 @@
 
 static char *networkGetBridgeName(virNetworkPtr net) {
     struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid);
     char *bridge;
     if (!network) {
         networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@@ -1096,7 +1082,7 @@
 static int networkGetAutostart(virNetworkPtr net,
                              int *autostart) {
     struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid);
 
     if (!network) {
         networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
@@ -1112,7 +1098,7 @@
 static int networkSetAutostart(virNetworkPtr net,
                              int autostart) {
     struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData;
-    virNetworkObjPtr network = virNetworkFindByUUID(driver->networks, net->uuid);
+    virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid);
 
     if (!network) {
         networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
diff -r 25b5be9d400e src/test.c
--- a/src/test.c	Fri Oct 03 12:58:03 2008 +0100
+++ b/src/test.c	Fri Oct 03 12:58:27 2008 +0100
@@ -58,7 +58,7 @@
     virCapsPtr caps;
     virNodeInfo nodeInfo;
     virDomainObjList domains;
-    virNetworkObjPtr networks;
+    virNetworkObjList networks;
     int numCells;
     testCell cells[MAX_CELLS];
 };
@@ -100,7 +100,7 @@
                                                                         \
     privconn = (testConnPtr)net->conn->privateData;                     \
     do {                                                                \
-        if ((privnet = virNetworkFindByName(privconn->networks,         \
+        if ((privnet = virNetworkFindByName(&privconn->networks,        \
                                             (net)->name)) == NULL) {    \
             testError((net)->conn, NULL, (net), VIR_ERR_INVALID_ARG,    \
                       __FUNCTION__);                                    \
@@ -273,7 +273,7 @@
 
 error:
     virDomainObjListFree(&privconn->domains);
-    virNetworkObjFree(privconn->networks);
+    virNetworkObjListFree(&privconn->networks);
     virCapabilitiesFree(privconn->caps);
     VIR_FREE(privconn);
     return VIR_DRV_OPEN_ERROR;
@@ -508,12 +508,7 @@
     if (fd != -1)
         close(fd);
     virDomainObjListFree(&privconn->domains);
-    net = privconn->networks;
-    while (net) {
-        virNetworkObjPtr tmp = net->next;
-        virNetworkObjFree(net);
-        net = tmp;
-    }
+    virNetworkObjListFree(&privconn->networks);
     VIR_FREE(privconn);
     conn->privateData = NULL;
     return VIR_DRV_OPEN_ERROR;
@@ -560,16 +555,12 @@
 
 static int testClose(virConnectPtr conn)
 {
-    virNetworkObjPtr net;
     GET_CONNECTION(conn);
+
     virCapabilitiesFree(privconn->caps);
     virDomainObjListFree(&privconn->domains);
-    net = privconn->networks;
-    while (net) {
-        virNetworkObjPtr tmp = net->next;
-        virNetworkObjFree(net);
-        net = tmp;
-    }
+    virNetworkObjListFree(&privconn->networks);
+
     VIR_FREE (privconn);
     conn->privateData = conn;
     return 0;
@@ -1293,7 +1284,7 @@
     virNetworkObjPtr net = NULL;
     GET_CONNECTION(conn);
 
-    if ((net = virNetworkFindByUUID(privconn->networks, uuid)) == NULL) {
+    if ((net = virNetworkFindByUUID(&privconn->networks, uuid)) == NULL) {
         testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL);
         return NULL;
     }
@@ -1307,7 +1298,7 @@
     virNetworkObjPtr net = NULL;
     GET_CONNECTION(conn);
 
-    if ((net = virNetworkFindByName(privconn->networks, name)) == NULL) {
+    if ((net = virNetworkFindByName(&privconn->networks, name)) == NULL) {
         testError (conn, NULL, NULL, VIR_ERR_NO_NETWORK, NULL);
         return NULL;
     }
@@ -1317,32 +1308,26 @@
 
 
 static int testNumNetworks(virConnectPtr conn) {
-    int numActive = 0;
-    virNetworkObjPtr net;
+    int numActive = 0, i;
     GET_CONNECTION(conn);
 
-    net = privconn->networks;
-    while (net) {
-        if (virNetworkIsActive(net))
+    for (i = 0 ; i < privconn->networks.count ; i++)
+        if (virNetworkIsActive(privconn->networks.objs[i]))
             numActive++;
-        net = net->next;
-    }
+
     return numActive;
 }
 
 static int testListNetworks(virConnectPtr conn, char **const names, int nnames) {
-    int n = 0;
-    virNetworkObjPtr net;
+    int n = 0, i;
     GET_CONNECTION(conn);
 
-    net = privconn->networks;
     memset(names, 0, sizeof(*names)*nnames);
-    while (net && n < nnames) {
-        if (virNetworkIsActive(net) &&
-            !(names[n++] = strdup(net->def->name)))
+    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++)
+        if (virNetworkIsActive(privconn->networks.objs[i]) &&
+            !(names[n++] = strdup(privconn->networks.objs[i]->def->name)))
             goto no_memory;
-        net = net->next;
-    }
+
     return n;
 
 no_memory:
@@ -1353,32 +1338,26 @@
 }
 
 static int testNumDefinedNetworks(virConnectPtr conn) {
-    int numInactive = 0;
-    virNetworkObjPtr net;
+    int numInactive = 0, i;
     GET_CONNECTION(conn);
 
-    net = privconn->networks;
-    while (net) {
-        if (!virNetworkIsActive(net))
+    for (i = 0 ; i < privconn->networks.count ; i++)
+        if (!virNetworkIsActive(privconn->networks.objs[i]))
             numInactive++;
-        net = net->next;
-    }
+
     return numInactive;
 }
 
 static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
-    int n = 0;
-    virNetworkObjPtr net;
+    int n = 0, i;
     GET_CONNECTION(conn);
 
-    net = privconn->networks;
     memset(names, 0, sizeof(*names)*nnames);
-    while (net && n < nnames) {
-        if (!virNetworkIsActive(net) &&
-            !(names[n++] = strdup(net->def->name)))
+    for (i = 0 ; i < privconn->networks.count && n < nnames ; i++)
+        if (!virNetworkIsActive(privconn->networks.objs[i]) &&
+            !(names[n++] = strdup(privconn->networks.objs[i]->def->name)))
             goto no_memory;
-        net = net->next;
-    }
+
     return n;
 
 no_memory:


-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]