2
* See the file LICENSE for redistribution information.
4
* Copyright (c) 1999-2001
5
* Sleepycat Software. All rights reserved.
11
static const char revid[] = "$Id$";
14
#ifndef NO_SYSTEM_INCLUDES
15
#include <sys/types.h>
24
#include "dbinc/tcl_db.h"
27
* Prototypes for procedures defined later in this file:
29
static int mutex_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
33
* Implements rand* functions.
35
* PUBLIC: int bdb_RandCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
38
bdb_RandCommand(interp, objc, objv)
39
Tcl_Interp *interp; /* Interpreter */
40
int objc; /* How many arguments? */
41
Tcl_Obj *CONST objv[]; /* The argument objects */
43
static char *rcmds[] = {
44
"rand", "random_int", "srand",
48
RRAND, RRAND_INT, RSRAND
51
int cmdindex, hi, lo, result, ret;
57
* Get the command name index from the object based on the cmds
58
* defined above. This SHOULD NOT fail because we already checked
59
* in the 'berkdb' command.
61
if (Tcl_GetIndexFromObj(interp,
62
objv[1], rcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
63
return (IS_HELP(objv[1]));
66
switch ((enum rcmds)cmdindex) {
69
* Must be 0 args. Error if different.
72
Tcl_WrongNumArgs(interp, 2, objv, NULL);
76
res = Tcl_NewIntObj(ret);
80
* Must be 4 args. Error if different.
83
Tcl_WrongNumArgs(interp, 2, objv, "lo hi");
86
result = Tcl_GetIntFromObj(interp, objv[2], &lo);
89
result = Tcl_GetIntFromObj(interp, objv[3], &hi);
90
if (result == TCL_OK) {
92
#define RAND_MAX 0x7fffffff
96
snprintf(msg, MSG_SIZE,
97
"Max random is higher than %ld\n",
99
Tcl_SetResult(interp, msg, TCL_VOLATILE);
104
ret = (int)(((double)t / ((double)(RAND_MAX) + 1)) *
107
res = Tcl_NewIntObj(ret);
112
* Must be 1 arg. Error if different.
115
Tcl_WrongNumArgs(interp, 2, objv, "seed");
118
result = Tcl_GetIntFromObj(interp, objv[2], &lo);
119
if (result == TCL_OK) {
121
res = Tcl_NewIntObj(0);
126
* Only set result if we have a res. Otherwise, lower
127
* functions have already done so.
129
if (result == TCL_OK && res)
130
Tcl_SetObjResult(interp, res);
137
* Opens an env mutex.
139
* PUBLIC: int tcl_Mutex __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *,
140
* PUBLIC: DBTCL_INFO *));
143
tcl_Mutex(interp, objc, objv, envp, envip)
144
Tcl_Interp *interp; /* Interpreter */
145
int objc; /* How many arguments? */
146
Tcl_Obj *CONST objv[]; /* The argument objects */
147
DB_ENV *envp; /* Environment pointer */
148
DBTCL_INFO *envip; /* Info pointer */
153
int i, mode, nitems, result, ret;
154
char newname[MSG_SIZE];
158
mode = nitems = ret = 0;
159
memset(newname, 0, MSG_SIZE);
162
Tcl_WrongNumArgs(interp, 2, objv, "mode nitems");
165
result = Tcl_GetIntFromObj(interp, objv[2], &mode);
166
if (result != TCL_OK)
168
result = Tcl_GetIntFromObj(interp, objv[3], &nitems);
169
if (result != TCL_OK)
172
snprintf(newname, sizeof(newname),
173
"%s.mutex%d", envip->i_name, envip->i_envmutexid);
174
ip = _NewInfo(interp, NULL, newname, I_MUTEX);
176
Tcl_SetResult(interp, "Could not set up info",
187
* We don't bother doing this "right", i.e., using the shalloc
188
* functions, just grab some memory knowing that it's correctly
192
if (__os_calloc(NULL, 1, sizeof(_MUTEX_DATA), &md) != 0)
195
md->n_mutex = nitems;
196
md->size = sizeof(_MUTEX_ENTRY) * nitems;
198
md->reginfo.type = REGION_TYPE_MUTEX;
199
md->reginfo.id = INVALID_REGION_TYPE;
200
md->reginfo.mode = mode;
201
md->reginfo.flags = REGION_CREATE_OK | REGION_JOIN_OK;
202
if ((ret = __db_r_attach(envp, &md->reginfo, md->size)) != 0)
204
md->marray = md->reginfo.addr;
206
/* Initialize a created region. */
207
if (F_ISSET(&md->reginfo, REGION_CREATE))
208
for (i = 0; i < nitems; i++) {
209
md->marray[i].val = 0;
210
if ((ret = __db_mutex_init_int(envp,
211
&md->marray[i].m, i, 0)) != 0)
214
R_UNLOCK(envp, &md->reginfo);
217
* Success. Set up return. Set up new info
218
* and command widget for this mutex.
220
envip->i_envmutexid++;
221
ip->i_parent = envip;
222
_SetInfoData(ip, md);
223
Tcl_CreateObjCommand(interp, newname,
224
(Tcl_ObjCmdProc *)mutex_Cmd, (ClientData)md, NULL);
225
res = Tcl_NewStringObj(newname, strlen(newname));
226
Tcl_SetObjResult(interp, res);
232
Tcl_PosixError(interp);
233
result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mutex");
237
if (md->reginfo.addr != NULL)
238
(void)__db_r_detach(md->env,
239
&md->reginfo, F_ISSET(&md->reginfo, REGION_CREATE));
240
__os_free(md->env, md);
247
* Implements the "mutex" widget.
250
mutex_Cmd(clientData, interp, objc, objv)
251
ClientData clientData; /* Mutex handle */
252
Tcl_Interp *interp; /* Interpreter */
253
int objc; /* How many arguments? */
254
Tcl_Obj *CONST objv[]; /* The argument objects */
256
static char *mxcmds[] = {
272
DBTCL_INFO *envip, *mpip;
275
int cmdindex, id, result, newval;
277
Tcl_ResetResult(interp);
278
mp = (_MUTEX_DATA *)clientData;
279
mpip = _PtrToInfo((void *)mp);
280
envip = mpip->i_parent;
281
dbenv = envip->i_envp;
285
Tcl_SetResult(interp, "NULL mp pointer", TCL_STATIC);
289
Tcl_SetResult(interp, "NULL mp info pointer", TCL_STATIC);
294
* Get the command name index from the object based on the dbcmds
297
if (Tcl_GetIndexFromObj(interp,
298
objv[1], mxcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
299
return (IS_HELP(objv[1]));
302
switch ((enum mxcmds)cmdindex) {
305
Tcl_WrongNumArgs(interp, 1, objv, NULL);
309
(void)__db_r_detach(mp->env, &mp->reginfo, 0);
310
res = Tcl_NewIntObj(0);
311
(void)Tcl_DeleteCommand(interp, mpip->i_name);
313
__os_free(mp->env, mp);
317
* Check for 1 arg. Error if different.
320
Tcl_WrongNumArgs(interp, 2, objv, "id");
323
result = Tcl_GetIntFromObj(interp, objv[2], &id);
324
if (result != TCL_OK)
326
MUTEX_UNLOCK(dbenv, &mp->marray[id].m);
327
res = Tcl_NewIntObj(0);
331
* Check for 1 arg. Error if different.
334
Tcl_WrongNumArgs(interp, 2, objv, "id");
337
result = Tcl_GetIntFromObj(interp, objv[2], &id);
338
if (result != TCL_OK)
340
MUTEX_LOCK(dbenv, &mp->marray[id].m);
341
res = Tcl_NewIntObj(0);
345
* Check for 1 arg. Error if different.
348
Tcl_WrongNumArgs(interp, 2, objv, "id");
351
result = Tcl_GetIntFromObj(interp, objv[2], &id);
352
if (result != TCL_OK)
354
res = Tcl_NewLongObj((long)mp->marray[id].val);
358
* Check for 2 args. Error if different.
361
Tcl_WrongNumArgs(interp, 2, objv, "id val");
364
result = Tcl_GetIntFromObj(interp, objv[2], &id);
365
if (result != TCL_OK)
367
result = Tcl_GetIntFromObj(interp, objv[3], &newval);
368
if (result != TCL_OK)
370
mp->marray[id].val = newval;
371
res = Tcl_NewIntObj(0);
375
* Only set result if we have a res. Otherwise, lower
376
* functions have already done so.
378
if (result == TCL_OK && res)
379
Tcl_SetObjResult(interp, res);