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

tcl_seq.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2004-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: tcl_seq.c,v 12.2 2005/06/16 20:23:49 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifdef HAVE_SEQUENCE
00013 #ifndef NO_SYSTEM_INCLUDES
00014 #include <sys/types.h>
00015 
00016 #include <string.h>
00017 #include <tcl.h>
00018 #endif
00019 
00020 #include "db_int.h"
00021 #include "dbinc/tcl_db.h"
00022 #include "dbinc_auto/sequence_ext.h"
00023 
00024 /*
00025  * Prototypes for procedures defined later in this file:
00026  */
00027 static int      tcl_SeqClose __P((Tcl_Interp *,
00028     int, Tcl_Obj * CONST*, DB_SEQUENCE *, DBTCL_INFO *));
00029 static int      tcl_SeqGet __P((Tcl_Interp *,
00030     int, Tcl_Obj * CONST*, DB_SEQUENCE *));
00031 static int      tcl_SeqRemove __P((Tcl_Interp *,
00032     int, Tcl_Obj * CONST*, DB_SEQUENCE *, DBTCL_INFO *));
00033 static int      tcl_SeqStat __P((Tcl_Interp *,
00034     int, Tcl_Obj * CONST*, DB_SEQUENCE *));
00035 static int      tcl_SeqGetFlags __P((Tcl_Interp *,
00036     int, Tcl_Obj * CONST*, DB_SEQUENCE *));
00037 
00038 /*
00039  *
00040  * PUBLIC: int seq_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
00041  *
00042  * seq_Cmd --
00043  *      Implements the "seq" widget.
00044  */
00045 int
00046 seq_Cmd(clientData, interp, objc, objv)
00047         ClientData clientData;          /* SEQ handle */
00048         Tcl_Interp *interp;             /* Interpreter */
00049         int objc;                       /* How many arguments? */
00050         Tcl_Obj *CONST objv[];          /* The argument objects */
00051 {
00052         static const char *seqcmds[] = {
00053                 "close",
00054                 "get",
00055                 "get_cachesize",
00056                 "get_db",
00057                 "get_flags",
00058                 "get_key",
00059                 "get_range",
00060                 "remove",
00061                 "stat",
00062                 NULL
00063         };
00064         enum seqcmds {
00065                 SEQCLOSE,
00066                 SEQGET,
00067                 SEQGETCACHESIZE,
00068                 SEQGETDB,
00069                 SEQGETFLAGS,
00070                 SEQGETKEY,
00071                 SEQGETRANGE,
00072                 SEQREMOVE,
00073                 SEQSTAT
00074         };
00075         DB *dbp;
00076         DBT key;
00077         DBTCL_INFO *dbip, *ip;
00078         DB_SEQUENCE *seq;
00079         Tcl_Obj *myobjv[2], *res;
00080         db_seq_t min, max;
00081         int cmdindex, ncache, result, ret;
00082 
00083         Tcl_ResetResult(interp);
00084         seq = (DB_SEQUENCE *)clientData;
00085         result = TCL_OK;
00086         dbip = NULL;
00087         if (objc <= 1) {
00088                 Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
00089                 return (TCL_ERROR);
00090         }
00091         if (seq == NULL) {
00092                 Tcl_SetResult(interp, "NULL sequence pointer", TCL_STATIC);
00093                 return (TCL_ERROR);
00094         }
00095 
00096         ip = _PtrToInfo((void *)seq);
00097         if (ip == NULL) {
00098                 Tcl_SetResult(interp, "NULL info pointer", TCL_STATIC);
00099                 return (TCL_ERROR);
00100         }
00101 
00102         /*
00103          * Get the command name index from the object based on the dbcmds
00104          * defined above.
00105          */
00106         if (Tcl_GetIndexFromObj(interp,
00107             objv[1], seqcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00108                 return (IS_HELP(objv[1]));
00109 
00110         res = NULL;
00111         switch ((enum seqcmds)cmdindex) {
00112         case SEQGETRANGE:
00113                 ret = seq->get_range(seq, &min, &max);
00114                 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00115                     "sequence get_range")) == TCL_OK) {
00116                         myobjv[0] = Tcl_NewWideIntObj(min);
00117                         myobjv[1] = Tcl_NewWideIntObj(max);
00118                         res = Tcl_NewListObj(2, myobjv);
00119                 }
00120                 break;
00121         case SEQCLOSE:
00122                 result = tcl_SeqClose(interp, objc, objv, seq, ip);
00123                 break;
00124         case SEQREMOVE:
00125                 result = tcl_SeqRemove(interp, objc, objv, seq, ip);
00126                 break;
00127         case SEQGET:
00128                 result = tcl_SeqGet(interp, objc, objv, seq);
00129                 break;
00130         case SEQSTAT:
00131                 result = tcl_SeqStat(interp, objc, objv, seq);
00132                 break;
00133         case SEQGETCACHESIZE:
00134                 if (objc != 2) {
00135                         Tcl_WrongNumArgs(interp, 1, objv, NULL);
00136                         return (TCL_ERROR);
00137                 }
00138                 ret = seq->get_cachesize(seq, &ncache);
00139                 if ((result = _ReturnSetup(interp, ret,
00140                     DB_RETOK_STD(ret), "sequence get_cachesize")) == TCL_OK)
00141                         res = Tcl_NewIntObj(ncache);
00142                 break;
00143         case SEQGETDB:
00144                 if (objc != 2) {
00145                         Tcl_WrongNumArgs(interp, 1, objv, NULL);
00146                         return (TCL_ERROR);
00147                 }
00148                 ret = seq->get_db(seq, &dbp);
00149                 if (ret == 0 && (dbip = _PtrToInfo((void *)dbp)) == NULL) {
00150                         Tcl_SetResult(interp,
00151                              "NULL db info pointer", TCL_STATIC);
00152                         return (TCL_ERROR);
00153                 }
00154 
00155                 if ((result = _ReturnSetup(interp, ret,
00156                     DB_RETOK_STD(ret), "sequence get_db")) == TCL_OK)
00157                         res = NewStringObj(dbip->i_name, strlen(dbip->i_name));
00158                 break;
00159         case SEQGETKEY:
00160                 if (objc != 2) {
00161                         Tcl_WrongNumArgs(interp, 1, objv, NULL);
00162                         return (TCL_ERROR);
00163                 }
00164                 ret = seq->get_key(seq, &key);
00165                 if ((result = _ReturnSetup(interp, ret,
00166                     DB_RETOK_STD(ret), "sequence get_key")) == TCL_OK)
00167                         res = Tcl_NewByteArrayObj(
00168                             (u_char *)key.data, (int)key.size);
00169                 break;
00170         case SEQGETFLAGS:
00171                 result = tcl_SeqGetFlags(interp, objc, objv, seq);
00172                 break;
00173         }
00174 
00175         /*
00176          * Only set result if we have a res.  Otherwise, lower functions have
00177          * already done so.
00178          */
00179         if (result == TCL_OK && res)
00180                 Tcl_SetObjResult(interp, res);
00181         return (result);
00182 }
00183 
00184 /*
00185  * tcl_db_stat --
00186  */
00187 static int
00188 tcl_SeqStat(interp, objc, objv, seq)
00189         Tcl_Interp *interp;             /* Interpreter */
00190         int objc;                       /* How many arguments? */
00191         Tcl_Obj *CONST objv[];          /* The argument objects */
00192         DB_SEQUENCE *seq;               /* Database pointer */
00193 {
00194         DB_SEQUENCE_STAT *sp;
00195         u_int32_t flag;
00196         Tcl_Obj *res, *flaglist, *myobjv[2];
00197         int result, ret;
00198         char *arg;
00199 
00200         result = TCL_OK;
00201         flag = 0;
00202 
00203         if (objc > 3) {
00204                 Tcl_WrongNumArgs(interp, 2, objv, "?-clear?");
00205                 return (TCL_ERROR);
00206         }
00207 
00208         if (objc == 3) {
00209                 arg = Tcl_GetStringFromObj(objv[2], NULL);
00210                 if (strcmp(arg, "-clear") == 0)
00211                         flag = DB_STAT_CLEAR;
00212                 else {
00213                         Tcl_SetResult(interp,
00214                             "db stat: unknown arg", TCL_STATIC);
00215                         return (TCL_ERROR);
00216                 }
00217         }
00218 
00219         _debug_check();
00220         ret = seq->stat(seq, &sp, flag);
00221         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db stat");
00222         if (result == TCL_ERROR)
00223                 return (result);
00224 
00225         res = Tcl_NewObj();
00226         MAKE_STAT_LIST("Wait", sp->st_wait);
00227         MAKE_STAT_LIST("No wait", sp->st_nowait);
00228         MAKE_WSTAT_LIST("Current", sp->st_current);
00229         MAKE_WSTAT_LIST("Cached", sp->st_value);
00230         MAKE_WSTAT_LIST("Max Cached", sp->st_last_value);
00231         MAKE_WSTAT_LIST("Min", sp->st_min);
00232         MAKE_WSTAT_LIST("Max", sp->st_max);
00233         MAKE_STAT_LIST("Cache size", sp->st_cache_size);
00234         /*
00235          * Construct a {name {flag1 flag2 ... flagN}} list for the
00236          * seq flags.
00237          */
00238         myobjv[0] = NewStringObj("Flags", strlen("Flags"));
00239         myobjv[1] =
00240             _GetFlagsList(interp, sp->st_flags, __db_get_seq_flags_fn());
00241         flaglist = Tcl_NewListObj(2, myobjv);
00242         if (flaglist == NULL) {
00243                 result = TCL_ERROR;
00244                 goto error;
00245         }
00246         if ((result =
00247             Tcl_ListObjAppendElement(interp, res, flaglist)) != TCL_OK)
00248                 goto error;
00249 
00250         Tcl_SetObjResult(interp, res);
00251 
00252 error:  __os_ufree(seq->seq_dbp->dbenv, sp);
00253         return (result);
00254 }
00255 
00256 /*
00257  * tcl_db_close --
00258  */
00259 static int
00260 tcl_SeqClose(interp, objc, objv, seq, ip)
00261         Tcl_Interp *interp;             /* Interpreter */
00262         int objc;                       /* How many arguments? */
00263         Tcl_Obj *CONST objv[];          /* The argument objects */
00264         DB_SEQUENCE *seq;               /* Database pointer */
00265         DBTCL_INFO *ip;                 /* Info pointer */
00266 {
00267         int result, ret;
00268 
00269         result = TCL_OK;
00270         if (objc > 2) {
00271                 Tcl_WrongNumArgs(interp, 2, objv, "");
00272                 return (TCL_ERROR);
00273         }
00274 
00275         _DeleteInfo(ip);
00276         _debug_check();
00277 
00278         ret = seq->close(seq, 0);
00279         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "sequence close");
00280         return (result);
00281 }
00282 
00283 /*
00284  * tcl_SeqGet --
00285  */
00286 static int
00287 tcl_SeqGet(interp, objc, objv, seq)
00288         Tcl_Interp *interp;             /* Interpreter */
00289         int objc;                       /* How many arguments? */
00290         Tcl_Obj *CONST objv[];          /* The argument objects */
00291         DB_SEQUENCE *seq;               /* Sequence pointer */
00292 {
00293         static const char *seqgetopts[] = {
00294                 "-nosync",
00295                 "-txn",
00296                 NULL
00297         };
00298         enum seqgetopts {
00299                 SEQGET_NOSYNC,
00300                 SEQGET_TXN
00301         };
00302         DB_TXN *txn;
00303         Tcl_Obj *res;
00304         db_seq_t value;
00305         u_int32_t aflag, delta;
00306         int i, end, optindex, result, ret;
00307         char *arg, msg[MSG_SIZE];
00308 
00309         result = TCL_OK;
00310         txn = NULL;
00311         aflag = 0;
00312 
00313         if (objc < 3) {
00314                 Tcl_WrongNumArgs(interp, 2, objv, "?-args? delta");
00315                 return (TCL_ERROR);
00316         }
00317 
00318         /*
00319          * Get the command name index from the object based on the options
00320          * defined above.
00321          */
00322         i = 2;
00323         end = objc;
00324         while (i < end) {
00325                 if (Tcl_GetIndexFromObj(interp, objv[i], seqgetopts, "option",
00326                     TCL_EXACT, &optindex) != TCL_OK) {
00327                         arg = Tcl_GetStringFromObj(objv[i], NULL);
00328                         if (arg[0] == '-') {
00329                                 result = IS_HELP(objv[i]);
00330                                 goto out;
00331                         } else
00332                                 Tcl_ResetResult(interp);
00333                         break;
00334                 }
00335                 i++;
00336                 switch ((enum seqgetopts)optindex) {
00337                 case SEQGET_NOSYNC:
00338                         aflag |= DB_TXN_NOSYNC;
00339                         break;
00340                 case SEQGET_TXN:
00341                         if (i >= end) {
00342                                 Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
00343                                 result = TCL_ERROR;
00344                                 break;
00345                         }
00346                         arg = Tcl_GetStringFromObj(objv[i++], NULL);
00347                         txn = NAME_TO_TXN(arg);
00348                         if (txn == NULL) {
00349                                 snprintf(msg, MSG_SIZE,
00350                                     "Get: Invalid txn: %s\n", arg);
00351                                 Tcl_SetResult(interp, msg, TCL_VOLATILE);
00352                                 result = TCL_ERROR;
00353                         }
00354                         break;
00355                 } /* switch */
00356                 if (result != TCL_OK)
00357                         break;
00358         }
00359         if (result != TCL_OK)
00360                 goto out;
00361 
00362         if (i != objc - 1) {
00363                 Tcl_SetResult(interp,
00364                     "Wrong number of key/data given\n", TCL_STATIC);
00365                 result = TCL_ERROR;
00366                 goto out;
00367         }
00368 
00369         if ((result = _GetUInt32(interp, objv[objc - 1], &delta)) != TCL_OK)
00370                 goto out;
00371 
00372         ret = seq->get(seq, txn, (int32_t)delta, &value, aflag);
00373         result = _ReturnSetup(interp, ret, DB_RETOK_DBGET(ret), "sequence get");
00374         if (ret == 0) {
00375                 res = Tcl_NewWideIntObj((Tcl_WideInt)value);
00376                 Tcl_SetObjResult(interp, res);
00377         }
00378 out:
00379         return (result);
00380 }
00381 /*
00382  */
00383 static int
00384 tcl_SeqRemove(interp, objc, objv, seq, ip)
00385         Tcl_Interp *interp;             /* Interpreter */
00386         int objc;                       /* How many arguments? */
00387         Tcl_Obj *CONST objv[];          /* The argument objects */
00388         DB_SEQUENCE *seq;               /* Sequence pointer */
00389         DBTCL_INFO *ip;                 /* Info pointer */
00390 {
00391         static const char *seqgetopts[] = {
00392                 "-nosync",
00393                 "-txn",
00394                 NULL
00395         };
00396         enum seqgetopts {
00397                 SEQGET_NOSYNC,
00398                 SEQGET_TXN
00399         };
00400         DB_TXN *txn;
00401         u_int32_t aflag;
00402         int i, end, optindex, result, ret;
00403         char *arg, msg[MSG_SIZE];
00404 
00405         result = TCL_OK;
00406         txn = NULL;
00407         aflag = 0;
00408 
00409         _DeleteInfo(ip);
00410 
00411         if (objc < 2) {
00412                 Tcl_WrongNumArgs(interp, 2, objv, "?-args?");
00413                 return (TCL_ERROR);
00414         }
00415 
00416         /*
00417          * Get the command name index from the object based on the options
00418          * defined above.
00419          */
00420         i = 2;
00421         end = objc;
00422         while (i < end) {
00423                 if (Tcl_GetIndexFromObj(interp, objv[i], seqgetopts, "option",
00424                     TCL_EXACT, &optindex) != TCL_OK) {
00425                         arg = Tcl_GetStringFromObj(objv[i], NULL);
00426                         if (arg[0] == '-') {
00427                                 result = IS_HELP(objv[i]);
00428                                 goto out;
00429                         } else
00430                                 Tcl_ResetResult(interp);
00431                         break;
00432                 }
00433                 i++;
00434                 switch ((enum seqgetopts)optindex) {
00435                 case SEQGET_NOSYNC:
00436                         aflag |= DB_TXN_NOSYNC;
00437                         break;
00438                 case SEQGET_TXN:
00439                         if (i >= end) {
00440                                 Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
00441                                 result = TCL_ERROR;
00442                                 break;
00443                         }
00444                         arg = Tcl_GetStringFromObj(objv[i++], NULL);
00445                         txn = NAME_TO_TXN(arg);
00446                         if (txn == NULL) {
00447                                 snprintf(msg, MSG_SIZE,
00448                                     "Remove: Invalid txn: %s\n", arg);
00449                                 Tcl_SetResult(interp, msg, TCL_VOLATILE);
00450                                 result = TCL_ERROR;
00451                         }
00452                         break;
00453                 } /* switch */
00454                 if (result != TCL_OK)
00455                         break;
00456         }
00457         if (result != TCL_OK)
00458                 goto out;
00459 
00460         ret = seq->remove(seq, txn, aflag);
00461         result = _ReturnSetup(interp,
00462             ret, DB_RETOK_DBGET(ret), "sequence remove");
00463 out:
00464         return (result);
00465 }
00466 
00467 /*
00468  * tcl_SeqGetFlags --
00469  */
00470 static int
00471 tcl_SeqGetFlags(interp, objc, objv, seq)
00472         Tcl_Interp *interp;             /* Interpreter */
00473         int objc;                       /* How many arguments? */
00474         Tcl_Obj *CONST objv[];          /* The argument objects */
00475         DB_SEQUENCE *seq;               /* Sequence pointer */
00476 {
00477         int i, ret, result;
00478         u_int32_t flags;
00479         char buf[512];
00480         Tcl_Obj *res;
00481 
00482         static const struct {
00483                 u_int32_t flag;
00484                 char *arg;
00485         } seq_flags[] = {
00486                 { DB_SEQ_INC, "-inc" },
00487                 { DB_SEQ_DEC, "-dec" },
00488                 { DB_SEQ_WRAP, "-wrap" },
00489                 { 0, NULL }
00490         };
00491 
00492         if (objc != 2) {
00493                 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00494                 return (TCL_ERROR);
00495         }
00496 
00497         ret = seq->get_flags(seq, &flags);
00498         if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00499             "db get_flags")) == TCL_OK) {
00500                 buf[0] = '\0';
00501 
00502                 for (i = 0; seq_flags[i].flag != 0; i++)
00503                         if (LF_ISSET(seq_flags[i].flag)) {
00504                                 if (strlen(buf) > 0)
00505                                         (void)strncat(buf, " ", sizeof(buf));
00506                                 (void)strncat(
00507                                     buf, seq_flags[i].arg, sizeof(buf));
00508                         }
00509 
00510                 res = NewStringObj(buf, strlen(buf));
00511                 Tcl_SetObjResult(interp, res);
00512         }
00513 
00514         return (result);
00515 }
00516 #endif /* HAVE_SEQUENCE */

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