00001
00002
00003
00004
00005
00006
00007
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
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
00041
00042
00043
00044
00045 int
00046 seq_Cmd(clientData, interp, objc, objv)
00047 ClientData clientData;
00048 Tcl_Interp *interp;
00049 int objc;
00050 Tcl_Obj *CONST objv[];
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
00104
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
00177
00178
00179 if (result == TCL_OK && res)
00180 Tcl_SetObjResult(interp, res);
00181 return (result);
00182 }
00183
00184
00185
00186
00187 static int
00188 tcl_SeqStat(interp, objc, objv, seq)
00189 Tcl_Interp *interp;
00190 int objc;
00191 Tcl_Obj *CONST objv[];
00192 DB_SEQUENCE *seq;
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
00236
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
00258
00259 static int
00260 tcl_SeqClose(interp, objc, objv, seq, ip)
00261 Tcl_Interp *interp;
00262 int objc;
00263 Tcl_Obj *CONST objv[];
00264 DB_SEQUENCE *seq;
00265 DBTCL_INFO *ip;
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
00285
00286 static int
00287 tcl_SeqGet(interp, objc, objv, seq)
00288 Tcl_Interp *interp;
00289 int objc;
00290 Tcl_Obj *CONST objv[];
00291 DB_SEQUENCE *seq;
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
00320
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 }
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;
00386 int objc;
00387 Tcl_Obj *CONST objv[];
00388 DB_SEQUENCE *seq;
00389 DBTCL_INFO *ip;
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
00418
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 }
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
00469
00470 static int
00471 tcl_SeqGetFlags(interp, objc, objv, seq)
00472 Tcl_Interp *interp;
00473 int objc;
00474 Tcl_Obj *CONST objv[];
00475 DB_SEQUENCE *seq;
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