Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

ex_rq_client.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2001-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: ex_rq_client.c,v 12.7 2005/11/02 22:14:24 alanb Exp $
00008  */
00009 
00010 #include <sys/types.h>
00011 #include <errno.h>
00012 #include <signal.h>
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <string.h>
00016 
00017 #include <db.h>
00018 
00019 #include "ex_repquote.h"
00020 
00021 static void *check_loop __P((void *));
00022 static void *display_loop __P((void *));
00023 static int print_stocks __P((DBC *));
00024 
00025 typedef struct {
00026         const char *progname;
00027         DB_ENV *dbenv;
00028 } disploop_args;
00029 
00030 typedef struct {
00031         DB_ENV *dbenv;
00032         machtab_t *machtab;
00033         const char *progname;
00034 } checkloop_args;
00035 
00036 int
00037 doclient(dbenv, progname, machtab)
00038         DB_ENV *dbenv;
00039         const char *progname;
00040         machtab_t *machtab;
00041 {
00042         checkloop_args cargs;
00043         disploop_args dargs;
00044         thread_t check_thr, disp_thr;
00045         void *cstatus, *dstatus;
00046         int rval, s;
00047 
00048         rval = EXIT_SUCCESS;
00049         s = -1;
00050 
00051         memset(&dargs, 0, sizeof(dargs));
00052 
00053         dargs.progname = progname;
00054         dargs.dbenv = dbenv;
00055         if (thread_create(&disp_thr, NULL, display_loop, (void *)&dargs)) {
00056                 dbenv->errx(dbenv, "display_loop thread creation failed");
00057                 goto err;
00058         }
00059 
00060         cargs.dbenv = dbenv;
00061         cargs.machtab = machtab;
00062         cargs.progname = progname;
00063         if (thread_create(&check_thr, NULL, check_loop, (void *)&cargs)) {
00064                 dbenv->errx(dbenv, "check_thread pthread_create failed");
00065                 goto err;
00066         }
00067         if (thread_join(disp_thr, &dstatus) ||
00068             thread_join(check_thr, &cstatus)) {
00069                 dbenv->errx(dbenv, "pthread_join failed");
00070                 goto err;
00071         }
00072 
00073         if (0) {
00074 err:            rval = EXIT_FAILURE;
00075         }
00076         return (rval);
00077 }
00078 
00079 /*
00080  * Our only job is to check that the master is valid and if it's not
00081  * for an extended period, to trigger an election.  We do two phases.
00082  * If we do not have a master, first we send out a request for a master
00083  * to identify itself (that would be a call to rep_start).  If that fails,
00084  * we trigger an election.
00085  */
00086 static void *
00087 check_loop(args)
00088         void *args;
00089 {
00090         DB_ENV *dbenv;
00091         DBT dbt;
00092         const char *progname;
00093         checkloop_args *cargs;
00094         int count, n, pri;
00095         machtab_t *machtab;
00096         u_int32_t timeout;
00097 
00098         cargs = (checkloop_args *)args;
00099         dbenv = cargs->dbenv;
00100         machtab = cargs->machtab;
00101         progname = cargs->progname;
00102 
00103 #define IDLE_INTERVAL   1
00104 
00105         count = 0;
00106         while (master_eid == DB_EID_INVALID) {
00107                 /*
00108                  * Call either rep_start or rep_elect depending on if
00109                  * count is 0 or 1.
00110                  */
00111 
00112                 if (count == 0) {
00113                         memset(&dbt, 0, sizeof(dbt));
00114                         dbt.data = myaddr;
00115                         dbt.size = (u_int32_t)strlen(myaddr) + 1;
00116                         (void)dbenv->rep_start(dbenv, &dbt, DB_REP_CLIENT);
00117                         count = 1;
00118                 } else {
00119                         machtab_parm(machtab, &n, &pri, &timeout);
00120                         if (dbenv->rep_elect(dbenv,
00121                             n, (n/2+1), pri, timeout, &master_eid, 0) == 0)
00122                                 break;
00123                         count = 0;
00124                 }
00125                 sleep(IDLE_INTERVAL);
00126         }
00127 
00128         /* Check if I won the election. */
00129         if (master_eid == SELF_EID &&
00130             dbenv->rep_start(dbenv, NULL, DB_REP_MASTER) == 0)
00131                 (void)domaster(dbenv, progname);
00132 
00133         return (NULL);
00134 }
00135 
00136 static void *
00137 display_loop(args)
00138         void *args;
00139 {
00140         DB *dbp;
00141         DB_ENV *dbenv;
00142         DBC *dbc;
00143         const char *progname;
00144         disploop_args *dargs;
00145         int ret, t_ret;
00146 
00147         dargs = (disploop_args *)args;
00148         progname = dargs->progname;
00149         dbenv = dargs->dbenv;
00150 
00151         dbc = NULL;
00152         dbp = NULL;
00153 
00154 retry:  for (;;) {
00155                 ret = 0;
00156 
00157                 /* If we become master, shut this loop off. */
00158                 if (master_eid == SELF_EID)
00159                         break;
00160 
00161                 if (dbp == NULL) {
00162                         if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
00163                                 dbenv->err(dbenv, ret, "db_create");
00164                                 goto err;
00165                         }
00166 
00167                         if ((ret = dbp->open(dbp, NULL,
00168                             DATABASE, NULL, DB_BTREE, DB_RDONLY, 0)) != 0) {
00169                                 if (ret == ENOENT) {
00170                                         printf(
00171                                     "No stock database yet available.\n");
00172                                         if ((ret = dbp->close(dbp, 0)) != 0) {
00173                                                 dbenv->err(dbenv,
00174                                                     ret, "DB->close");
00175                                                 goto err;
00176                                         }
00177                                         dbp = NULL;
00178                                         sleep(SLEEPTIME);
00179                                         continue;
00180                                 }
00181                                 dbenv->err(dbenv, ret, "DB->open");
00182                                 goto err;
00183                         }
00184                 }
00185 
00186                 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
00187                         dbenv->err(dbenv, ret, "DB->cursor");
00188                 else {
00189                         if ((ret = print_stocks(dbc)) != 0)
00190                                 dbenv->err(dbenv, ret,
00191                                     "database traversal failed");
00192 
00193                         if ((t_ret = dbc->c_close(dbc)) != 0) {
00194                                 dbenv->err(dbenv, ret, "DBC->c_close");
00195                                 if (ret == 0)
00196                                         ret = t_ret;
00197                         }
00198                 }
00199                 if (ret != 0)
00200                         goto err;
00201 
00202                 dbc = NULL;
00203                 sleep(SLEEPTIME);
00204         }
00205 
00206 err:    switch (ret) {
00207         case DB_LOCK_DEADLOCK:
00208                 if (dbc != NULL) {
00209                         ret = dbc->c_close(dbc);
00210                         dbc = NULL;
00211                         if (ret != 0)
00212                                 break;
00213                 }
00214                 goto retry;
00215         case DB_REP_HANDLE_DEAD:
00216                 if (dbp != NULL) {
00217                         ret = dbp->close(dbp, DB_NOSYNC);
00218                         dbp = NULL;
00219                         if (ret != 0)
00220                                 break;
00221                 }
00222                 goto retry;
00223         default:
00224                 break;
00225         }
00226 
00227         if (dbp != NULL && (t_ret = dbp->close(dbp, 0)) != 0) {
00228                 dbenv->err(dbenv, t_ret, "DB->close");
00229                 if (ret == 0)
00230                         ret = t_ret;
00231         }
00232 
00233         return (NULL);
00234 }
00235 
00236 static int
00237 print_stocks(dbc)
00238         DBC *dbc;
00239 {
00240         DBT key, data;
00241 #define MAXKEYSIZE      10
00242 #define MAXDATASIZE     20
00243         char keybuf[MAXKEYSIZE + 1], databuf[MAXDATASIZE + 1];
00244         int ret;
00245         u_int32_t keysize, datasize;
00246 
00247         memset(&key, 0, sizeof(key));
00248         memset(&data, 0, sizeof(data));
00249 
00250         printf("\tSymbol\tPrice\n");
00251         printf("\t======\t=====\n");
00252 
00253         for (ret = dbc->c_get(dbc, &key, &data, DB_FIRST);
00254             ret == 0;
00255             ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) {
00256                 keysize = key.size > MAXKEYSIZE ? MAXKEYSIZE : key.size;
00257                 memcpy(keybuf, key.data, keysize);
00258                 keybuf[keysize] = '\0';
00259 
00260                 datasize = data.size >= MAXDATASIZE ? MAXDATASIZE : data.size;
00261                 memcpy(databuf, data.data, datasize);
00262                 databuf[datasize] = '\0';
00263 
00264                 printf("\t%s\t%s\n", keybuf, databuf);
00265         }
00266         printf("\n");
00267         return (ret == DB_NOTFOUND ? 0 : ret);
00268 }

Generated on Sun Dec 25 12:14:25 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2