00001
00002
00003
00004
00005
00006
00007
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
00081
00082
00083
00084
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
00109
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
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
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 }