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

tcl_rep.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1999-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: tcl_rep.c,v 12.11 2005/10/14 20:15:33 sue Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <tcl.h>
00018 #endif
00019 
00020 #include "db_int.h"
00021 #include "dbinc/tcl_db.h"
00022 
00023 #ifdef CONFIG_TEST
00024 /*
00025  * tcl_RepConfig --
00026  *      Call DB_ENV->rep_set_config().
00027  *
00028  * PUBLIC: int tcl_RepConfig
00029  * PUBLIC:     __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *));
00030  */
00031 int
00032 tcl_RepConfig(interp, dbenv, list)
00033         Tcl_Interp *interp;             /* Interpreter */
00034         DB_ENV *dbenv;                  /* Environment pointer */
00035         Tcl_Obj *list;                  /* {which on|off} */
00036 {
00037         static const char *confwhich[] = {
00038                 "bulk",
00039                 "delayclient",
00040                 "noautoinit",
00041                 "nowait",
00042                 NULL
00043         };
00044         enum confwhich {
00045                 REPCONF_BULK,
00046                 REPCONF_DELAYCLIENT,
00047                 REPCONF_NOAUTOINIT,
00048                 REPCONF_NOWAIT
00049         };
00050         static const char *confonoff[] = {
00051                 "off",
00052                 "on",
00053                 NULL
00054         };
00055         enum confonoff {
00056                 REPCONF_OFF,
00057                 REPCONF_ON
00058         };
00059         Tcl_Obj **myobjv, *onoff, *which;
00060         int myobjc, on, optindex, result, ret;
00061         u_int32_t wh;
00062 
00063         result = Tcl_ListObjGetElements(interp, list, &myobjc, &myobjv);
00064         which = myobjv[0];
00065         onoff = myobjv[1];
00066         if (result != TCL_OK)
00067                 return (result);
00068         if (Tcl_GetIndexFromObj(interp, which, confwhich, "option",
00069             TCL_EXACT, &optindex) != TCL_OK)
00070                 return (IS_HELP(which));
00071 
00072         switch ((enum confwhich)optindex) {
00073         case REPCONF_NOAUTOINIT:
00074                 wh = DB_REP_CONF_NOAUTOINIT;
00075                 break;
00076         case REPCONF_BULK:
00077                 wh = DB_REP_CONF_BULK;
00078                 break;
00079         case REPCONF_DELAYCLIENT:
00080                 wh = DB_REP_CONF_DELAYCLIENT;
00081                 break;
00082         case REPCONF_NOWAIT:
00083                 wh = DB_REP_CONF_NOWAIT;
00084                 break;
00085         default:
00086                 return (TCL_ERROR);
00087         }
00088         if (Tcl_GetIndexFromObj(interp, onoff, confonoff, "option",
00089             TCL_EXACT, &optindex) != TCL_OK)
00090                 return (IS_HELP(onoff));
00091         switch ((enum confonoff)optindex) {
00092         case REPCONF_OFF:
00093                 on = 0;
00094                 break;
00095         case REPCONF_ON:
00096                 on = 1;
00097                 break;
00098         default:
00099                 return (TCL_ERROR);
00100         }
00101         ret = dbenv->rep_set_config(dbenv, wh, on);
00102         return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00103             "env rep_config"));
00104 }
00105 
00106 /*
00107  * tcl_RepGetConfig --
00108  *      Call DB_ENV->rep_get_config().
00109  *
00110  * PUBLIC: int tcl_RepGetConfig
00111  * PUBLIC:     __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *));
00112  */
00113 int
00114 tcl_RepGetConfig(interp, dbenv, which)
00115         Tcl_Interp *interp;             /* Interpreter */
00116         DB_ENV *dbenv;                  /* Environment pointer */
00117         Tcl_Obj *which;                 /* which flag */
00118 {
00119         static const char *confwhich[] = {
00120                 "bulk",
00121                 "delayclient",
00122                 "noautoinit",
00123                 "nowait",
00124                 NULL
00125         };
00126         enum confwhich {
00127                 REPGCONF_BULK,
00128                 REPGCONF_DELAYCLIENT,
00129                 REPGCONF_NOAUTOINIT,
00130                 REPGCONF_NOWAIT
00131         };
00132         Tcl_Obj *res;
00133         int on, optindex, result, ret;
00134         u_int32_t wh;
00135 
00136         if (Tcl_GetIndexFromObj(interp, which, confwhich, "option",
00137             TCL_EXACT, &optindex) != TCL_OK)
00138                 return (IS_HELP(which));
00139 
00140         res = NULL;
00141         switch ((enum confwhich)optindex) {
00142         case REPGCONF_BULK:
00143                 wh = DB_REP_CONF_BULK;
00144                 break;
00145         case REPGCONF_DELAYCLIENT:
00146                 wh = DB_REP_CONF_DELAYCLIENT;
00147                 break;
00148         case REPGCONF_NOAUTOINIT:
00149                 wh = DB_REP_CONF_NOAUTOINIT;
00150                 break;
00151         case REPGCONF_NOWAIT:
00152                 wh = DB_REP_CONF_NOWAIT;
00153                 break;
00154         default:
00155                 return (TCL_ERROR);
00156         }
00157         ret = dbenv->rep_get_config(dbenv, wh, &on);
00158         if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00159             "env rep_config")) == TCL_OK) {
00160                 res = Tcl_NewIntObj(on);
00161                 Tcl_SetObjResult(interp, res);
00162         }
00163         return (result);
00164 }
00165 #endif
00166 
00167 #ifdef CONFIG_TEST
00168 /*
00169  * tcl_RepElect --
00170  *      Call DB_ENV->rep_elect().
00171  *
00172  * PUBLIC: int tcl_RepElect
00173  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00174  */
00175 int
00176 tcl_RepElect(interp, objc, objv, dbenv)
00177         Tcl_Interp *interp;             /* Interpreter */
00178         int objc;                       /* How many arguments? */
00179         Tcl_Obj *CONST objv[];          /* The argument objects */
00180         DB_ENV *dbenv;                  /* Environment pointer */
00181 {
00182         int eid, nsites, nvotes, pri, result, ret;
00183         u_int32_t timeout;
00184 
00185         if (objc != 6) {
00186                 Tcl_WrongNumArgs(interp, 6, objv, "nsites pri timeout");
00187                 return (TCL_ERROR);
00188         }
00189 
00190         if ((result = Tcl_GetIntFromObj(interp, objv[2], &nsites)) != TCL_OK)
00191                 return (result);
00192         if ((result = Tcl_GetIntFromObj(interp, objv[3], &nvotes)) != TCL_OK)
00193                 return (result);
00194         if ((result = Tcl_GetIntFromObj(interp, objv[4], &pri)) != TCL_OK)
00195                 return (result);
00196         if ((result = _GetUInt32(interp, objv[5], &timeout)) != TCL_OK)
00197                 return (result);
00198 
00199         _debug_check();
00200         if ((ret = dbenv->rep_elect(dbenv, nsites, nvotes,
00201             pri, timeout, &eid, 0)) != 0)
00202                 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00203                     "env rep_elect"));
00204 
00205         Tcl_SetObjResult(interp, Tcl_NewIntObj(eid));
00206 
00207         return (TCL_OK);
00208 }
00209 #endif
00210 
00211 #ifdef CONFIG_TEST
00212 /*
00213  * tcl_RepFlush --
00214  *      Call DB_ENV->rep_flush().
00215  *
00216  * PUBLIC: int tcl_RepFlush
00217  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00218  */
00219 int
00220 tcl_RepFlush(interp, objc, objv, dbenv)
00221         Tcl_Interp *interp;
00222         int objc;
00223         Tcl_Obj *CONST objv[];
00224         DB_ENV *dbenv;
00225 {
00226         int ret;
00227 
00228         if (objc != 2) {
00229                 Tcl_WrongNumArgs(interp, 2, objv, "");
00230                 return TCL_ERROR;
00231         }
00232 
00233         _debug_check();
00234         ret = dbenv->rep_flush(dbenv);
00235         return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_flush"));
00236 }
00237 #endif
00238 #ifdef CONFIG_TEST
00239 /*
00240  * tcl_RepSync --
00241  *      Call DB_ENV->rep_sync().
00242  *
00243  * PUBLIC: int tcl_RepSync
00244  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00245  */
00246 int
00247 tcl_RepSync(interp, objc, objv, dbenv)
00248         Tcl_Interp *interp;
00249         int objc;
00250         Tcl_Obj *CONST objv[];
00251         DB_ENV *dbenv;
00252 {
00253         int ret;
00254 
00255         if (objc != 2) {
00256                 Tcl_WrongNumArgs(interp, 2, objv, "");
00257                 return TCL_ERROR;
00258         }
00259 
00260         _debug_check();
00261         ret = dbenv->rep_sync(dbenv, 0);
00262         return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_sync"));
00263 }
00264 #endif
00265 #ifdef CONFIG_TEST
00266 /*
00267  * tcl_RepLimit --
00268  *      Call DB_ENV->set_rep_limit().
00269  *
00270  * PUBLIC: int tcl_RepLimit
00271  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00272  */
00273 int
00274 tcl_RepLimit(interp, objc, objv, dbenv)
00275         Tcl_Interp *interp;             /* Interpreter */
00276         int objc;                       /* How many arguments? */
00277         Tcl_Obj *CONST objv[];          /* The argument objects */
00278         DB_ENV *dbenv;                  /* Environment pointer */
00279 {
00280         int result, ret;
00281         u_int32_t bytes, gbytes;
00282 
00283         if (objc != 4) {
00284                 Tcl_WrongNumArgs(interp, 4, objv, "gbytes bytes");
00285                 return (TCL_ERROR);
00286         }
00287 
00288         if ((result = _GetUInt32(interp, objv[2], &gbytes)) != TCL_OK)
00289                 return (result);
00290         if ((result = _GetUInt32(interp, objv[3], &bytes)) != TCL_OK)
00291                 return (result);
00292 
00293         _debug_check();
00294         if ((ret = dbenv->set_rep_limit(dbenv, gbytes, bytes)) != 0)
00295                 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00296                     "env set_rep_limit"));
00297 
00298         return (_ReturnSetup(interp,
00299             ret, DB_RETOK_STD(ret), "env set_rep_limit"));
00300 }
00301 #endif
00302 
00303 #ifdef CONFIG_TEST
00304 /*
00305  * tcl_RepRequest --
00306  *      Call DB_ENV->set_rep_request().
00307  *
00308  * PUBLIC: int tcl_RepRequest
00309  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00310  */
00311 int
00312 tcl_RepRequest(interp, objc, objv, dbenv)
00313         Tcl_Interp *interp;             /* Interpreter */
00314         int objc;                       /* How many arguments? */
00315         Tcl_Obj *CONST objv[];          /* The argument objects */
00316         DB_ENV *dbenv;                  /* Environment pointer */
00317 {
00318         int result, ret;
00319         u_int32_t min, max;
00320 
00321         if (objc != 4) {
00322                 Tcl_WrongNumArgs(interp, 4, objv, "min max");
00323                 return (TCL_ERROR);
00324         }
00325 
00326         if ((result = _GetUInt32(interp, objv[2], &min)) != TCL_OK)
00327                 return (result);
00328         if ((result = _GetUInt32(interp, objv[3], &max)) != TCL_OK)
00329                 return (result);
00330 
00331         _debug_check();
00332         if ((ret = dbenv->set_rep_request(dbenv, min, max)) != 0)
00333                 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00334                     "env set_rep_request"));
00335 
00336         return (_ReturnSetup(interp,
00337             ret, DB_RETOK_STD(ret), "env set_rep_request"));
00338 }
00339 #endif
00340 
00341 #ifdef CONFIG_TEST
00342 /*
00343  * tcl_RepTransport --
00344  *      Call DB_ENV->set_rep_transport().
00345  *
00346  * PUBLIC: int tcl_RepTransport  __P((Tcl_Interp *, int, Tcl_Obj * CONST *,
00347  * PUBLIC:    DB_ENV *, DBTCL_INFO *));
00348  *
00349  *      Note that this normally can/should be achieved as an argument to
00350  * berkdb env, but we need to test changing the transport function on
00351  * the fly.
00352  */
00353 int
00354 tcl_RepTransport(interp, objc, objv, dbenv, ip)
00355         Tcl_Interp *interp;             /* Interpreter */
00356         int objc;                       /* How many arguments? */
00357         Tcl_Obj *CONST objv[];          /* The argument objects */
00358         DB_ENV *dbenv;
00359         DBTCL_INFO *ip;
00360 {
00361         int intarg, result, ret;
00362 
00363         if (objc != 2) {
00364                 Tcl_WrongNumArgs(interp, 2, objv, "{id transport_func");
00365                 return (TCL_ERROR);
00366         }
00367 
00368         /*
00369          * Store the objects containing the machine ID
00370          * and the procedure name.  We don't need to crack
00371          * the send procedure out now, but we do convert the
00372          * machine ID to an int, since set_rep_transport needs
00373          * it.  Even so, it'll be easier later to deal with
00374          * the Tcl_Obj *, so we save that, not the int.
00375          *
00376          * Note that we Tcl_IncrRefCount both objects
00377          * independently;  Tcl is free to discard the list
00378          * that they're bundled into.
00379          */
00380 
00381         /*
00382          * Check that the machine ID is an int.  Note that
00383          * we do want to use GetIntFromObj;  the machine
00384          * ID is explicitly an int, not a u_int32_t.
00385          */
00386         if (ip->i_rep_eid != NULL)
00387                 Tcl_DecrRefCount(ip->i_rep_eid);
00388         ip->i_rep_eid = objv[0];
00389         Tcl_IncrRefCount(ip->i_rep_eid);
00390         result = Tcl_GetIntFromObj(interp,
00391             ip->i_rep_eid, &intarg);
00392         if (result != TCL_OK)
00393                 return (result);
00394 
00395         if (ip->i_rep_send != NULL)
00396                 Tcl_DecrRefCount(ip->i_rep_send);
00397         ip->i_rep_send = objv[1];
00398         Tcl_IncrRefCount(ip->i_rep_send);
00399         _debug_check();
00400         ret = dbenv->set_rep_transport(dbenv, intarg, tcl_rep_send);
00401         return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00402             "env rep_transport"));
00403 }
00404 #endif
00405 
00406 #ifdef CONFIG_TEST
00407 /*
00408  * tcl_RepStart --
00409  *      Call DB_ENV->rep_start().
00410  *
00411  * PUBLIC: int tcl_RepStart
00412  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00413  *
00414  *      Note that this normally can/should be achieved as an argument to
00415  * berkdb env, but we need to test forcible upgrading of clients, which
00416  * involves calling this on an open environment handle.
00417  */
00418 int
00419 tcl_RepStart(interp, objc, objv, dbenv)
00420         Tcl_Interp *interp;             /* Interpreter */
00421         int objc;                       /* How many arguments? */
00422         Tcl_Obj *CONST objv[];          /* The argument objects */
00423         DB_ENV *dbenv;
00424 {
00425         static const char *tclrpstrt[] = {
00426                 "-client",
00427                 "-master",
00428                 NULL
00429         };
00430         enum tclrpstrt {
00431                 TCL_RPSTRT_CLIENT,
00432                 TCL_RPSTRT_MASTER
00433         };
00434         char *arg;
00435         int i, optindex, ret;
00436         u_int32_t flag;
00437 
00438         flag = 0;
00439 
00440         if (objc != 3) {
00441                 Tcl_WrongNumArgs(interp, 3, objv, "[-master/-client]");
00442                 return (TCL_ERROR);
00443         }
00444 
00445         i = 2;
00446         while (i < objc) {
00447                 if (Tcl_GetIndexFromObj(interp, objv[i], tclrpstrt,
00448                     "option", TCL_EXACT, &optindex) != TCL_OK) {
00449                         arg = Tcl_GetStringFromObj(objv[i], NULL);
00450                         if (arg[0] == '-')
00451                                 return (IS_HELP(objv[i]));
00452                         else
00453                                 Tcl_ResetResult(interp);
00454                         break;
00455                 }
00456                 i++;
00457                 switch ((enum tclrpstrt)optindex) {
00458                 case TCL_RPSTRT_CLIENT:
00459                         flag |= DB_REP_CLIENT;
00460                         break;
00461                 case TCL_RPSTRT_MASTER:
00462                         flag |= DB_REP_MASTER;
00463                         break;
00464                 }
00465         }
00466 
00467         _debug_check();
00468         ret = dbenv->rep_start(dbenv, NULL, flag);
00469         return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env rep_start"));
00470 }
00471 #endif
00472 
00473 #ifdef CONFIG_TEST
00474 /*
00475  * tcl_RepProcessMessage --
00476  *      Call DB_ENV->rep_process_message().
00477  *
00478  * PUBLIC: int tcl_RepProcessMessage
00479  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00480  */
00481 int
00482 tcl_RepProcessMessage(interp, objc, objv, dbenv)
00483         Tcl_Interp *interp;             /* Interpreter */
00484         int objc;                       /* How many arguments? */
00485         Tcl_Obj *CONST objv[];          /* The argument objects */
00486         DB_ENV *dbenv;                  /* Environment pointer */
00487 {
00488         DBT control, rec;
00489         DB_LSN permlsn;
00490         Tcl_Obj *lsnlist, *myobjv[2], *res;
00491         void *ctmp, *rtmp;
00492         char *msg;
00493         int eid;
00494         int freectl, freerec, myobjc, result, ret;
00495 
00496         if (objc != 5) {
00497                 Tcl_WrongNumArgs(interp, 5, objv, "id control rec");
00498                 return (TCL_ERROR);
00499         }
00500         freectl = freerec = 0;
00501 
00502         memset(&control, 0, sizeof(control));
00503         memset(&rec, 0, sizeof(rec));
00504 
00505         if ((result = Tcl_GetIntFromObj(interp, objv[2], &eid)) != TCL_OK)
00506                 return (result);
00507 
00508         ret = _CopyObjBytes(interp, objv[3], &ctmp,
00509             &control.size, &freectl);
00510         if (ret != 0) {
00511                 result = _ReturnSetup(interp, ret,
00512                     DB_RETOK_REPPMSG(ret), "rep_proc_msg");
00513                 return (result);
00514         }
00515         control.data = ctmp;
00516         ret = _CopyObjBytes(interp, objv[4], &rtmp,
00517             &rec.size, &freerec);
00518         if (ret != 0) {
00519                 result = _ReturnSetup(interp, ret,
00520                     DB_RETOK_REPPMSG(ret), "rep_proc_msg");
00521                 goto out;
00522         }
00523         rec.data = rtmp;
00524         _debug_check();
00525         ret = dbenv->rep_process_message(dbenv, &control, &rec, &eid, &permlsn);
00526         /*
00527          * !!!
00528          * The TCL API diverges from the C++/Java APIs here.  For us, it
00529          * is OK to get DUPMASTER and HOLDELECTION for testing purposes.
00530          */
00531         result = _ReturnSetup(interp, ret,
00532             DB_RETOK_REPPMSG(ret) || ret == DB_REP_DUPMASTER ||
00533             ret == DB_REP_HOLDELECTION,
00534             "env rep_process_message");
00535 
00536         if (result != TCL_OK)
00537                 goto out;
00538 
00539         /*
00540          * We have a valid return.  We need to return a variety of information.
00541          * It will be one of the following:
00542          * {0 0} -  Make a 0 return a list for consistent return structure.
00543          * {DUPMASTER 0} -  DUPMASTER, no other info needed.
00544          * {HOLDELECTION 0} -  HOLDELECTION, no other info needed.
00545          * {NEWMASTER #} - NEWMASTER and its ID.
00546          * {NEWSITE 0} - NEWSITE, no other info needed.
00547          * {STARTUPDONE 0} - STARTUPDONE, no other info needed.
00548          * {IGNORE {LSN list}} - IGNORE and this msg's LSN.
00549          * {ISPERM {LSN list}} - ISPERM and the perm LSN.
00550          * {NOTPERM {LSN list}} - NOTPERM and this msg's LSN.
00551          */
00552         myobjc = 2;
00553         switch (ret) {
00554         case 0:
00555                 myobjv[0] = Tcl_NewIntObj(0);
00556                 myobjv[1] = Tcl_NewIntObj(0);
00557                 break;
00558         case DB_REP_DUPMASTER:
00559                 myobjv[0] = Tcl_NewByteArrayObj(
00560                     (u_char *)"DUPMASTER", (int)strlen("DUPMASTER"));
00561                 myobjv[1] = Tcl_NewIntObj(0);
00562                 break;
00563         case DB_REP_HOLDELECTION:
00564                 myobjv[0] = Tcl_NewByteArrayObj(
00565                     (u_char *)"HOLDELECTION", (int)strlen("HOLDELECTION"));
00566                 myobjv[1] = Tcl_NewIntObj(0);
00567                 break;
00568         case DB_REP_IGNORE:
00569                 myobjv[0] = Tcl_NewLongObj((long)permlsn.file);
00570                 myobjv[1] = Tcl_NewLongObj((long)permlsn.offset);
00571                 lsnlist = Tcl_NewListObj(myobjc, myobjv);
00572                 myobjv[0] = Tcl_NewByteArrayObj(
00573                     (u_char *)"IGNORE", (int)strlen("IGNORE"));
00574                 myobjv[1] = lsnlist;
00575                 break;
00576         case DB_REP_ISPERM:
00577                 myobjv[0] = Tcl_NewLongObj((long)permlsn.file);
00578                 myobjv[1] = Tcl_NewLongObj((long)permlsn.offset);
00579                 lsnlist = Tcl_NewListObj(myobjc, myobjv);
00580                 myobjv[0] = Tcl_NewByteArrayObj(
00581                     (u_char *)"ISPERM", (int)strlen("ISPERM"));
00582                 myobjv[1] = lsnlist;
00583                 break;
00584         case DB_REP_NEWMASTER:
00585                 myobjv[0] = Tcl_NewByteArrayObj(
00586                     (u_char *)"NEWMASTER", (int)strlen("NEWMASTER"));
00587                 myobjv[1] = Tcl_NewIntObj(eid);
00588                 break;
00589         case DB_REP_NEWSITE:
00590                 myobjv[0] = Tcl_NewByteArrayObj(
00591                     (u_char *)"NEWSITE", (int)strlen("NEWSITE"));
00592                 myobjv[1] = Tcl_NewIntObj(0);
00593                 break;
00594         case DB_REP_NOTPERM:
00595                 myobjv[0] = Tcl_NewLongObj((long)permlsn.file);
00596                 myobjv[1] = Tcl_NewLongObj((long)permlsn.offset);
00597                 lsnlist = Tcl_NewListObj(myobjc, myobjv);
00598                 myobjv[0] = Tcl_NewByteArrayObj(
00599                     (u_char *)"NOTPERM", (int)strlen("NOTPERM"));
00600                 myobjv[1] = lsnlist;
00601                 break;
00602         case DB_REP_STARTUPDONE:
00603                 myobjv[0] = Tcl_NewByteArrayObj(
00604                     (u_char *)"STARTUPDONE", (int)strlen("STARTUPDONE"));
00605                 myobjv[1] = Tcl_NewIntObj(0);
00606                 break;
00607         default:
00608                 msg = db_strerror(ret);
00609                 Tcl_AppendResult(interp, msg, NULL);
00610                 Tcl_SetErrorCode(interp, "BerkeleyDB", msg, NULL);
00611                 result = TCL_ERROR;
00612                 goto out;
00613         }
00614         res = Tcl_NewListObj(myobjc, myobjv);
00615         if (res != NULL)
00616                 Tcl_SetObjResult(interp, res);
00617 out:
00618         if (freectl)
00619                 __os_free(NULL, ctmp);
00620         if (freerec)
00621                 __os_free(NULL, rtmp);
00622 
00623         return (result);
00624 }
00625 #endif
00626 
00627 #ifdef CONFIG_TEST
00628 /*
00629  * tcl_RepStat --
00630  *      Call DB_ENV->rep_stat().
00631  *
00632  * PUBLIC: int tcl_RepStat
00633  * PUBLIC:     __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *));
00634  */
00635 int
00636 tcl_RepStat(interp, objc, objv, dbenv)
00637         Tcl_Interp *interp;             /* Interpreter */
00638         int objc;                       /* How many arguments? */
00639         Tcl_Obj *CONST objv[];          /* The argument objects */
00640         DB_ENV *dbenv;
00641 {
00642         DB_REP_STAT *sp;
00643         Tcl_Obj *myobjv[2], *res, *thislist, *lsnlist;
00644         u_int32_t flag;
00645         int myobjc, result, ret;
00646         char *arg;
00647 
00648         flag = 0;
00649         result = TCL_OK;
00650 
00651         if (objc > 3) {
00652                 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00653                 return (TCL_ERROR);
00654         }
00655         if (objc == 3) {
00656                 arg = Tcl_GetStringFromObj(objv[2], NULL);
00657                 if (strcmp(arg, "-clear") == 0)
00658                         flag = DB_STAT_CLEAR;
00659                 else {
00660                         Tcl_SetResult(interp,
00661                             "db stat: unknown arg", TCL_STATIC);
00662                         return (TCL_ERROR);
00663                 }
00664         }
00665 
00666         _debug_check();
00667         ret = dbenv->rep_stat(dbenv, &sp, flag);
00668         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00669             "rep stat");
00670         if (result == TCL_ERROR)
00671                 return (result);
00672 
00673         /*
00674          * Have our stats, now construct the name value
00675          * list pairs and free up the memory.
00676          */
00677         res = Tcl_NewObj();
00678         /*
00679          * MAKE_STAT_* assumes 'res' and 'error' label.
00680          */
00681         if (sp->st_status == DB_REP_MASTER)
00682                 MAKE_STAT_LIST("Master", 1);
00683         else
00684                 MAKE_STAT_LIST("Client", 1);
00685         MAKE_STAT_LSN("Next LSN expected", &sp->st_next_lsn);
00686         MAKE_STAT_LSN("First missed LSN", &sp->st_waiting_lsn);
00687         MAKE_STAT_LIST("Bulk buffer fills", sp->st_bulk_fills);
00688         MAKE_STAT_LIST("Bulk buffer overflows", sp->st_bulk_overflows);
00689         MAKE_STAT_LIST("Bulk records stored", sp->st_bulk_records);
00690         MAKE_STAT_LIST("Bulk buffer transfers", sp->st_bulk_transfers);
00691         MAKE_STAT_LIST("Client service requests", sp->st_client_svc_req);
00692         MAKE_STAT_LIST("Client service req misses", sp->st_client_svc_miss);
00693         MAKE_STAT_LIST("Client rerequests", sp->st_client_rerequests);
00694         MAKE_STAT_LIST("Duplicate master conditions", sp->st_dupmasters);
00695         MAKE_STAT_LIST("Environment ID", sp->st_env_id);
00696         MAKE_STAT_LIST("Environment priority", sp->st_env_priority);
00697         MAKE_STAT_LIST("Generation number", sp->st_gen);
00698         MAKE_STAT_LIST("Election generation number", sp->st_egen);
00699         MAKE_STAT_LIST("Startup complete", sp->st_startup_complete);
00700         MAKE_STAT_LIST("Duplicate log records received", sp->st_log_duplicated);
00701         MAKE_STAT_LIST("Current log records queued", sp->st_log_queued);
00702         MAKE_STAT_LIST("Maximum log records queued", sp->st_log_queued_max);
00703         MAKE_STAT_LIST("Total log records queued", sp->st_log_queued_total);
00704         MAKE_STAT_LIST("Log records received", sp->st_log_records);
00705         MAKE_STAT_LIST("Log records requested", sp->st_log_requested);
00706         MAKE_STAT_LIST("Master environment ID", sp->st_master);
00707         MAKE_STAT_LIST("Master changes", sp->st_master_changes);
00708         MAKE_STAT_LIST("Messages with bad generation number",
00709             sp->st_msgs_badgen);
00710         MAKE_STAT_LIST("Messages processed", sp->st_msgs_processed);
00711         MAKE_STAT_LIST("Messages ignored for recovery", sp->st_msgs_recover);
00712         MAKE_STAT_LIST("Message send failures", sp->st_msgs_send_failures);
00713         MAKE_STAT_LIST("Messages sent", sp->st_msgs_sent);
00714         MAKE_STAT_LIST("New site messages", sp->st_newsites);
00715         MAKE_STAT_LIST("Number of sites in replication group", sp->st_nsites);
00716         MAKE_STAT_LIST("Transmission limited", sp->st_nthrottles);
00717         MAKE_STAT_LIST("Outdated conditions", sp->st_outdated);
00718         MAKE_STAT_LIST("Transactions applied", sp->st_txns_applied);
00719         MAKE_STAT_LIST("Next page expected", sp->st_next_pg);
00720         MAKE_STAT_LIST("First missed page", sp->st_waiting_pg);
00721         MAKE_STAT_LIST("Duplicate pages received", sp->st_pg_duplicated);
00722         MAKE_STAT_LIST("Pages received", sp->st_pg_records);
00723         MAKE_STAT_LIST("Pages requested", sp->st_pg_requested);
00724         MAKE_STAT_LIST("Elections held", sp->st_elections);
00725         MAKE_STAT_LIST("Elections won", sp->st_elections_won);
00726         MAKE_STAT_LIST("Election phase", sp->st_election_status);
00727         MAKE_STAT_LIST("Election winner", sp->st_election_cur_winner);
00728         MAKE_STAT_LIST("Election generation number", sp->st_election_gen);
00729         MAKE_STAT_LSN("Election max LSN", &sp->st_election_lsn);
00730         MAKE_STAT_LIST("Election sites", sp->st_election_nsites);
00731         MAKE_STAT_LIST("Election votes", sp->st_election_nvotes);
00732         MAKE_STAT_LIST("Election priority", sp->st_election_priority);
00733         MAKE_STAT_LIST("Election tiebreaker", sp->st_election_tiebreaker);
00734         MAKE_STAT_LIST("Election votes", sp->st_election_votes);
00735         MAKE_STAT_LIST("Election seconds", sp->st_election_sec);
00736         MAKE_STAT_LIST("Election usecs", sp->st_election_usec);
00737 
00738         Tcl_SetObjResult(interp, res);
00739 error:
00740         __os_ufree(dbenv, sp);
00741         return (result);
00742 }
00743 #endif

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