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

tcl_log.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_log.c,v 12.4 2005/10/29 13:05:02 bostic 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/log.h"
00022 #include "dbinc/tcl_db.h"
00023 #include "dbinc/txn.h"
00024 
00025 #ifdef CONFIG_TEST
00026 static int tcl_LogcGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_LOGC *));
00027 
00028 /*
00029  * tcl_LogArchive --
00030  *
00031  * PUBLIC: int tcl_LogArchive __P((Tcl_Interp *, int,
00032  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00033  */
00034 int
00035 tcl_LogArchive(interp, objc, objv, envp)
00036         Tcl_Interp *interp;             /* Interpreter */
00037         int objc;                       /* How many arguments? */
00038         Tcl_Obj *CONST objv[];          /* The argument objects */
00039         DB_ENV *envp;                   /* Environment pointer */
00040 {
00041         static const char *archopts[] = {
00042                 "-arch_abs",    "-arch_data",   "-arch_log",    "-arch_remove",
00043                 NULL
00044         };
00045         enum archopts {
00046                 ARCH_ABS,       ARCH_DATA,      ARCH_LOG,       ARCH_REMOVE
00047         };
00048         Tcl_Obj *fileobj, *res;
00049         u_int32_t flag;
00050         int i, optindex, result, ret;
00051         char **file, **list;
00052 
00053         result = TCL_OK;
00054         flag = 0;
00055         /*
00056          * Get the flag index from the object based on the options
00057          * defined above.
00058          */
00059         i = 2;
00060         while (i < objc) {
00061                 if (Tcl_GetIndexFromObj(interp, objv[i],
00062                     archopts, "option", TCL_EXACT, &optindex) != TCL_OK)
00063                         return (IS_HELP(objv[i]));
00064                 i++;
00065                 switch ((enum archopts)optindex) {
00066                 case ARCH_ABS:
00067                         flag |= DB_ARCH_ABS;
00068                         break;
00069                 case ARCH_DATA:
00070                         flag |= DB_ARCH_DATA;
00071                         break;
00072                 case ARCH_LOG:
00073                         flag |= DB_ARCH_LOG;
00074                         break;
00075                 case ARCH_REMOVE:
00076                         flag |= DB_ARCH_REMOVE;
00077                         break;
00078                 }
00079         }
00080         _debug_check();
00081         list = NULL;
00082         ret = envp->log_archive(envp, &list, flag);
00083         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log archive");
00084         if (result == TCL_OK) {
00085                 res = Tcl_NewListObj(0, NULL);
00086                 for (file = list; file != NULL && *file != NULL; file++) {
00087                         fileobj = NewStringObj(*file, strlen(*file));
00088                         result = Tcl_ListObjAppendElement(interp, res, fileobj);
00089                         if (result != TCL_OK)
00090                                 break;
00091                 }
00092                 Tcl_SetObjResult(interp, res);
00093         }
00094         if (list != NULL)
00095                 __os_ufree(envp, list);
00096         return (result);
00097 }
00098 
00099 /*
00100  * tcl_LogCompare --
00101  *
00102  * PUBLIC: int tcl_LogCompare __P((Tcl_Interp *, int,
00103  * PUBLIC:    Tcl_Obj * CONST*));
00104  */
00105 int
00106 tcl_LogCompare(interp, objc, objv)
00107         Tcl_Interp *interp;             /* Interpreter */
00108         int objc;                       /* How many arguments? */
00109         Tcl_Obj *CONST objv[];          /* The argument objects */
00110 {
00111         DB_LSN lsn0, lsn1;
00112         Tcl_Obj *res;
00113         int result, ret;
00114 
00115         result = TCL_OK;
00116         /*
00117          * No flags, must be 4 args.
00118          */
00119         if (objc != 4) {
00120                 Tcl_WrongNumArgs(interp, 2, objv, "lsn1 lsn2");
00121                 return (TCL_ERROR);
00122         }
00123 
00124         result = _GetLsn(interp, objv[2], &lsn0);
00125         if (result == TCL_ERROR)
00126                 return (result);
00127         result = _GetLsn(interp, objv[3], &lsn1);
00128         if (result == TCL_ERROR)
00129                 return (result);
00130 
00131         _debug_check();
00132         ret = log_compare(&lsn0, &lsn1);
00133         res = Tcl_NewIntObj(ret);
00134         Tcl_SetObjResult(interp, res);
00135         return (result);
00136 }
00137 
00138 /*
00139  * tcl_LogFile --
00140  *
00141  * PUBLIC: int tcl_LogFile __P((Tcl_Interp *, int,
00142  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00143  */
00144 int
00145 tcl_LogFile(interp, objc, objv, envp)
00146         Tcl_Interp *interp;             /* Interpreter */
00147         int objc;                       /* How many arguments? */
00148         Tcl_Obj *CONST objv[];          /* The argument objects */
00149         DB_ENV *envp;                   /* Environment pointer */
00150 {
00151         DB_LSN lsn;
00152         Tcl_Obj *res;
00153         size_t len;
00154         int result, ret;
00155         char *name;
00156 
00157         result = TCL_OK;
00158         /*
00159          * No flags, must be 3 args.
00160          */
00161         if (objc != 3) {
00162                 Tcl_WrongNumArgs(interp, 2, objv, "lsn");
00163                 return (TCL_ERROR);
00164         }
00165 
00166         result = _GetLsn(interp, objv[2], &lsn);
00167         if (result == TCL_ERROR)
00168                 return (result);
00169 
00170         len = MSG_SIZE;
00171         ret = ENOMEM;
00172         name = NULL;
00173         while (ret == ENOMEM) {
00174                 if (name != NULL)
00175                         __os_free(envp, name);
00176                 ret = __os_malloc(envp, len, &name);
00177                 if (ret != 0) {
00178                         Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
00179                         break;
00180                 }
00181                 _debug_check();
00182                 ret = envp->log_file(envp, &lsn, name, len);
00183                 len *= 2;
00184         }
00185         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_file");
00186         if (ret == 0) {
00187                 res = NewStringObj(name, strlen(name));
00188                 Tcl_SetObjResult(interp, res);
00189         }
00190 
00191         if (name != NULL)
00192                 __os_free(envp, name);
00193 
00194         return (result);
00195 }
00196 
00197 /*
00198  * tcl_LogFlush --
00199  *
00200  * PUBLIC: int tcl_LogFlush __P((Tcl_Interp *, int,
00201  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00202  */
00203 int
00204 tcl_LogFlush(interp, objc, objv, envp)
00205         Tcl_Interp *interp;             /* Interpreter */
00206         int objc;                       /* How many arguments? */
00207         Tcl_Obj *CONST objv[];          /* The argument objects */
00208         DB_ENV *envp;                   /* Environment pointer */
00209 {
00210         DB_LSN lsn, *lsnp;
00211         int result, ret;
00212 
00213         result = TCL_OK;
00214         /*
00215          * No flags, must be 2 or 3 args.
00216          */
00217         if (objc > 3) {
00218                 Tcl_WrongNumArgs(interp, 2, objv, "?lsn?");
00219                 return (TCL_ERROR);
00220         }
00221 
00222         if (objc == 3) {
00223                 lsnp = &lsn;
00224                 result = _GetLsn(interp, objv[2], &lsn);
00225                 if (result == TCL_ERROR)
00226                         return (result);
00227         } else
00228                 lsnp = NULL;
00229 
00230         _debug_check();
00231         ret = envp->log_flush(envp, lsnp);
00232         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_flush");
00233         return (result);
00234 }
00235 
00236 /*
00237  * tcl_LogGet --
00238  *
00239  * PUBLIC: int tcl_LogGet __P((Tcl_Interp *, int,
00240  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00241  */
00242 int
00243 tcl_LogGet(interp, objc, objv, envp)
00244         Tcl_Interp *interp;             /* Interpreter */
00245         int objc;                       /* How many arguments? */
00246         Tcl_Obj *CONST objv[];          /* The argument objects */
00247         DB_ENV *envp;                   /* Environment pointer */
00248 {
00249 
00250         COMPQUIET(objv, NULL);
00251         COMPQUIET(objc, 0);
00252         COMPQUIET(envp, NULL);
00253 
00254         Tcl_SetResult(interp, "FAIL: log_get deprecated\n", TCL_STATIC);
00255         return (TCL_ERROR);
00256 }
00257 
00258 /*
00259  * tcl_LogPut --
00260  *
00261  * PUBLIC: int tcl_LogPut __P((Tcl_Interp *, int,
00262  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00263  */
00264 int
00265 tcl_LogPut(interp, objc, objv, envp)
00266         Tcl_Interp *interp;             /* Interpreter */
00267         int objc;                       /* How many arguments? */
00268         Tcl_Obj *CONST objv[];          /* The argument objects */
00269         DB_ENV *envp;                   /* Environment pointer */
00270 {
00271         static const char *logputopts[] = {
00272                 "-flush",
00273                 NULL
00274         };
00275         enum logputopts {
00276                 LOGPUT_FLUSH
00277         };
00278         DB_LSN lsn;
00279         DBT data;
00280         Tcl_Obj *intobj, *res;
00281         void *dtmp;
00282         u_int32_t flag;
00283         int freedata, optindex, result, ret;
00284 
00285         result = TCL_OK;
00286         flag = 0;
00287         freedata = 0;
00288         if (objc < 3) {
00289                 Tcl_WrongNumArgs(interp, 2, objv, "?-args? record");
00290                 return (TCL_ERROR);
00291         }
00292 
00293         /*
00294          * Data/record must be the last arg.
00295          */
00296         memset(&data, 0, sizeof(data));
00297         ret = _CopyObjBytes(interp, objv[objc-1], &dtmp,
00298             &data.size, &freedata);
00299         if (ret != 0) {
00300                 result = _ReturnSetup(interp, ret,
00301                     DB_RETOK_STD(ret), "log put");
00302                 return (result);
00303         }
00304         data.data = dtmp;
00305 
00306         /*
00307          * Get the command name index from the object based on the options
00308          * defined above.
00309          */
00310         if (objc == 4) {
00311                 if (Tcl_GetIndexFromObj(interp, objv[2],
00312                     logputopts, "option", TCL_EXACT, &optindex) != TCL_OK) {
00313                         return (IS_HELP(objv[2]));
00314                 }
00315                 switch ((enum logputopts)optindex) {
00316                 case LOGPUT_FLUSH:
00317                         flag = DB_FLUSH;
00318                         break;
00319                 }
00320         }
00321 
00322         if (result == TCL_ERROR)
00323                 return (result);
00324 
00325         _debug_check();
00326         ret = envp->log_put(envp, &lsn, &data, flag);
00327         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log_put");
00328         if (result == TCL_ERROR)
00329                 return (result);
00330         res = Tcl_NewListObj(0, NULL);
00331         intobj = Tcl_NewWideIntObj((Tcl_WideInt)lsn.file);
00332         result = Tcl_ListObjAppendElement(interp, res, intobj);
00333         intobj = Tcl_NewWideIntObj((Tcl_WideInt)lsn.offset);
00334         result = Tcl_ListObjAppendElement(interp, res, intobj);
00335         Tcl_SetObjResult(interp, res);
00336         if (freedata)
00337                 __os_free(NULL, dtmp);
00338         return (result);
00339 }
00340 /*
00341  * tcl_LogStat --
00342  *
00343  * PUBLIC: int tcl_LogStat __P((Tcl_Interp *, int,
00344  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00345  */
00346 int
00347 tcl_LogStat(interp, objc, objv, envp)
00348         Tcl_Interp *interp;             /* Interpreter */
00349         int objc;                       /* How many arguments? */
00350         Tcl_Obj *CONST objv[];          /* The argument objects */
00351         DB_ENV *envp;                   /* Environment pointer */
00352 {
00353         DB_LOG_STAT *sp;
00354         Tcl_Obj *res;
00355         int result, ret;
00356 
00357         result = TCL_OK;
00358         /*
00359          * No args for this.  Error if there are some.
00360          */
00361         if (objc != 2) {
00362                 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00363                 return (TCL_ERROR);
00364         }
00365         _debug_check();
00366         ret = envp->log_stat(envp, &sp, 0);
00367         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log stat");
00368         if (result == TCL_ERROR)
00369                 return (result);
00370 
00371         /*
00372          * Have our stats, now construct the name value
00373          * list pairs and free up the memory.
00374          */
00375         res = Tcl_NewObj();
00376         /*
00377          * MAKE_STAT_LIST assumes 'res' and 'error' label.
00378          */
00379         MAKE_STAT_LIST("Magic", sp->st_magic);
00380         MAKE_STAT_LIST("Log file Version", sp->st_version);
00381         MAKE_STAT_LIST("Region size", sp->st_regsize);
00382         MAKE_STAT_LIST("Log file mode", sp->st_mode);
00383         MAKE_STAT_LIST("Log record cache size", sp->st_lg_bsize);
00384         MAKE_STAT_LIST("Current log file size", sp->st_lg_size);
00385         MAKE_STAT_LIST("Log file records written", sp->st_record);
00386         MAKE_STAT_LIST("Mbytes written", sp->st_w_mbytes);
00387         MAKE_STAT_LIST("Bytes written (over Mb)", sp->st_w_bytes);
00388         MAKE_STAT_LIST("Mbytes written since checkpoint", sp->st_wc_mbytes);
00389         MAKE_STAT_LIST("Bytes written (over Mb) since checkpoint",
00390             sp->st_wc_bytes);
00391         MAKE_STAT_LIST("Times log written", sp->st_wcount);
00392         MAKE_STAT_LIST("Times log written because cache filled up",
00393             sp->st_wcount_fill);
00394         MAKE_STAT_LIST("Times log read from disk", sp->st_rcount);
00395         MAKE_STAT_LIST("Times log flushed to disk", sp->st_scount);
00396         MAKE_STAT_LIST("Current log file number", sp->st_cur_file);
00397         MAKE_STAT_LIST("Current log file offset", sp->st_cur_offset);
00398         MAKE_STAT_LIST("On-disk log file number", sp->st_disk_file);
00399         MAKE_STAT_LIST("On-disk log file offset", sp->st_disk_offset);
00400         MAKE_STAT_LIST("Max commits in a log flush", sp->st_maxcommitperflush);
00401         MAKE_STAT_LIST("Min commits in a log flush", sp->st_mincommitperflush);
00402         MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
00403         MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
00404         Tcl_SetObjResult(interp, res);
00405 error:
00406         __os_ufree(envp, sp);
00407         return (result);
00408 }
00409 
00410 /*
00411  * logc_Cmd --
00412  *      Implements the log cursor command.
00413  *
00414  * PUBLIC: int logc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
00415  */
00416 int
00417 logc_Cmd(clientData, interp, objc, objv)
00418         ClientData clientData;          /* Cursor handle */
00419         Tcl_Interp *interp;             /* Interpreter */
00420         int objc;                       /* How many arguments? */
00421         Tcl_Obj *CONST objv[];          /* The argument objects */
00422 {
00423         static const char *logccmds[] = {
00424                 "close",
00425                 "get",
00426                 NULL
00427         };
00428         enum logccmds {
00429                 LOGCCLOSE,
00430                 LOGCGET
00431         };
00432         DB_LOGC *logc;
00433         DBTCL_INFO *logcip;
00434         int cmdindex, result, ret;
00435 
00436         Tcl_ResetResult(interp);
00437         logc = (DB_LOGC *)clientData;
00438         logcip = _PtrToInfo((void *)logc);
00439         result = TCL_OK;
00440 
00441         if (objc <= 1) {
00442                 Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
00443                 return (TCL_ERROR);
00444         }
00445         if (logc == NULL) {
00446                 Tcl_SetResult(interp, "NULL logc pointer", TCL_STATIC);
00447                 return (TCL_ERROR);
00448         }
00449         if (logcip == NULL) {
00450                 Tcl_SetResult(interp, "NULL logc info pointer", TCL_STATIC);
00451                 return (TCL_ERROR);
00452         }
00453 
00454         /*
00455          * Get the command name index from the object based on the berkdbcmds
00456          * defined above.
00457          */
00458         if (Tcl_GetIndexFromObj(interp, objv[1], logccmds, "command",
00459             TCL_EXACT, &cmdindex) != TCL_OK)
00460                 return (IS_HELP(objv[1]));
00461         switch ((enum logccmds)cmdindex) {
00462         case LOGCCLOSE:
00463                 /*
00464                  * No args for this.  Error if there are some.
00465                  */
00466                 if (objc > 2) {
00467                         Tcl_WrongNumArgs(interp, 2, objv, NULL);
00468                         return (TCL_ERROR);
00469                 }
00470                 _debug_check();
00471                 ret = logc->close(logc, 0);
00472                 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00473                     "logc close");
00474                 if (result == TCL_OK) {
00475                         (void)Tcl_DeleteCommand(interp, logcip->i_name);
00476                         _DeleteInfo(logcip);
00477                 }
00478                 break;
00479         case LOGCGET:
00480                 result = tcl_LogcGet(interp, objc, objv, logc);
00481                 break;
00482         }
00483         return (result);
00484 }
00485 
00486 static int
00487 tcl_LogcGet(interp, objc, objv, logc)
00488         Tcl_Interp *interp;
00489         int objc;
00490         Tcl_Obj * CONST *objv;
00491         DB_LOGC *logc;
00492 {
00493         static const char *logcgetopts[] = {
00494                 "-current",
00495                 "-first",
00496                 "-last",
00497                 "-next",
00498                 "-prev",
00499                 "-set",
00500                 NULL
00501         };
00502         enum logcgetopts {
00503                 LOGCGET_CURRENT,
00504                 LOGCGET_FIRST,
00505                 LOGCGET_LAST,
00506                 LOGCGET_NEXT,
00507                 LOGCGET_PREV,
00508                 LOGCGET_SET
00509         };
00510         DB_LSN lsn;
00511         DBT data;
00512         Tcl_Obj *dataobj, *lsnlist, *myobjv[2], *res;
00513         u_int32_t flag;
00514         int i, myobjc, optindex, result, ret;
00515 
00516         result = TCL_OK;
00517         res = NULL;
00518         flag = 0;
00519 
00520         if (objc < 3) {
00521                 Tcl_WrongNumArgs(interp, 2, objv, "?-args? lsn");
00522                 return (TCL_ERROR);
00523         }
00524 
00525         /*
00526          * Get the command name index from the object based on the options
00527          * defined above.
00528          */
00529         i = 2;
00530         while (i < objc) {
00531                 if (Tcl_GetIndexFromObj(interp, objv[i],
00532                     logcgetopts, "option", TCL_EXACT, &optindex) != TCL_OK)
00533                         return (IS_HELP(objv[i]));
00534                 i++;
00535                 switch ((enum logcgetopts)optindex) {
00536                 case LOGCGET_CURRENT:
00537                         FLAG_CHECK(flag);
00538                         flag |= DB_CURRENT;
00539                         break;
00540                 case LOGCGET_FIRST:
00541                         FLAG_CHECK(flag);
00542                         flag |= DB_FIRST;
00543                         break;
00544                 case LOGCGET_LAST:
00545                         FLAG_CHECK(flag);
00546                         flag |= DB_LAST;
00547                         break;
00548                 case LOGCGET_NEXT:
00549                         FLAG_CHECK(flag);
00550                         flag |= DB_NEXT;
00551                         break;
00552                 case LOGCGET_PREV:
00553                         FLAG_CHECK(flag);
00554                         flag |= DB_PREV;
00555                         break;
00556                 case LOGCGET_SET:
00557                         FLAG_CHECK(flag);
00558                         flag |= DB_SET;
00559                         if (i == objc) {
00560                                 Tcl_WrongNumArgs(interp, 2, objv, "?-set lsn?");
00561                                 result = TCL_ERROR;
00562                                 break;
00563                         }
00564                         result = _GetLsn(interp, objv[i++], &lsn);
00565                         break;
00566                 }
00567         }
00568 
00569         if (result == TCL_ERROR)
00570                 return (result);
00571 
00572         memset(&data, 0, sizeof(data));
00573 
00574         _debug_check();
00575         ret = logc->get(logc, &lsn, &data, flag);
00576 
00577         res = Tcl_NewListObj(0, NULL);
00578         if (res == NULL)
00579                 goto memerr;
00580 
00581         if (ret == 0) {
00582                 /*
00583                  * Success.  Set up return list as {LSN data} where LSN
00584                  * is a sublist {file offset}.
00585                  */
00586                 myobjc = 2;
00587                 myobjv[0] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.file);
00588                 myobjv[1] = Tcl_NewWideIntObj((Tcl_WideInt)lsn.offset);
00589                 lsnlist = Tcl_NewListObj(myobjc, myobjv);
00590                 if (lsnlist == NULL)
00591                         goto memerr;
00592 
00593                 result = Tcl_ListObjAppendElement(interp, res, lsnlist);
00594                 dataobj = NewStringObj(data.data, data.size);
00595                 if (dataobj == NULL) {
00596                         goto memerr;
00597                 }
00598                 result = Tcl_ListObjAppendElement(interp, res, dataobj);
00599         } else
00600                 result = _ReturnSetup(interp, ret, DB_RETOK_LGGET(ret),
00601                     "DB_LOGC->get");
00602 
00603         Tcl_SetObjResult(interp, res);
00604 
00605         if (0) {
00606 memerr:         if (res != NULL)
00607                         Tcl_DecrRefCount(res);
00608                 Tcl_SetResult(interp, "allocation failed", TCL_STATIC);
00609         }
00610 
00611         return (result);
00612 }
00613 #endif

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