00001
00002
00003
00004
00005
00006
00007
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
00024
00025
00026 #ifdef CONFIG_TEST
00027 static int mp_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
00028 static int pg_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
00029 static int tcl_MpGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
00030 DB_MPOOLFILE *, DBTCL_INFO *));
00031 static int tcl_Pg __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
00032 void *, DB_MPOOLFILE *, DBTCL_INFO *, int));
00033 static int tcl_PgInit __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
00034 void *, DBTCL_INFO *));
00035 static int tcl_PgIsset __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
00036 void *, DBTCL_INFO *));
00037 #endif
00038
00039
00040
00041
00042
00043
00044
00045
00046 void
00047 _MpInfoDelete(interp, mpip)
00048 Tcl_Interp *interp;
00049 DBTCL_INFO *mpip;
00050 {
00051 DBTCL_INFO *nextp, *p;
00052
00053 for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
00054
00055
00056
00057
00058 nextp = LIST_NEXT(p, entries);
00059 if (p->i_parent == mpip && p->i_type == I_PG) {
00060 (void)Tcl_DeleteCommand(interp, p->i_name);
00061 _DeleteInfo(p);
00062 }
00063 }
00064 }
00065
00066 #ifdef CONFIG_TEST
00067
00068
00069
00070
00071
00072 int
00073 tcl_MpSync(interp, objc, objv, envp)
00074 Tcl_Interp *interp;
00075 int objc;
00076 Tcl_Obj *CONST objv[];
00077 DB_ENV *envp;
00078 {
00079
00080 DB_LSN lsn, *lsnp;
00081 int result, ret;
00082
00083 result = TCL_OK;
00084 lsnp = NULL;
00085
00086
00087
00088 if (objc == 3) {
00089 result = _GetLsn(interp, objv[2], &lsn);
00090 if (result == TCL_ERROR)
00091 return (result);
00092 lsnp = &lsn;
00093 }
00094 else if (objc != 2) {
00095 Tcl_WrongNumArgs(interp, 2, objv, "lsn");
00096 return (TCL_ERROR);
00097 }
00098
00099 _debug_check();
00100 ret = envp->memp_sync(envp, lsnp);
00101 return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp sync"));
00102 }
00103
00104
00105
00106
00107
00108
00109
00110 int
00111 tcl_MpTrickle(interp, objc, objv, envp)
00112 Tcl_Interp *interp;
00113 int objc;
00114 Tcl_Obj *CONST objv[];
00115 DB_ENV *envp;
00116 {
00117
00118 Tcl_Obj *res;
00119 int pages, percent, result, ret;
00120
00121 result = TCL_OK;
00122
00123
00124
00125 if (objc != 3) {
00126 Tcl_WrongNumArgs(interp, 2, objv, "percent");
00127 return (TCL_ERROR);
00128 }
00129
00130 result = Tcl_GetIntFromObj(interp, objv[2], &percent);
00131 if (result == TCL_ERROR)
00132 return (result);
00133
00134 _debug_check();
00135 ret = envp->memp_trickle(envp, percent, &pages);
00136 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp trickle");
00137 if (result == TCL_ERROR)
00138 return (result);
00139
00140 res = Tcl_NewIntObj(pages);
00141 Tcl_SetObjResult(interp, res);
00142 return (result);
00143
00144 }
00145
00146
00147
00148
00149
00150
00151
00152 int
00153 tcl_Mp(interp, objc, objv, envp, envip)
00154 Tcl_Interp *interp;
00155 int objc;
00156 Tcl_Obj *CONST objv[];
00157 DB_ENV *envp;
00158 DBTCL_INFO *envip;
00159 {
00160 static const char *mpopts[] = {
00161 "-create",
00162 "-mode",
00163 "-nommap",
00164 "-pagesize",
00165 "-rdonly",
00166 NULL
00167 };
00168 enum mpopts {
00169 MPCREATE,
00170 MPMODE,
00171 MPNOMMAP,
00172 MPPAGE,
00173 MPRDONLY
00174 };
00175 DBTCL_INFO *ip;
00176 DB_MPOOLFILE *mpf;
00177 Tcl_Obj *res;
00178 u_int32_t flag;
00179 int i, pgsize, mode, optindex, result, ret;
00180 char *file, newname[MSG_SIZE];
00181
00182 result = TCL_OK;
00183 i = 2;
00184 flag = 0;
00185 mode = 0;
00186 pgsize = 0;
00187 memset(newname, 0, MSG_SIZE);
00188 while (i < objc) {
00189 if (Tcl_GetIndexFromObj(interp, objv[i],
00190 mpopts, "option", TCL_EXACT, &optindex) != TCL_OK) {
00191
00192
00193
00194
00195
00196 if (IS_HELP(objv[i]) == TCL_OK)
00197 return (TCL_OK);
00198 Tcl_ResetResult(interp);
00199 break;
00200 }
00201 i++;
00202 switch ((enum mpopts)optindex) {
00203 case MPCREATE:
00204 flag |= DB_CREATE;
00205 break;
00206 case MPNOMMAP:
00207 flag |= DB_NOMMAP;
00208 break;
00209 case MPPAGE:
00210 if (i >= objc) {
00211 Tcl_WrongNumArgs(interp, 2, objv,
00212 "?-pagesize size?");
00213 result = TCL_ERROR;
00214 break;
00215 }
00216
00217
00218
00219
00220
00221
00222 result = Tcl_GetIntFromObj(interp, objv[i++], &pgsize);
00223 break;
00224 case MPRDONLY:
00225 flag |= DB_RDONLY;
00226 break;
00227 case MPMODE:
00228 if (i >= objc) {
00229 Tcl_WrongNumArgs(interp, 2, objv,
00230 "?-mode mode?");
00231 result = TCL_ERROR;
00232 break;
00233 }
00234
00235
00236
00237
00238
00239
00240 result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
00241 break;
00242 }
00243 if (result != TCL_OK)
00244 goto error;
00245 }
00246
00247
00248
00249 file = NULL;
00250 if (i != objc) {
00251 if (i != objc - 1) {
00252 Tcl_WrongNumArgs(interp, 2, objv, "?args? ?file?");
00253 result = TCL_ERROR;
00254 goto error;
00255 }
00256 file = Tcl_GetStringFromObj(objv[i++], NULL);
00257 }
00258
00259 snprintf(newname, sizeof(newname), "%s.mp%d",
00260 envip->i_name, envip->i_envmpid);
00261 ip = _NewInfo(interp, NULL, newname, I_MP);
00262 if (ip == NULL) {
00263 Tcl_SetResult(interp, "Could not set up info",
00264 TCL_STATIC);
00265 return (TCL_ERROR);
00266 }
00267
00268 _debug_check();
00269 if ((ret = envp->memp_fcreate(envp, &mpf, 0)) != 0) {
00270 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mpool");
00271 _DeleteInfo(ip);
00272 goto error;
00273 }
00274
00275
00276
00277
00278
00279 if ((ret = mpf->open(mpf, file, flag, mode, (size_t)pgsize)) != 0) {
00280 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mpool");
00281 _DeleteInfo(ip);
00282
00283 (void)mpf->close(mpf, 0);
00284 goto error;
00285 }
00286
00287
00288
00289
00290
00291 envip->i_envmpid++;
00292 ip->i_parent = envip;
00293 ip->i_pgsz = pgsize;
00294 _SetInfoData(ip, mpf);
00295 (void)Tcl_CreateObjCommand(interp, newname,
00296 (Tcl_ObjCmdProc *)mp_Cmd, (ClientData)mpf, NULL);
00297 res = NewStringObj(newname, strlen(newname));
00298 Tcl_SetObjResult(interp, res);
00299
00300 error:
00301 return (result);
00302 }
00303
00304
00305
00306
00307
00308
00309 int
00310 tcl_MpStat(interp, objc, objv, envp)
00311 Tcl_Interp *interp;
00312 int objc;
00313 Tcl_Obj *CONST objv[];
00314 DB_ENV *envp;
00315 {
00316 DB_MPOOL_STAT *sp;
00317 DB_MPOOL_FSTAT **fsp, **savefsp;
00318 int result;
00319 int ret;
00320 Tcl_Obj *res;
00321 Tcl_Obj *res1;
00322
00323 result = TCL_OK;
00324 savefsp = NULL;
00325
00326
00327
00328 if (objc != 2) {
00329 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00330 return (TCL_ERROR);
00331 }
00332 _debug_check();
00333 ret = envp->memp_stat(envp, &sp, &fsp, 0);
00334 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "memp stat");
00335 if (result == TCL_ERROR)
00336 return (result);
00337
00338
00339
00340
00341
00342 res = Tcl_NewObj();
00343
00344
00345
00346 MAKE_STAT_LIST("Cache size (gbytes)", sp->st_gbytes);
00347 MAKE_STAT_LIST("Cache size (bytes)", sp->st_bytes);
00348 MAKE_STAT_LIST("Number of caches", sp->st_ncache);
00349 MAKE_STAT_LIST("Region size", sp->st_regsize);
00350 MAKE_STAT_LIST("Maximum memory-mapped file size", sp->st_mmapsize);
00351 MAKE_STAT_LIST("Maximum open file descriptors", sp->st_maxopenfd);
00352 MAKE_STAT_LIST("Maximum sequential buffer writes", sp->st_maxwrite);
00353 MAKE_STAT_LIST(
00354 "Sleep after writing maximum buffers", sp->st_maxwrite_sleep);
00355 MAKE_STAT_LIST("Pages mapped into address space", sp->st_map);
00356 MAKE_STAT_LIST("Cache hits", sp->st_cache_hit);
00357 MAKE_STAT_LIST("Cache misses", sp->st_cache_miss);
00358 MAKE_STAT_LIST("Pages created", sp->st_page_create);
00359 MAKE_STAT_LIST("Pages read in", sp->st_page_in);
00360 MAKE_STAT_LIST("Pages written", sp->st_page_out);
00361 MAKE_STAT_LIST("Clean page evictions", sp->st_ro_evict);
00362 MAKE_STAT_LIST("Dirty page evictions", sp->st_rw_evict);
00363 MAKE_STAT_LIST("Dirty pages trickled", sp->st_page_trickle);
00364 MAKE_STAT_LIST("Cached pages", sp->st_pages);
00365 MAKE_STAT_LIST("Cached clean pages", sp->st_page_clean);
00366 MAKE_STAT_LIST("Cached dirty pages", sp->st_page_dirty);
00367 MAKE_STAT_LIST("Hash buckets", sp->st_hash_buckets);
00368 MAKE_STAT_LIST("Hash lookups", sp->st_hash_searches);
00369 MAKE_STAT_LIST("Longest hash chain found", sp->st_hash_longest);
00370 MAKE_STAT_LIST("Hash elements examined", sp->st_hash_examined);
00371 MAKE_STAT_LIST("Number of hash bucket nowaits", sp->st_hash_nowait);
00372 MAKE_STAT_LIST("Number of hash bucket waits", sp->st_hash_wait);
00373 MAKE_STAT_LIST("Maximum number of hash bucket waits",
00374 sp->st_hash_max_wait);
00375 MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
00376 MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
00377 MAKE_STAT_LIST("Page allocations", sp->st_alloc);
00378 MAKE_STAT_LIST("Buckets examined during allocation",
00379 sp->st_alloc_buckets);
00380 MAKE_STAT_LIST("Maximum buckets examined during allocation",
00381 sp->st_alloc_max_buckets);
00382 MAKE_STAT_LIST("Pages examined during allocation", sp->st_alloc_pages);
00383 MAKE_STAT_LIST("Maximum pages examined during allocation",
00384 sp->st_alloc_max_pages);
00385
00386
00387
00388
00389
00390
00391 res1 = res;
00392 for (savefsp = fsp; fsp != NULL && *fsp != NULL; fsp++) {
00393 res = Tcl_NewObj();
00394 result = _SetListElem(interp, res, "File Name",
00395 strlen("File Name"), (*fsp)->file_name,
00396 strlen((*fsp)->file_name));
00397 if (result != TCL_OK)
00398 goto error;
00399 MAKE_STAT_LIST("Page size", (*fsp)->st_pagesize);
00400 MAKE_STAT_LIST("Pages mapped into address space",
00401 (*fsp)->st_map);
00402 MAKE_STAT_LIST("Cache hits", (*fsp)->st_cache_hit);
00403 MAKE_STAT_LIST("Cache misses", (*fsp)->st_cache_miss);
00404 MAKE_STAT_LIST("Pages created", (*fsp)->st_page_create);
00405 MAKE_STAT_LIST("Pages read in", (*fsp)->st_page_in);
00406 MAKE_STAT_LIST("Pages written", (*fsp)->st_page_out);
00407
00408
00409
00410
00411 result = Tcl_ListObjAppendElement(interp, res1, res);
00412 if (result != TCL_OK)
00413 goto error;
00414 }
00415 Tcl_SetObjResult(interp, res1);
00416 error:
00417 __os_ufree(envp, sp);
00418 if (savefsp != NULL)
00419 __os_ufree(envp, savefsp);
00420 return (result);
00421 }
00422
00423
00424
00425
00426
00427 static int
00428 mp_Cmd(clientData, interp, objc, objv)
00429 ClientData clientData;
00430 Tcl_Interp *interp;
00431 int objc;
00432 Tcl_Obj *CONST objv[];
00433 {
00434 static const char *mpcmds[] = {
00435 "close",
00436 "fsync",
00437 "get",
00438 "get_clear_len",
00439 "get_fileid",
00440 "get_ftype",
00441 "get_lsn_offset",
00442 "get_pgcookie",
00443 NULL
00444 };
00445 enum mpcmds {
00446 MPCLOSE,
00447 MPFSYNC,
00448 MPGET,
00449 MPGETCLEARLEN,
00450 MPGETFILEID,
00451 MPGETFTYPE,
00452 MPGETLSNOFFSET,
00453 MPGETPGCOOKIE
00454 };
00455 DB_MPOOLFILE *mp;
00456 int cmdindex, ftype, length, result, ret;
00457 DBTCL_INFO *mpip;
00458 Tcl_Obj *res;
00459 char *obj_name;
00460 u_int32_t value;
00461 int32_t intval;
00462 u_int8_t fileid[DB_FILE_ID_LEN];
00463 DBT cookie;
00464
00465 Tcl_ResetResult(interp);
00466 mp = (DB_MPOOLFILE *)clientData;
00467 obj_name = Tcl_GetStringFromObj(objv[0], &length);
00468 mpip = _NameToInfo(obj_name);
00469 result = TCL_OK;
00470
00471 if (mp == NULL) {
00472 Tcl_SetResult(interp, "NULL mp pointer", TCL_STATIC);
00473 return (TCL_ERROR);
00474 }
00475 if (mpip == NULL) {
00476 Tcl_SetResult(interp, "NULL mp info pointer", TCL_STATIC);
00477 return (TCL_ERROR);
00478 }
00479
00480
00481
00482
00483
00484 if (Tcl_GetIndexFromObj(interp,
00485 objv[1], mpcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00486 return (IS_HELP(objv[1]));
00487
00488 res = NULL;
00489 switch ((enum mpcmds)cmdindex) {
00490 case MPCLOSE:
00491 if (objc != 2) {
00492 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00493 return (TCL_ERROR);
00494 }
00495 _debug_check();
00496 ret = mp->close(mp, 0);
00497 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00498 "mp close");
00499 _MpInfoDelete(interp, mpip);
00500 (void)Tcl_DeleteCommand(interp, mpip->i_name);
00501 _DeleteInfo(mpip);
00502 break;
00503 case MPFSYNC:
00504 if (objc != 2) {
00505 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00506 return (TCL_ERROR);
00507 }
00508 _debug_check();
00509 ret = mp->sync(mp);
00510 res = Tcl_NewIntObj(ret);
00511 break;
00512 case MPGET:
00513 result = tcl_MpGet(interp, objc, objv, mp, mpip);
00514 break;
00515 case MPGETCLEARLEN:
00516 if (objc != 2) {
00517 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00518 return (TCL_ERROR);
00519 }
00520 ret = mp->get_clear_len(mp, &value);
00521 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00522 "mp get_clear_len")) == TCL_OK)
00523 res = Tcl_NewIntObj((int)value);
00524 break;
00525 case MPGETFILEID:
00526 if (objc != 2) {
00527 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00528 return (TCL_ERROR);
00529 }
00530 ret = mp->get_fileid(mp, fileid);
00531 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00532 "mp get_fileid")) == TCL_OK)
00533 res = NewStringObj((char *)fileid, DB_FILE_ID_LEN);
00534 break;
00535 case MPGETFTYPE:
00536 if (objc != 2) {
00537 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00538 return (TCL_ERROR);
00539 }
00540 ret = mp->get_ftype(mp, &ftype);
00541 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00542 "mp get_ftype")) == TCL_OK)
00543 res = Tcl_NewIntObj(ftype);
00544 break;
00545 case MPGETLSNOFFSET:
00546 if (objc != 2) {
00547 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00548 return (TCL_ERROR);
00549 }
00550 ret = mp->get_lsn_offset(mp, &intval);
00551 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00552 "mp get_lsn_offset")) == TCL_OK)
00553 res = Tcl_NewIntObj(intval);
00554 break;
00555 case MPGETPGCOOKIE:
00556 if (objc != 2) {
00557 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00558 return (TCL_ERROR);
00559 }
00560 memset(&cookie, 0, sizeof(DBT));
00561 ret = mp->get_pgcookie(mp, &cookie);
00562 if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00563 "mp get_pgcookie")) == TCL_OK)
00564 res = Tcl_NewByteArrayObj((u_char *)cookie.data,
00565 (int)cookie.size);
00566 break;
00567 }
00568
00569
00570
00571
00572 if (result == TCL_OK && res)
00573 Tcl_SetObjResult(interp, res);
00574 return (result);
00575 }
00576
00577
00578
00579
00580 static int
00581 tcl_MpGet(interp, objc, objv, mp, mpip)
00582 Tcl_Interp *interp;
00583 int objc;
00584 Tcl_Obj *CONST objv[];
00585 DB_MPOOLFILE *mp;
00586 DBTCL_INFO *mpip;
00587 {
00588 static const char *mpget[] = {
00589 "-create",
00590 "-last",
00591 "-new",
00592 NULL
00593 };
00594 enum mpget {
00595 MPGET_CREATE,
00596 MPGET_LAST,
00597 MPGET_NEW
00598 };
00599
00600 DBTCL_INFO *ip;
00601 Tcl_Obj *res;
00602 db_pgno_t pgno;
00603 u_int32_t flag;
00604 int i, ipgno, optindex, result, ret;
00605 char newname[MSG_SIZE];
00606 void *page;
00607
00608 result = TCL_OK;
00609 memset(newname, 0, MSG_SIZE);
00610 i = 2;
00611 flag = 0;
00612 while (i < objc) {
00613 if (Tcl_GetIndexFromObj(interp, objv[i],
00614 mpget, "option", TCL_EXACT, &optindex) != TCL_OK) {
00615
00616
00617
00618
00619
00620 if (IS_HELP(objv[i]) == TCL_OK)
00621 return (TCL_OK);
00622 Tcl_ResetResult(interp);
00623 break;
00624 }
00625 i++;
00626 switch ((enum mpget)optindex) {
00627 case MPGET_CREATE:
00628 flag |= DB_MPOOL_CREATE;
00629 break;
00630 case MPGET_LAST:
00631 flag |= DB_MPOOL_LAST;
00632 break;
00633 case MPGET_NEW:
00634 flag |= DB_MPOOL_NEW;
00635 break;
00636 }
00637 if (result != TCL_OK)
00638 goto error;
00639 }
00640
00641
00642
00643 ipgno = 0;
00644 if (i != objc) {
00645 if (i != objc - 1) {
00646 Tcl_WrongNumArgs(interp, 2, objv, "?args? ?pgno?");
00647 result = TCL_ERROR;
00648 goto error;
00649 }
00650 result = Tcl_GetIntFromObj(interp, objv[i++], &ipgno);
00651 if (result != TCL_OK)
00652 goto error;
00653 }
00654
00655 snprintf(newname, sizeof(newname), "%s.pg%d",
00656 mpip->i_name, mpip->i_mppgid);
00657 ip = _NewInfo(interp, NULL, newname, I_PG);
00658 if (ip == NULL) {
00659 Tcl_SetResult(interp, "Could not set up info",
00660 TCL_STATIC);
00661 return (TCL_ERROR);
00662 }
00663 _debug_check();
00664 pgno = (db_pgno_t)ipgno;
00665 ret = mp->get(mp, &pgno, flag, &page);
00666 result = _ReturnSetup(interp, ret, DB_RETOK_MPGET(ret), "mpool get");
00667 if (result == TCL_ERROR)
00668 _DeleteInfo(ip);
00669 else {
00670
00671
00672
00673
00674 mpip->i_mppgid++;
00675 ip->i_parent = mpip;
00676 ip->i_pgno = pgno;
00677 ip->i_pgsz = mpip->i_pgsz;
00678 _SetInfoData(ip, page);
00679 (void)Tcl_CreateObjCommand(interp, newname,
00680 (Tcl_ObjCmdProc *)pg_Cmd, (ClientData)page, NULL);
00681 res = NewStringObj(newname, strlen(newname));
00682 Tcl_SetObjResult(interp, res);
00683 }
00684 error:
00685 return (result);
00686 }
00687
00688
00689
00690
00691
00692 static int
00693 pg_Cmd(clientData, interp, objc, objv)
00694 ClientData clientData;
00695 Tcl_Interp *interp;
00696 int objc;
00697 Tcl_Obj *CONST objv[];
00698 {
00699 static const char *pgcmds[] = {
00700 "init",
00701 "is_setto",
00702 "pgnum",
00703 "pgsize",
00704 "put",
00705 "set",
00706 NULL
00707 };
00708 enum pgcmds {
00709 PGINIT,
00710 PGISSET,
00711 PGNUM,
00712 PGSIZE,
00713 PGPUT,
00714 PGSET
00715 };
00716 DB_MPOOLFILE *mp;
00717 int cmdindex, length, result;
00718 char *obj_name;
00719 void *page;
00720 DBTCL_INFO *pgip;
00721 Tcl_Obj *res;
00722
00723 Tcl_ResetResult(interp);
00724 page = (void *)clientData;
00725 obj_name = Tcl_GetStringFromObj(objv[0], &length);
00726 pgip = _NameToInfo(obj_name);
00727 mp = NAME_TO_MP(pgip->i_parent->i_name);
00728 result = TCL_OK;
00729
00730 if (page == NULL) {
00731 Tcl_SetResult(interp, "NULL page pointer", TCL_STATIC);
00732 return (TCL_ERROR);
00733 }
00734 if (mp == NULL) {
00735 Tcl_SetResult(interp, "NULL mp pointer", TCL_STATIC);
00736 return (TCL_ERROR);
00737 }
00738 if (pgip == NULL) {
00739 Tcl_SetResult(interp, "NULL page info pointer", TCL_STATIC);
00740 return (TCL_ERROR);
00741 }
00742
00743
00744
00745
00746
00747 if (Tcl_GetIndexFromObj(interp,
00748 objv[1], pgcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00749 return (IS_HELP(objv[1]));
00750
00751 res = NULL;
00752 switch ((enum pgcmds)cmdindex) {
00753 case PGNUM:
00754 res = Tcl_NewWideIntObj((Tcl_WideInt)pgip->i_pgno);
00755 break;
00756 case PGSIZE:
00757 res = Tcl_NewWideIntObj((Tcl_WideInt)pgip->i_pgsz);
00758 break;
00759 case PGSET:
00760 case PGPUT:
00761 result = tcl_Pg(interp, objc, objv, page, mp, pgip,
00762 (enum pgcmds)cmdindex == PGSET ? 0 : 1);
00763 break;
00764 case PGINIT:
00765 result = tcl_PgInit(interp, objc, objv, page, pgip);
00766 break;
00767 case PGISSET:
00768 result = tcl_PgIsset(interp, objc, objv, page, pgip);
00769 break;
00770 }
00771
00772
00773
00774
00775
00776 if (result == TCL_OK && res != NULL)
00777 Tcl_SetObjResult(interp, res);
00778 return (result);
00779 }
00780
00781 static int
00782 tcl_Pg(interp, objc, objv, page, mp, pgip, putop)
00783 Tcl_Interp *interp;
00784 int objc;
00785 Tcl_Obj *CONST objv[];
00786 void *page;
00787 DB_MPOOLFILE *mp;
00788 DBTCL_INFO *pgip;
00789 int putop;
00790 {
00791 static const char *pgopt[] = {
00792 "-clean",
00793 "-dirty",
00794 "-discard",
00795 NULL
00796 };
00797 enum pgopt {
00798 PGCLEAN,
00799 PGDIRTY,
00800 PGDISCARD
00801 };
00802 u_int32_t flag;
00803 int i, optindex, result, ret;
00804
00805 result = TCL_OK;
00806 i = 2;
00807 flag = 0;
00808 while (i < objc) {
00809 if (Tcl_GetIndexFromObj(interp, objv[i],
00810 pgopt, "option", TCL_EXACT, &optindex) != TCL_OK)
00811 return (IS_HELP(objv[i]));
00812 i++;
00813 switch ((enum pgopt)optindex) {
00814 case PGCLEAN:
00815 flag |= DB_MPOOL_CLEAN;
00816 break;
00817 case PGDIRTY:
00818 flag |= DB_MPOOL_DIRTY;
00819 break;
00820 case PGDISCARD:
00821 flag |= DB_MPOOL_DISCARD;
00822 break;
00823 }
00824 }
00825
00826 _debug_check();
00827 if (putop)
00828 ret = mp->put(mp, page, flag);
00829 else
00830 ret = mp->set(mp, page, flag);
00831
00832 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "page");
00833
00834 if (putop) {
00835 (void)Tcl_DeleteCommand(interp, pgip->i_name);
00836 _DeleteInfo(pgip);
00837 }
00838 return (result);
00839 }
00840
00841 static int
00842 tcl_PgInit(interp, objc, objv, page, pgip)
00843 Tcl_Interp *interp;
00844 int objc;
00845 Tcl_Obj *CONST objv[];
00846 void *page;
00847 DBTCL_INFO *pgip;
00848 {
00849 Tcl_Obj *res;
00850 long *p, *endp, newval;
00851 int length, pgsz, result;
00852 u_char *s;
00853
00854 result = TCL_OK;
00855 if (objc != 3) {
00856 Tcl_WrongNumArgs(interp, 2, objv, "val");
00857 return (TCL_ERROR);
00858 }
00859
00860 pgsz = pgip->i_pgsz;
00861 result = Tcl_GetLongFromObj(interp, objv[2], &newval);
00862 if (result != TCL_OK) {
00863 s = Tcl_GetByteArrayFromObj(objv[2], &length);
00864 if (s == NULL)
00865 return (TCL_ERROR);
00866 memcpy(page, s, (size_t)((length < pgsz) ? length : pgsz));
00867 result = TCL_OK;
00868 } else {
00869 p = (long *)page;
00870 for (endp = p + ((u_int)pgsz / sizeof(long)); p < endp; p++)
00871 *p = newval;
00872 }
00873 res = Tcl_NewIntObj(0);
00874 Tcl_SetObjResult(interp, res);
00875 return (result);
00876 }
00877
00878 static int
00879 tcl_PgIsset(interp, objc, objv, page, pgip)
00880 Tcl_Interp *interp;
00881 int objc;
00882 Tcl_Obj *CONST objv[];
00883 void *page;
00884 DBTCL_INFO *pgip;
00885 {
00886 Tcl_Obj *res;
00887 long *p, *endp, newval;
00888 int length, pgsz, result;
00889 u_char *s;
00890
00891 result = TCL_OK;
00892 if (objc != 3) {
00893 Tcl_WrongNumArgs(interp, 2, objv, "val");
00894 return (TCL_ERROR);
00895 }
00896
00897 pgsz = pgip->i_pgsz;
00898 result = Tcl_GetLongFromObj(interp, objv[2], &newval);
00899 if (result != TCL_OK) {
00900 if ((s = Tcl_GetByteArrayFromObj(objv[2], &length)) == NULL)
00901 return (TCL_ERROR);
00902 result = TCL_OK;
00903
00904 if (memcmp(page, s,
00905 (size_t)((length < pgsz) ? length : pgsz)) != 0) {
00906 res = Tcl_NewIntObj(0);
00907 Tcl_SetObjResult(interp, res);
00908 return (result);
00909 }
00910 } else {
00911 p = (long *)page;
00912
00913
00914
00915
00916
00917 for (endp = p + ((u_int)pgsz / sizeof(long)); p < endp; p++)
00918 if (*p != newval) {
00919 res = Tcl_NewIntObj(0);
00920 Tcl_SetObjResult(interp, res);
00921 return (result);
00922 }
00923 }
00924
00925 res = Tcl_NewIntObj(1);
00926 Tcl_SetObjResult(interp, res);
00927 return (result);
00928 }
00929 #endif