View Source

[modwtcl]
apreq.h
dist/
libapreq1/
mod_wtcl.c
mod_wtcl.h
setupExclude.txt
util/
win.def
win.mak
wt1.1/
WtAppTable.c
WtAppTable.h
WtBasicCmds.c
WtBasicCmds.h
WtClientRequest.c
WtClientRequest.h
WtCollection.c
WtCollection.h
WtCollectionCmds.c
WtCollectionCmds.h
WtContext.c
WtContext.h
WtContextEvents.c
WtContextEvents.h
WtCookie.c
WtCookie.h
WtDbSession.c
WtDbSession.h
WtExecute.c
WtExecute.h
WtHtmlEntities.c
WtHtmlEntities.h
WtInitCmds.c
WtInitCmds.h
WtMtTable.c
WtMtTable.h
WtMultiTable.c
WtMultiTable.h
WtOS.h
WtProcSession.c
WtProcSession.h
WtResponse.c
WtResponse.h
WtServerCmds.c
WtServerCmds.h
WtSession.c
WtSession.h
WtSettings.c
WtSettings.h
WtTable.c
WtTable.h
WtTableCmds.c
WtTableCmds.h
WtTableUtil.c
WtTableUtil.h
WtUpload.c
WtUpload.h
WtUtil.c
WtUtil.h
WtWebErrors.c
WtWebErrors.h
WtWindows.h
File: / archive / modwtcl / WtDbSession.c

Lines Size Modified Created Owner MIME Types
1,663 42,311 2010/05/08 18:46:41 2011/06/13 15:35:15 BUILTIN\Administrators text/x-csrc

0001
/*
0002
 * Copyright 2001 Alexander Boverman and the original authors.
0003
 * 
0004
 * Licensed under the Apache License, Version 2.0 (the "License");
0005
 * you may not use this file except in compliance with the License.
0006
 * You may obtain a copy of the License at
0007
 * 
0008
 *      http://www.apache.org/licenses/LICENSE-2.0
0009
 * 
0010
 * Unless required by applicable law or agreed to in writing, software
0011
 * distributed under the License is distributed on an "AS IS" BASIS,
0012
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013
 * See the License for the specific language governing permissions and
0014
 * limitations under the License.
0015
 */
0016
0017
#include "WtDbSession.h"
0018
#include "WtUtil.h"
0019
#include "WtTable.h"
0020
#include "WtTableUtil.h"
0021
0022
/* Create a new WtDbSession */
0023
0024
Tcl_Obj *WtNewDbSessionObj()
0025
{
0026
  Tcl_Obj *obj = Tcl_NewObj();
0027
  WtDbSession *ds = (WtDbSession *)ckalloc(sizeof(WtDbSession));
0028
0029
  ds->id = NULL;
0030
0031
  ds->isAutoId = 0;
0032
  ds->isOpen = 0;
0033
  ds->isFetched = 0;
0034
0035
  ds->items = WtNewTableObj();
0036
  Tcl_IncrRefCount(ds->items);
0037
0038
  ds->checkpoint = NULL;
0039
0040
  ds->isModified = 0;
0041
0042
  ds->deletions = Tcl_NewListObj(0, NULL);
0043
  Tcl_IncrRefCount(ds->deletions);
0044
0045
  ds->insertions = Tcl_NewListObj(0, NULL);
0046
  Tcl_IncrRefCount(ds->insertions);
0047
0048
  ds->isCleared = 0;
0049
  ds->commitStatus = WT_STATUS_NONE;
0050
0051
  ds->accessTime = -1;
0052
  ds->syncedAccessTime = 0;
0053
  ds->accessTimeInterval = 300;
0054
0055
#ifdef WIN32
0056
  ds->dbHandler = WtNewString("::wt::session::dbSession::odbcSession::sqlServerSession::");
0057
#else
0058
  ds->dbHandler = WtNewString(NULL);
0059
#endif /* WIN32 */
0060
0061
  Tcl_IncrRefCount(ds->dbHandler);
0062
0063
  ds->dbHandlerData = WtNewString(NULL);
0064
  Tcl_IncrRefCount(ds->dbHandlerData);
0065
0066
  ds->dbHandlerLoaded = 0;
0067
  ds->dbSessionOpened = 0;
0068
0069
  obj->internalRep.twoPtrValue.ptr1 = ds;
0070
  obj->internalRep.twoPtrValue.ptr2 = NULL;
0071
  obj->typePtr = &WtDbSessionType;
0072
  Tcl_InvalidateStringRep(obj);
0073
0074
  return obj;
0075
}
0076
0077
/* Get the internal rep */
0078
0079
WtDbSession *WtDbSessionRep(Tcl_Obj *obj)
0080
{
0081
  return (WtDbSession *)obj->internalRep.twoPtrValue.ptr1;
0082
}
0083
0084
/* Copy a WtDbSession */
0085
0086
static void WtDbSessionDup(Tcl_Obj *src, Tcl_Obj *dst)
0087
{
0088
  WtDbSession *srcRep = WtDbSessionRep(src);
0089
  WtDbSession *dstRep = (WtDbSession *)ckalloc(sizeof(WtDbSession));
0090
0091
  if (srcRep->id) {
0092
    dstRep->id = Tcl_DuplicateObj(srcRep->id);
0093
    Tcl_IncrRefCount(dstRep->id);
0094
  } else {
0095
    dstRep->id = NULL;
0096
  }
0097
0098
  dstRep->isAutoId = srcRep->isAutoId;
0099
  dstRep->isOpen = srcRep->isOpen;
0100
  dstRep->isFetched = srcRep->isFetched;
0101
0102
  dstRep->items = Tcl_DuplicateObj(srcRep->items);
0103
  Tcl_IncrRefCount(dstRep->items);
0104
0105
  if (srcRep->checkpoint) {
0106
    dstRep->checkpoint = Tcl_DuplicateObj(srcRep->checkpoint);
0107
    Tcl_IncrRefCount(dstRep->checkpoint);
0108
  } else {
0109
    dstRep->checkpoint = srcRep->checkpoint;
0110
  }
0111
0112
  dstRep->isModified = srcRep->isModified;
0113
0114
  dstRep->deletions = Tcl_DuplicateObj(srcRep->deletions);
0115
  Tcl_IncrRefCount(dstRep->deletions);
0116
0117
  dstRep->insertions = Tcl_DuplicateObj(srcRep->insertions);
0118
  Tcl_IncrRefCount(dstRep->insertions);
0119
0120
  dstRep->isCleared = srcRep->isCleared;
0121
  dstRep->commitStatus = srcRep->commitStatus;
0122
0123
  dstRep->accessTime = srcRep->accessTime;
0124
  dstRep->syncedAccessTime = srcRep->syncedAccessTime;
0125
  dstRep->accessTimeInterval = srcRep->accessTimeInterval;
0126
0127
  dstRep->dbHandler = Tcl_DuplicateObj(srcRep->dbHandler);
0128
  Tcl_IncrRefCount(dstRep->dbHandler);
0129
0130
  dstRep->dbHandlerData = Tcl_DuplicateObj(srcRep->dbHandlerData);
0131
  Tcl_IncrRefCount(dstRep->dbHandlerData);
0132
0133
  dstRep->dbHandlerLoaded = srcRep->dbHandlerLoaded;
0134
  dstRep->dbSessionOpened = srcRep->dbSessionOpened;
0135
0136
  dst->internalRep.twoPtrValue.ptr1 = dstRep;
0137
  dst->internalRep.twoPtrValue.ptr2 = NULL;
0138
  dst->typePtr = &WtDbSessionType;
0139
}
0140
0141
/* Update the string rep */
0142
0143
static void WtDbSessionUpdateString(Tcl_Obj *obj)
0144
{
0145
  WtUpdateProtectedObjString(obj);
0146
}
0147
0148
/* Convert an obj to a WtDbSession */
0149
0150
static int WtDbSessionSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj)
0151
{
0152
  return WtSetProtectedObjFromAny(interp, obj, &WtDbSessionType);
0153
}
0154
0155
/* Free a WtDbSession */
0156
0157
static void WtDbSessionFree(Tcl_Obj *obj)
0158
{
0159
  WtDbSession *ds;
0160
0161
  ds = WtDbSessionRep(obj);
0162
0163
  if (ds->id) {
0164
    Tcl_DecrRefCount(ds->id);
0165
  }
0166
  Tcl_DecrRefCount(ds->items);
0167
  Tcl_DecrRefCount(ds->deletions);
0168
  Tcl_DecrRefCount(ds->insertions);
0169
  Tcl_DecrRefCount(ds->dbHandler);
0170
  Tcl_DecrRefCount(ds->dbHandlerData);
0171
0172
  ckfree((char *)(ds));
0173
}
0174
0175
/* DB session type */
0176
0177
struct Tcl_ObjType WtDbSessionType =
0178
{
0179
  "dbSession",
0180
  WtDbSessionFree,
0181
  WtDbSessionDup,
0182
  WtDbSessionUpdateString,
0183
  WtDbSessionSetFromAny
0184
};
0185
0186
/* Initialize the DB session ID */
0187
0188
int WtInitDbSessionId(WtDbSession *ds, Tcl_Interp *interp)
0189
{
0190
  int ok = 0;
0191
  WtSession *s;
0192
0193
  if (ds->id) {
0194
    ok = 1;
0195
  } else {
0196
    s = WtGetAssocSession(interp);
0197
    if (ds->id = WtGetInitialSessionId(s, &ds->isAutoId, interp)) {
0198
      Tcl_IncrRefCount(ds->id);
0199
      ok = 1;
0200
    }
0201
  }
0202
0203
  return ok;
0204
}
0205
0206
/* Get the session ID */
0207
0208
Tcl_Obj *WtGetDbSessionId(WtDbSession *ds, Tcl_Interp *interp)
0209
{
0210
  return WtInitDbSessionId(ds, interp) ? ds->id : NULL;
0211
}
0212
0213
/* Set the session ID. Closes the current session. */
0214
0215
int WtSetDbSessionId(WtDbSession *ds, Tcl_Obj *id, Tcl_Interp *interp)
0216
{
0217
  int ok = 0;
0218
0219
  if (!Tcl_GetCharLength(id)) {
0220
    Tcl_AppendResult(interp, "Session ID string is invalid.", NULL);
0221
  } else if (ds->id && !strcmp(WtToString(ds->id), WtToString(id))) {
0222
    ok = 1;
0223
  } else if (!ds->isOpen || WtCloseDbSession(ds, interp, 1)) {
0224
    if (ds->id) {
0225
      Tcl_DecrRefCount(ds->id);
0226
    }
0227
    ds->id = id;
0228
    Tcl_IncrRefCount(ds->id);
0229
    ds->isAutoId = 0;
0230
    ok = 1;
0231
  }
0232
0233
  return ok;
0234
}
0235
0236
/* Open the session */
0237
0238
int WtOpenDbSession(WtDbSession *ds, Tcl_Interp *interp)
0239
{
0240
  int ok = 0;
0241
0242
  if (ds->isOpen) {
0243
    ok = 1;
0244
  } else if (WtInitDbSessionId(ds, interp)) {
0245
    ds->isOpen = 1;
0246
    ok = 1;
0247
  }
0248
0249
  return ok;
0250
}
0251
0252
/* Close the session */
0253
0254
int WtCloseDbSession(WtDbSession *ds, Tcl_Interp *interp, int doCommit)
0255
{
0256
  int ok = 0;
0257
0258
  if (!ds->isOpen) {
0259
    ok = 1;
0260
  } else if (!WtCommitIsPending(ds) ||
0261
      (doCommit && WtCommitDbSession(ds, interp))) {
0262
    if (!ds->dbSessionOpened ||
0263
        WtCloseDbSessionResource(ds, interp)) {
0264
      ds->isOpen = 0;
0265
      ds->accessTime = -1;
0266
      ds->syncedAccessTime = 0;
0267
      ds->commitStatus = WT_STATUS_NONE;
0268
      WtClearDbSessionCache(ds, interp);
0269
      WtClearDbSessionUpdates(ds, interp);
0270
      ok = 1;
0271
    }
0272
  }
0273
0274
  return ok;
0275
}
0276
0277
/* Open the session resource */
0278
0279
int WtOpenDbSessionResource(WtDbSession *ds, Tcl_Interp *interp)
0280
{
0281
  int ok = 0;
0282
0283
  if (ds->dbSessionOpened) {
0284
    ok = 1;
0285
  } else if (ds->isOpen || WtOpenDbSession(ds, interp)) {
0286
    if (WtDbSessionHandlerStr(ds, ds->dbHandler,
0287
        "open", interp, 1, &ds->id) == TCL_OK) {
0288
      ds->dbSessionOpened = 1;
0289
      ok = 1;
0290
    }
0291
  }
0292
0293
  return ok;
0294
}
0295
0296
/* Close the session resource */
0297
0298
int WtCloseDbSessionResource(WtDbSession *ds, Tcl_Interp *interp)
0299
{
0300
  int ok = 0;
0301
0302
  if (!ds->dbSessionOpened) {
0303
    ok = 1;
0304
  } else if (WtDbSessionHandlerStr(ds, ds->dbHandler,
0305
      "close", interp, 1, &ds->id) == TCL_OK) {
0306
    ds->dbSessionOpened = 0;
0307
    ok = 1;
0308
  }
0309
0310
  return ok;
0311
}
0312
0313
/* Set the handler. Unloads the current handler. */
0314
0315
int WtSetDbSessionHandler(WtDbSession *ds, Tcl_Obj *handler, Tcl_Interp *interp)
0316
{
0317
  int ok = 0;
0318
0319
  if (!Tcl_GetCharLength(handler)) {
0320
    Tcl_AppendResult(interp, "Database handler string is invalid.", NULL);
0321
  } else if (!strcmp(WtToString(ds->dbHandler), WtToString(handler))) {
0322
    ok = 1;
0323
  } else if (!ds->dbHandlerLoaded || WtUnloadDbSessionStore(ds, interp, 1)) {
0324
    Tcl_DecrRefCount(ds->dbHandler);
0325
    ds->dbHandler = handler;
0326
    Tcl_IncrRefCount(ds->dbHandler);
0327
    ok = 1;
0328
  }
0329
0330
  return ok;
0331
}
0332
0333
/* Load the handler */
0334
0335
int WtLoadDbSessionStore(WtDbSession *ds, Tcl_Interp *interp)
0336
{
0337
  int ok = 0;
0338
0339
  if (ds->dbHandlerLoaded) {
0340
    ok = 1;
0341
  } else if (!Tcl_GetCharLength(ds->dbHandler)) {
0342
    Tcl_AppendResult(interp, "Database handler string is invalid.", NULL);
0343
  } else if (WtDbSessionHandlerStr(ds, ds->dbHandler,
0344
      "load", interp, 0, NULL) == TCL_OK) {
0345
    ds->dbHandlerLoaded = 1;
0346
    ok = 1;
0347
  }
0348
0349
  return ok;
0350
}
0351
0352
/* Unload the handler */
0353
0354
int WtUnloadDbSessionStore(WtDbSession *ds, Tcl_Interp *interp, int doClose)
0355
{
0356
  int ok = 1;
0357
  Tcl_Obj *err, *msg;
0358
0359
  msg = WtNewString(NULL);
0360
  Tcl_IncrRefCount(msg);
0361
0362
  if (ds->dbHandlerLoaded) {
0363
    if (doClose && ds->isOpen && !WtCloseDbSession(ds, interp, 1)) {
0364
      err = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
0365
      Tcl_AppendObjToObj(msg, err);
0366
      ok = 0;
0367
    }
0368
0369
    if (WtDbSessionHandlerStr(ds, ds->dbHandler,
0370
        "unload", interp, 0, NULL) != TCL_OK) {
0371
      err = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
0372
      if (Tcl_GetCharLength(msg)) {
0373
        Tcl_AppendToObj(msg, "\n    and\n", -1);
0374
      }
0375
      Tcl_AppendObjToObj(msg, err);
0376
      ok = 0;
0377
    } else {
0378
      ds->dbHandlerLoaded = 0;
0379
    }
0380
  }
0381
0382
  if (!ok) {
0383
    Tcl_ResetResult(interp);
0384
    Tcl_AddObjErrorInfo(interp, WtToString(msg), -1);
0385
  }
0386
0387
  Tcl_DecrRefCount(msg);
0388
0389
  return ok;
0390
}
0391
0392
/* Get all session entries */
0393
0394
int WtFetchDbSession(WtDbSession *ds, Tcl_Interp *interp)
0395
{
0396
  int ok = 0;
0397
  Tcl_Obj *obj, *key, *val, *items, *deletions, *insertions;
0398
  Tcl_HashTable *hashTable;
0399
  Tcl_HashSearch search;
0400
  Tcl_HashEntry *ent;
0401
0402
  if (ds->isFetched) {
0403
    if (WtConvertToTable(ds->items, interp)) {
0404
      ok = 1;
0405
    }
0406
  } else if (WtOpenDbSessionResource(ds, interp)) {
0407
    if (WtDbSessionHandlerStr(ds, ds->dbHandler, "fetch", interp, 1,
0408
        &ds->id) == TCL_OK) {
0409
      if (!(obj = Tcl_GetObjResult(interp))) {
0410
        Tcl_AppendResult(interp,
0411
          "Failed to fetch session items using database handler \"",
0412
          WtSafeStr(WtToString(ds->dbHandler)), "\".", NULL);
0413
      } else if (WtConvertToTable(obj, interp)) {
0414
        Tcl_IncrRefCount(obj);
0415
        if (ds->items) {
0416
          Tcl_DecrRefCount(ds->items);
0417
        }
0418
        ds->items = obj;
0419
0420
        if (ds->checkpoint) {
0421
          Tcl_DecrRefCount(ds->checkpoint);
0422
          ds->checkpoint = NULL;
0423
        }
0424
0425
        if ((items = WtGetDbSessionItems(ds, interp)) &&
0426
            (deletions = WtGetDbSessionDeletions(ds, interp)) &&
0427
            (insertions = WtGetDbSessionInsertions(ds, interp))) {
0428
          hashTable = WtGetTableMap(deletions);
0429
          ent = Tcl_FirstHashEntry(hashTable, &search);
0430
          while (ent) {
0431
            key = (Tcl_Obj *)Tcl_GetHashKey(hashTable, ent);
0432
            WtTableRemove(items, key);
0433
            ent = Tcl_NextHashEntry(&search);
0434
          }
0435
0436
          ok = 1;
0437
          hashTable = WtGetTableMap(insertions);
0438
          ent = Tcl_FirstHashEntry(hashTable, &search);
0439
0440
          while (ent) {
0441
            key = (Tcl_Obj *)Tcl_GetHashKey(hashTable, ent);
0442
            val = (Tcl_Obj *)Tcl_GetHashValue(ent);
0443
            WtTableSet(items, key, val);
0444
            ent = Tcl_NextHashEntry(&search);
0445
          }
0446
0447
          if (ok) {
0448
            ds->checkpoint = Tcl_DuplicateObj(items);
0449
            Tcl_IncrRefCount(ds->checkpoint);
0450
            ds->isFetched = 1;
0451
          }
0452
        }
0453
      }
0454
    }
0455
  }
0456
0457
  return ok;
0458
}
0459
0460
/* Get the items */
0461
0462
Tcl_Obj *WtGetDbSessionItems(WtDbSession *ds, Tcl_Interp *interp)
0463
{
0464
  if (WtOwnTable(&ds->items, interp)) {
0465
    return ds->items;
0466
  }
0467
  return NULL;
0468
}
0469
0470
/* Get the insertions */
0471
0472
Tcl_Obj *WtGetDbSessionInsertions(WtDbSession *ds, Tcl_Interp *interp)
0473
{
0474
  if (WtOwnTable(&ds->insertions, interp)) {
0475
    return ds->insertions;
0476
  }
0477
  return NULL;
0478
}
0479
0480
/* Get the deletions */
0481
0482
Tcl_Obj *WtGetDbSessionDeletions(WtDbSession *ds, Tcl_Interp *interp)
0483
{
0484
  if (WtOwnTable(&ds->deletions, interp)) {
0485
    return ds->deletions;
0486
  }
0487
  return NULL;
0488
}
0489
0490
/* Is a commit needed */
0491
0492
int WtCommitIsPending(WtDbSession *ds)
0493
{
0494
  return ds->isModified || (ds->isOpen && !ds->syncedAccessTime);
0495
}
0496
0497
/* Commit the session */
0498
0499
int WtCommitDbSession(WtDbSession *ds, Tcl_Interp *interp)
0500
{
0501
  int ok = 1, i = 0;
0502
  time_t now, accessTime = -1;
0503
  Tcl_Obj *objv[2], *tbl = NULL, *keyDeletions, *insertions, *items;
0504
  WtSession *s = WtGetAssocSession(interp);
0505
0506
  if (WtCommitIsPending(ds)) {
0507
    if (!WtOpenDbSessionResource(ds, interp)) {
0508
      ok = 0;
0509
    } else {
0510
      tbl = WtNewTableObj();
0511
      Tcl_IncrRefCount(tbl);
0512
0513
      WtTableSetStrToObj(tbl, "clearAll", WtNewBool(ds->isCleared));
0514
      WtTableSetStrToObj(tbl, "deletions", Tcl_NewListObj(0, NULL));
0515
0516
      if (!(keyDeletions = WtGetDbSessionDeletions(ds, interp))) {
0517
        ok = 0;
0518
      } else {
0519
        WtTableSetStrToObj(tbl, "keyDeletions", keyDeletions);
0520
        if (!(insertions = WtGetDbSessionInsertions(ds, interp))) {
0521
          ok = 0;
0522
        } else {
0523
          WtTableSetStrToObj(tbl, "insertions", insertions); 
0524
          WtTableSetStrToObj(tbl, "isAccessed", WtNewBool(ds->isOpen));
0525
          WtTableSetStrToObj(tbl, "updateAccessTime", WtNewBool(0));
0526
0527
          if (ds->isOpen) {
0528
            now = time(NULL);
0529
            if (s->clientTimeStamp == -1 ||
0530
                now - s->clientTimeStamp > ds->accessTimeInterval) {
0531
              accessTime = now;
0532
              WtTableSetStrToObj(tbl, "updateAccessTime", WtNewBool(1));
0533
            }
0534
          }
0535
0536
          WtTableSetStrToObj(tbl, "isModified",
0537
            WtNewBool(ds->isModified));
0538
0539
          if (ds->isFetched) {
0540
            if (!(items = WtGetDbSessionItems(ds, interp))) {
0541
              ok = 0;
0542
            } else {
0543
              WtTableSetStrToObj(tbl, "items", items);
0544
            }
0545
          }
0546
        }
0547
      }
0548
    }
0549
0550
    if (ok) {
0551
      objv[i] = ds->id;
0552
      objv[++i] = tbl;
0553
0554
      if (WtDbSessionHandlerStr(ds, ds->dbHandler, "update",
0555
          interp, i + 1, objv) != TCL_OK) {
0556
        ok = 0;
0557
      } else {
0558
        if (accessTime != -1) {
0559
          ds->accessTime = accessTime;
0560
        }
0561
        ds->syncedAccessTime = 1;
0562
        WtClearDbSessionUpdates(ds, interp);
0563
      }
0564
    }
0565
0566
    if (tbl) {
0567
      Tcl_DecrRefCount(tbl);
0568
    }
0569
0570
    ds->commitStatus = ok ? WT_STATUS_OK : WT_STATUS_ERROR;
0571
  }
0572
0573
  return ok;
0574
}
0575
0576
/* Delete a session */
0577
0578
int WtDeleteDbSession(WtDbSession *ds, Tcl_Obj *id, Tcl_Interp *interp)
0579
{
0580
  int ok = 1;
0581
0582
  if (id) {
0583
    if (!Tcl_GetCharLength(id)) {
0584
      Tcl_AppendResult(interp, "Session ID string is invalid.", NULL);
0585
      ok = 0;
0586
    }
0587
  } else if (!(id = WtGetDbSessionId(ds, interp))) {
0588
    ok = 0;
0589
  }
0590
0591
  if (ok) {
0592
    if (WtDbSessionHandlerStr(ds, ds->dbHandler, "delete",
0593
        interp, 1, &id) != TCL_OK) {
0594
      ok = 0;
0595
    } else if (ds->id && !strcmp(WtToString(id), WtToString(ds->id))) {
0596
      if (ds->isOpen) {
0597
        ok = WtCloseDbSession(ds, interp, 0);
0598
      }
0599
    }
0600
  }
0601
0602
  return ok;
0603
}
0604
0605
/* Delete stale sessions */
0606
0607
int WtSweepDbSessions(WtDbSession *ds, Tcl_Interp *interp)
0608
{
0609
  WtSession *s = WtGetAssocSession(interp);
0610
  Tcl_Obj *maxIdleTime = Tcl_NewIntObj(s->maxIdleTime);
0611
0612
  if (WtDbSessionHandlerStr(ds, ds->dbHandler, "sweep", interp,
0613
      1, &maxIdleTime) == TCL_OK) {
0614
    return 1;
0615
  }
0616
0617
  return 0;
0618
}
0619
0620
/* Clear the cache */
0621
0622
int WtClearDbSessionCache(WtDbSession *ds, Tcl_Interp *interp)
0623
{
0624
  Tcl_Obj *items;
0625
0626
  if (items = WtGetDbSessionItems(ds, interp)) {
0627
    WtClearTable(items);
0628
    ds->isFetched = 0;
0629
    return 1;
0630
  }
0631
0632
  return 0;
0633
}
0634
0635
/* Clear the updates */
0636
0637
int WtClearDbSessionUpdates(WtDbSession *ds, Tcl_Interp *interp)
0638
{
0639
  int ok = 1;
0640
  Tcl_Obj *deletions, *insertions;
0641
0642
  if (!(deletions = WtGetDbSessionDeletions(ds, interp))) {
0643
    ok = 0;
0644
  } else {
0645
    WtClearTable(deletions);
0646
    if (!(insertions = WtGetDbSessionInsertions(ds, interp))) {
0647
      ok = 0;
0648
    } else {
0649
      WtClearTable(insertions);
0650
      ds->isModified = 0;
0651
      ds->isCleared = 0;
0652
    }
0653
  }
0654
0655
  return ok;
0656
}
0657
0658
/* Unload module */
0659
0660
int WtUnloadDbSession(WtDbSession *ds, Tcl_Interp *interp)
0661
{
0662
  int ok = 1, doCommit;
0663
  Tcl_Obj *err, *msg;
0664
0665
  msg = WtNewString(NULL);
0666
  Tcl_IncrRefCount(msg);
0667
0668
  doCommit = ds->commitStatus != WT_STATUS_ERROR;
0669
0670
  if (ds->isOpen && !WtCloseDbSession(ds, interp, doCommit)) {
0671
    err = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
0672
    Tcl_AppendObjToObj(msg, err);
0673
    ok = 0;
0674
  }
0675
0676
  if (ds->dbHandlerLoaded && !WtUnloadDbSessionStore(ds, interp, 0)) {
0677
    err = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
0678
    if (Tcl_GetCharLength(msg)) {
0679
      Tcl_AppendToObj(msg, "\n    and\n", -1);
0680
    }
0681
    Tcl_AppendObjToObj(msg, err);
0682
    ok = 0;
0683
  }
0684
0685
  if (!ok) {
0686
    Tcl_ResetResult(interp);
0687
    Tcl_AddObjErrorInfo(interp, WtToString(msg), -1);
0688
  }
0689
0690
  Tcl_DecrRefCount(msg);
0691
0692
  return ok;
0693
}
0694
0695
/* Finalize request */
0696
0697
int WtDbSessionFinalizeRequest(WtDbSession *ds, Tcl_Interp *interp)
0698
{
0699
  int ok = 1;
0700
  time_t accessTime;
0701
  WtSession *s;
0702
0703
  if (ds->isOpen) {
0704
    s = WtGetAssocSession(interp);
0705
    if (WtShouldSweepSessions(s, interp)) {
0706
      ok = WtSweepDbSessions(ds, interp);
0707
    }
0708
0709
    if (WtCommitIsPending(ds) && !WtCommitDbSession(ds, interp)) {
0710
      ok = 0;
0711
    }
0712
0713
    if (ok) {
0714
      accessTime = ds->accessTime == -1 ? s->clientTimeStamp :
0715
        ds->accessTime;
0716
      ok = WtSetSessionCookie(s, ds->id, interp, accessTime);
0717
    }
0718
  }
0719
0720
  return ok;
0721
}
0722
0723
/* Session command */
0724
0725
int WtDbSessionCmd(ClientData clientData, Tcl_Interp *interp,
0726
                   int objc, Tcl_Obj *const objv[])
0727
{
0728
  WtSession *s = WtGetAssocSession(interp);
0729
  WtDbSession *ds;
0730
0731
  /* Initialize the db session */
0732
0733
  if (!s->dbSession) {
0734
    s->dbSession = WtNewDbSessionObj();
0735
  }
0736
0737
  ds = WtDbSessionRep(s->dbSession);
0738
0739
  return WtDbSessionCmdHelper(clientData, interp,
0740
    ds, objc, objv);
0741
}
0742
0743
/* Session command helper */
0744
0745
int WtDbSessionCmdHelper(ClientData clientData, Tcl_Interp *interp,
0746
                       WtDbSession *ds, int objc, Tcl_Obj *const objv[])
0747
{
0748
  int ret = TCL_ERROR;
0749
  char *subCmd;
0750
0751
  if (objc < 2) {
0752
    WtDbSessionCmdUsage(interp, objv[0]);
0753
    return ret;
0754
  }
0755
0756
  subCmd = Tcl_GetString(objv[1]);
0757
0758
  if (!strcmp(subCmd, "id")) {
0759
    ret = WtDbSessionIdCmd(clientData, interp, ds, objc, objv);
0760
  } else if (!strcmp(subCmd, "count")) {
0761
    ret = WtDbSessionCountCmd(clientData, interp, ds, objc, objv);
0762
  } else if (!strcmp(subCmd, "has")) {
0763
    ret = WtDbSessionHasCmd(clientData, interp, ds, objc, objv);
0764
  } else if (!strcmp(subCmd, "get")) {
0765
    ret = WtDbSessionGetCmd(clientData, interp, ds, objc, objv);
0766
  } else if (!strcmp(subCmd, "set")) {
0767
    ret = WtDbSessionSetCmd(clientData, interp, ds, objc, objv);
0768
  } else if (!strcmp(subCmd, "setDefault")) {
0769
    ret = WtDbSessionSetDefaultCmd(clientData, interp, ds, objc, objv);
0770
  } else if (!strcmp(subCmd, "keys")) {
0771
    ret = WtDbSessionKeysCmd(clientData, interp, ds, objc, objv);
0772
  } else if (!strcmp(subCmd, "values")) {
0773
    ret = WtDbSessionValuesCmd(clientData, interp, ds, objc, objv);
0774
  } else if (!strcmp(subCmd, "remove")) {
0775
    ret = WtDbSessionRemoveCmd(clientData, interp, ds, objc, objv);
0776
  } else if (!strcmp(subCmd, "removeList")) {
0777
    ret = WtDbSessionRemoveListCmd(clientData, interp, ds, objc, objv);
0778
  } else if (!strcmp(subCmd, "array")) {
0779
    ret = WtDbSessionArrayCmd(clientData, interp, ds, objc, objv);
0780
  } else if (!strcmp(subCmd, "items")) {
0781
    ret = WtDbSessionItemsCmd(clientData, interp, ds, objc, objv);
0782
  } else if (!strcmp(subCmd, "clear")) {
0783
    ret = WtDbSessionClearCmd(clientData, interp, ds, objc, objv);
0784
  } else if (!strcmp(subCmd, "isAccessed")) {
0785
    ret = WtDbSessionIsAccessedCmd(clientData, interp, ds, objc, objv);
0786
  } else if (!strcmp(subCmd, "isModified")) {
0787
    ret = WtDbSessionIsModifiedCmd(clientData, interp, ds, objc, objv);
0788
  } else if (!strcmp(subCmd, "commit")) {
0789
    ret = WtDbSessionCommitCmd(clientData, interp, ds, objc, objv);
0790
  } else if (!strcmp(subCmd, "touch")) {
0791
    ret = WtDbSessionTouchCmd(clientData, interp, ds, objc, objv);
0792
  } else if (!strcmp(subCmd, "clearCache")) {
0793
    ret = WtDbSessionClearCacheCmd(clientData, interp, ds, objc, objv);
0794
  } else if (!strcmp(subCmd, "status")) {
0795
    ret = WtDbSessionStatusCmd(clientData, interp, ds, objc, objv);
0796
  } else if (!strcmp(subCmd, "properties")) {
0797
    ret = WtDbSessionPropertiesCmd(clientData, interp, ds, objc, objv);
0798
  } else if (!strcmp(subCmd, "delete")) {
0799
    ret = WtDbSessionDeleteCmd(clientData, interp, ds, objc, objv);
0800
  } else if (!strcmp(subCmd, "sweep")) {
0801
    ret = WtDbSessionSweepCmd(clientData, interp, ds, objc, objv);
0802
  } else if (!strcmp(subCmd, "dbHandlerNamespace")) {
0803
    ret = WtDbSessionHandlerCmd(clientData, interp, ds, objc, objv);
0804
  } else if (!strcmp(subCmd, "dbHandlerData")) {
0805
    ret = WtDbSessionHandlerDataCmd(clientData, interp, ds, objc, objv);
0806
  } else if (!strcmp(subCmd, "dbHandlerEval")) {
0807
    ret = WtDbSessionHandlerEvalCmd(clientData, interp, ds, objc, objv);
0808
  } else if (!strcmp(subCmd, "unload")) {
0809
    ret = WtDbSessionUnloadCmd(clientData, interp, ds, objc, objv);
0810
  } else if (!strcmp(subCmd, "loadModule")) {
0811
    ret = WtDbSessionLoadModuleCmd(clientData, interp, ds, objc, objv);
0812
  } else if (!strcmp(subCmd, "unloadModule")) {
0813
    ret = WtDbSessionUnloadModuleCmd(clientData, interp, ds, objc, objv);
0814
  } else if (!strcmp(subCmd, "finalizeRequest")) {
0815
    ret = WtDbSessionFinalizeCmd(clientData, interp, ds, objc, objv);
0816
  } else {
0817
    WtDbSessionCmdUsage(interp, objv[0]);
0818
  }
0819
0820
  return ret;
0821
}
0822
0823
/* Session command usage */
0824
0825
WtDbSessionCmdUsage(Tcl_Interp *interp, Tcl_Obj *cmd)
0826
{
0827
  char *cmdStr = Tcl_GetString(cmd);
0828
0829
  Tcl_AppendResult(interp,
0830
    wtBadUsagePrefix2,
0831
    cmdStr, " id\n",
0832
    cmdStr, " count\n",
0833
    cmdStr, " has key\n",
0834
    cmdStr, " get key ?defaultValue?\n",
0835
    cmdStr, " set key value\n",
0836
    cmdStr, " setDefault key defaultValue\n",
0837
    cmdStr, " keys\n",
0838
    cmdStr, " values\n",
0839
    cmdStr, " remove key\n",
0840
    cmdStr, " removeList keys\n",
0841
    cmdStr, " array arrayName\n",
0842
    cmdStr, " items\n",
0843
    cmdStr, " clear\n",
0844
    cmdStr, " isModified\n",
0845
    cmdStr, " commit\n",
0846
    cmdStr, " clearCache\n",
0847
    cmdStr, " status ?id?\n",
0848
    cmdStr, " properties ?id?\n",
0849
    cmdStr, " delete ?id?\n",
0850
    cmdStr, " sweep\n",
0851
    cmdStr, " dbHandler\n",
0852
    cmdStr, " dbHandlerData\n",
0853
    cmdStr, " dbHandlerEval\n",
0854
    cmdStr, " load\n",
0855
    cmdStr, " unload\n",
0856
    cmdStr, " finalizeRequest\n",
0857
    NULL);
0858
}
0859
0860
/* id command */
0861
0862
int WtDbSessionIdCmd(ClientData clientData, Tcl_Interp *interp,
0863
                     WtDbSession *ds, int objc, Tcl_Obj *const objv[])
0864
{
0865
  int ret = TCL_ERROR;
0866
0867
  if (objc != 2 && objc != 3) {
0868
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0869
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
0870
    return ret;
0871
  } else if (objc == 2) {
0872
    Tcl_SetObjResult(interp, ds->id ? ds->id : WtNewString(NULL));
0873
    ret = TCL_OK;
0874
  } else if (WtSetDbSessionId(ds, objv[2], interp)) {
0875
    Tcl_SetObjResult(interp, ds->id);
0876
    ret = TCL_OK;
0877
  }
0878
0879
  return ret;
0880
}
0881
0882
/* count command */
0883
0884
int WtDbSessionCountCmd(ClientData clientData, Tcl_Interp *interp,
0885
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
0886
{
0887
  int ret = TCL_ERROR;
0888
0889
  if (objc != 2) {
0890
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0891
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
0892
    return ret;
0893
  } else if (WtFetchDbSession(ds, interp)) {
0894
    Tcl_SetObjResult(interp, Tcl_NewIntObj(WtTableSize(ds->items)));
0895
    ret = TCL_OK;
0896
  }
0897
0898
  return ret;
0899
}
0900
0901
/* has command */
0902
0903
int WtDbSessionHasCmd(ClientData clientData, Tcl_Interp *interp,
0904
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
0905
{
0906
  int ret = TCL_ERROR;
0907
0908
  if (objc != 3) {
0909
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0910
      WtToString(objv[0]), " ", WtToString(objv[1]), " key", NULL);
0911
    return ret;
0912
  } else if (WtFetchDbSession(ds, interp)) {
0913
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
0914
      WtTableHas(ds->items, objv[2])));
0915
    ret = TCL_OK;
0916
  }
0917
0918
  return ret;
0919
}
0920
0921
/* get command */
0922
0923
int WtDbSessionGetCmd(ClientData clientData, Tcl_Interp *interp,
0924
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
0925
{
0926
  int ret = TCL_ERROR;
0927
  Tcl_Obj *obj;
0928
0929
  if (objc != 3 && objc != 4) {
0930
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0931
      WtToString(objv[0]), " ", WtToString(objv[1]), " key ?defaultValue?", NULL);
0932
    return ret;
0933
  } else if (WtFetchDbSession(ds, interp)) {
0934
    obj = WtTableGet(ds->items, objv[2]);
0935
    if (obj) {
0936
      Tcl_SetObjResult(interp, obj);
0937
      ret = TCL_OK;
0938
    } else if (objc > 3) {
0939
      Tcl_SetObjResult(interp, objv[3]);
0940
      ret = TCL_OK;
0941
    } else {
0942
      Tcl_AppendResult(interp,
0943
        "No entry with key \"", Tcl_GetString(objv[2]),
0944
        "\" exists, and no default value was specified.", NULL);
0945
    }
0946
  }
0947
0948
  return ret;
0949
}
0950
0951
/* set command */
0952
0953
int WtDbSessionSetCmd(ClientData clientData, Tcl_Interp *interp,
0954
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
0955
{
0956
  int ret = TCL_ERROR;
0957
  Tcl_Obj *deletions, *insertions, *items;
0958
0959
  if (objc != 4) {
0960
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0961
      WtToString(objv[0]), " ", WtToString(objv[1]), " key value", NULL);
0962
    return ret;
0963
  } else if (WtOpenDbSession(ds, interp)) {
0964
    /* Log the update */
0965
0966
    if (deletions = WtGetDbSessionDeletions(ds, interp)) {
0967
      WtTableSet(deletions, objv[2], Tcl_NewBooleanObj(1));
0968
      if (insertions = WtGetDbSessionInsertions(ds, interp)) {
0969
        WtTableSet(insertions, objv[2], objv[3]);
0970
        ds->isModified = 1;
0971
        if (items = WtGetDbSessionItems(ds, interp)) {
0972
          WtTableSet(items, objv[2], objv[3]);
0973
          Tcl_SetObjResult(interp, objv[3]);
0974
          ret = TCL_OK;
0975
        }
0976
      }
0977
    }
0978
0979
    ret = TCL_OK;
0980
  }
0981
0982
  return ret;
0983
}
0984
0985
/* setDefault command */
0986
0987
int WtDbSessionSetDefaultCmd(ClientData clientData, Tcl_Interp *interp,
0988
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
0989
{
0990
  int ret = TCL_ERROR;
0991
  Tcl_Obj *obj, *deletions, *insertions, *items;
0992
0993
  if (objc != 4) {
0994
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0995
      WtToString(objv[0]), " ", WtToString(objv[1]), " key defaultValue",
0996
        NULL);
0997
    return ret;
0998
  } else if (WtFetchDbSession(ds, interp)) {
0999
    obj = WtTableGet(ds->items, objv[2]);
1000
    if (obj) {
1001
      Tcl_SetObjResult(interp, obj);
1002
      ret = TCL_OK;
1003
    } else {
1004
      /* Log the update */
1005
1006
      if (deletions = WtGetDbSessionDeletions(ds, interp)) {
1007
        WtTableSet(deletions, objv[2], Tcl_NewBooleanObj(1));
1008
        if (insertions = WtGetDbSessionInsertions(ds, interp)) {
1009
          WtTableSet(insertions, objv[2], objv[3]);
1010
          ds->isModified = 1;
1011
          if (items = WtGetDbSessionItems(ds, interp)) {
1012
            WtTableSet(items, objv[2], objv[3]);
1013
            Tcl_SetObjResult(interp, objv[3]);
1014
            ret = TCL_OK;
1015
          }
1016
        }
1017
      }
1018
    }
1019
  }
1020
1021
  return ret;
1022
}
1023
1024
/* keys command */
1025
1026
int WtDbSessionKeysCmd(ClientData clientData, Tcl_Interp *interp,
1027
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1028
{
1029
  int ret = TCL_ERROR;
1030
  Tcl_Obj *keys;
1031
1032
  if (objc != 2) {
1033
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1034
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1035
  } else if (WtFetchDbSession(ds, interp)) {
1036
    if (WtTableKeys(ds->items, &keys, interp)) {
1037
      Tcl_SetObjResult(interp, keys);
1038
      ret = TCL_OK;
1039
    }
1040
  }
1041
1042
  return ret;
1043
}
1044
1045
/* values command */
1046
1047
int WtDbSessionValuesCmd(ClientData clientData, Tcl_Interp *interp,
1048
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1049
{
1050
  int ret = TCL_ERROR;
1051
  Tcl_Obj *vals;
1052
1053
  if (objc != 2) {
1054
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1055
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1056
  } else if (WtFetchDbSession(ds, interp)) {
1057
    if (WtTableValues(ds->items, &vals, interp)) {
1058
      Tcl_SetObjResult(interp, vals);
1059
      ret = TCL_OK;
1060
    }
1061
  }
1062
1063
  return ret;
1064
}
1065
1066
/* remove command */
1067
1068
int WtDbSessionRemoveCmd(ClientData clientData, Tcl_Interp *interp,
1069
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1070
{
1071
  int ret = TCL_ERROR;
1072
  Tcl_Obj *deletions, *insertions, *items;
1073
1074
  if (objc != 3) {
1075
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1076
      WtToString(objv[0]), " ", WtToString(objv[1]), " key", NULL);
1077
  } else if (WtOpenDbSession(ds, interp)) {
1078
    /* Log the update */
1079
1080
    if (deletions = WtGetDbSessionDeletions(ds, interp)) {
1081
      WtTableSet(ds->deletions, objv[2], Tcl_NewBooleanObj(1));
1082
      if (insertions = WtGetDbSessionInsertions(ds, interp)) {
1083
        WtTableRemove(insertions, objv[2]);
1084
        ds->isModified = 1;
1085
        /* Update the cache */
1086
        if (items = WtGetDbSessionItems(ds, interp)) {
1087
          WtTableRemove(items, objv[2]);
1088
          ret = TCL_OK;
1089
        }
1090
      }
1091
    }
1092
  }
1093
1094
  return ret;
1095
}
1096
1097
/* removeList command */
1098
1099
int WtDbSessionRemoveListCmd(ClientData clientData, Tcl_Interp *interp,
1100
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1101
{
1102
  int ret = TCL_ERROR, listLen, i;
1103
  Tcl_Obj *key, *deletions, *insertions, *items;
1104
1105
  if (objc != 3) {
1106
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1107
      WtToString(objv[0]), " ", WtToString(objv[1]), " list", NULL);
1108
  } else {
1109
    if (Tcl_ListObjLength(interp, objv[2], &listLen) != TCL_OK) {
1110
      Tcl_AppendResult(interp,
1111
        "Argument is not a list. Usage: ",
1112
        WtToString(objv[0]), " ", WtToString(objv[1]), " list", NULL);
1113
    } else if (WtOpenDbSession(ds, interp)) {
1114
      /* Log the update */
1115
1116
      if ((deletions = WtGetDbSessionDeletions(ds, interp)) &&
1117
          (insertions = WtGetDbSessionInsertions(ds, interp))) {
1118
        ret = TCL_OK;
1119
1120
        for (i = 0; i < listLen; i++) {
1121
          if (Tcl_ListObjIndex(interp, objv[2], i, &key) != TCL_OK) {
1122
            ret = TCL_ERROR;
1123
            break;
1124
          }
1125
          WtTableSet(deletions, key, Tcl_NewBooleanObj(1));
1126
          WtTableRemove(insertions, key);
1127
        }
1128
1129
        if (ret == TCL_OK) {
1130
          ds->isModified = 1;
1131
          /* Update the cache */
1132
          if (!(items = WtGetDbSessionItems(ds, interp)) ||
1133
              !WtTableRemoveList(items, objv[2], interp)) {
1134
            ret = TCL_ERROR;
1135
          }
1136
        }
1137
      }
1138
    }
1139
  }
1140
1141
  return ret;
1142
}
1143
1144
/* array command */
1145
1146
int WtDbSessionArrayCmd(ClientData clientData, Tcl_Interp *interp,
1147
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1148
{
1149
  int ret = TCL_ERROR;
1150
1151
  if (objc != 3) {
1152
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1153
      WtToString(objv[0]), " ", WtToString(objv[1]), " arrayName",
1154
      NULL);
1155
  } else if (WtFetchDbSession(ds, interp)) {
1156
    if (WtTableToArray(interp, ds->items, objv[2], 0)) {
1157
      ret = TCL_OK;
1158
    }
1159
  }
1160
1161
  return ret;
1162
}
1163
1164
/* items command */
1165
1166
int WtDbSessionItemsCmd(ClientData clientData, Tcl_Interp *interp,
1167
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1168
{
1169
  int ret = TCL_ERROR;
1170
1171
  if (objc != 2) {
1172
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1173
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1174
  } else if (WtFetchDbSession(ds, interp)) {
1175
    Tcl_SetObjResult(interp, ds->items);
1176
    ret = TCL_OK;
1177
  }
1178
1179
  return ret;
1180
}
1181
1182
/* clear command */
1183
1184
int WtDbSessionClearCmd(ClientData clientData, Tcl_Interp *interp,
1185
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1186
{
1187
  int ret = TCL_ERROR;
1188
1189
  if (objc != 2) {
1190
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1191
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1192
  } else if (WtOpenDbSession(ds, interp)) {
1193
    WtClearDbSessionCache(ds, interp);
1194
    WtClearDbSessionUpdates(ds, interp);
1195
    ds->isCleared = 1;
1196
    ds->isModified = 1;
1197
    ret = TCL_OK;
1198
  }
1199
1200
  return ret;
1201
}
1202
1203
/* isAccessed command */
1204
1205
int WtDbSessionIsAccessedCmd(ClientData clientData, Tcl_Interp *interp,
1206
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1207
{
1208
  int ret = TCL_ERROR;
1209
1210
  if (objc != 2) {
1211
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1212
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1213
  } else {
1214
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ds->isOpen));
1215
    ret = TCL_OK;
1216
  }
1217
1218
  return ret;
1219
}
1220
1221
/* isModified command */
1222
1223
int WtDbSessionIsModifiedCmd(ClientData clientData, Tcl_Interp *interp,
1224
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1225
{
1226
  int ret = TCL_ERROR;
1227
1228
  if (objc != 2) {
1229
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1230
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1231
  } else {
1232
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ds->isModified));
1233
    ret = TCL_OK;
1234
  }
1235
1236
  return ret;
1237
}
1238
1239
/* commit command */
1240
1241
int WtDbSessionCommitCmd(ClientData clientData, Tcl_Interp *interp,
1242
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1243
{
1244
  int ret = TCL_ERROR;
1245
1246
  if (objc != 2) {
1247
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1248
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1249
  } else if (WtCommitDbSession(ds, interp)) {
1250
    ret = TCL_OK;
1251
  }
1252
1253
  return ret;
1254
}
1255
1256
/* touch command */
1257
1258
int WtDbSessionTouchCmd(ClientData clientData, Tcl_Interp *interp,
1259
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1260
{
1261
  int ret = TCL_ERROR;
1262
1263
  if (objc != 2) {
1264
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1265
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1266
  } else if (WtOpenDbSession(ds, interp)) {
1267
    ret = TCL_OK;
1268
  }
1269
1270
  return ret;
1271
}
1272
1273
/* clearCache command */
1274
1275
int WtDbSessionClearCacheCmd(ClientData clientData, Tcl_Interp *interp,
1276
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1277
{
1278
  int ret = TCL_ERROR;
1279
1280
  if (objc != 2) {
1281
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1282
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1283
  } else {
1284
    WtClearDbSessionCache(ds, interp);
1285
    ret = TCL_OK;
1286
  }
1287
1288
  return ret;
1289
}
1290
1291
/* status command
1292
 *
1293
 * Result values:
1294
 *
1295
 *     "new" - The session is new and hasn't been saved.
1296
 *     "active" - Session is active.
1297
 *     "expired" - Session has expired.
1298
 */
1299
1300
int WtDbSessionStatusCmd(ClientData clientData, Tcl_Interp *interp,
1301
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1302
{
1303
  int ret = TCL_ERROR, done = 0;
1304
  Tcl_Obj *id;
1305
1306
  if (objc != 2 && objc != 3) {
1307
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1308
      WtToString(objv[0]), " ", WtToString(objv[1]), " ?id?", NULL);
1309
  } else {
1310
    if (objc > 2) {
1311
      id = objv[2];
1312
    } else if (id = WtGetDbSessionId(ds, interp)) {
1313
      if (ds->isAutoId) {
1314
        Tcl_SetResult(interp, "new", NULL);
1315
        done = 1;
1316
      }
1317
    }
1318
    if (id && !done) {
1319
      ret = WtDbSessionHandlerStr(ds, ds->dbHandler, "status",
1320
        interp, 1, &id);
1321
    }
1322
  }
1323
1324
  return ret;
1325
}
1326
1327
/* properties command */
1328
1329
int WtDbSessionPropertiesCmd(ClientData clientData, Tcl_Interp *interp,
1330
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1331
{
1332
  int ret = TCL_ERROR, done = 0;
1333
  Tcl_Obj *id, *tbl;
1334
  WtSession *s;
1335
1336
  if (objc != 2 && objc != 3) {
1337
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1338
      WtToString(objv[0]), " ", WtToString(objv[1]), " ?id?", NULL);
1339
  } else {
1340
    id = objc > 2 ? objv[2] : WtGetDbSessionId(ds, interp);
1341
    if (id) {
1342
      if (WtDbSessionHandlerStr(ds, ds->dbHandler, "properties",
1343
          interp, 1, &id) == TCL_OK) {
1344
        if (!(tbl = Tcl_GetObjResult(interp)) ||
1345
            !WtOwnTable(&tbl, interp)) {
1346
          Tcl_AppendResult(interp, "Failed to read return value.", NULL);
1347
        } else {
1348
          Tcl_IncrRefCount(tbl);
1349
          if (WtFetchDbSession(ds, interp)) {
1350
            WtTableSetStrToInt(tbl, "size", WtTableSize(ds->items));
1351
            WtTableSetStrToObj(tbl, "id", id);
1352
            s = WtGetAssocSession(interp);
1353
            WtTableSetStrToObj(tbl, "clientValue", s->clientValue);
1354
            WtTableSetStrToObj(tbl, "clientId",
1355
              s->clientId ? s->clientId : WtNewString(NULL));
1356
            WtTableSetStrToLong(tbl, "clientTimeStamp",
1357
              (long)s->clientTimeStamp);
1358
            Tcl_SetObjResult(interp, tbl);
1359
            ret = TCL_OK;
1360
          }
1361
          Tcl_DecrRefCount(tbl);
1362
        }
1363
      }
1364
    }
1365
  }
1366
1367
  return ret;
1368
}
1369
1370
1371
/* delete command */
1372
1373
int WtDbSessionDeleteCmd(ClientData clientData, Tcl_Interp *interp,
1374
                         WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1375
{
1376
  int ret = TCL_ERROR;
1377
1378
  if (objc != 3) {
1379
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1380
      WtToString(objv[0]), " ", WtToString(objv[1]), " ?id?", NULL);
1381
  } else if (WtDeleteDbSession(ds, NULL, interp)) {
1382
    ret = TCL_OK;
1383
  }
1384
1385
  return ret;
1386
}
1387
1388
/* sweep command */
1389
1390
int WtDbSessionSweepCmd(ClientData clientData, Tcl_Interp *interp,
1391
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1392
{
1393
  int ret = TCL_ERROR;
1394
1395
  if (WtSweepDbSessions(ds, interp)) {
1396
    ret = TCL_OK;
1397
  }
1398
1399
  return ret;
1400
}
1401
1402
/* dbHandler command */
1403
1404
int WtDbSessionHandlerCmd(ClientData clientData, Tcl_Interp *interp,
1405
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1406
{
1407
  int ret = TCL_ERROR;
1408
1409
  if (objc != 2 && objc != 3) {
1410
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1411
      WtToString(objv[0]), " ", WtToString(objv[1]),
1412
      " ?dbHandler?", NULL);
1413
  } else if (objc == 2) {
1414
    Tcl_SetObjResult(interp, ds->dbHandler);
1415
    ret = TCL_OK;
1416
  } else if (objc == 3) {
1417
    if (WtSetDbSessionHandler(ds, objv[2], interp)) {
1418
      Tcl_SetObjResult(interp, ds->dbHandler);
1419
      ret = TCL_OK;
1420
    }
1421
  }
1422
1423
  return ret;
1424
}
1425
1426
/* dbHandlerData command */
1427
1428
int WtDbSessionHandlerDataCmd(ClientData clientData, Tcl_Interp *interp,
1429
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1430
{
1431
  int ret = TCL_ERROR;
1432
1433
  if (objc != 2 && objc != 3) {
1434
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1435
      WtToString(objv[0]), " ", WtToString(objv[1]),
1436
      " ?dbHandlerData?", NULL);
1437
  } else {
1438
    if (objc == 2) {
1439
      Tcl_SetObjResult(interp, ds->dbHandlerData);
1440
    } else if (objc == 3) {
1441
      Tcl_DecrRefCount(ds->dbHandlerData);
1442
      ds->dbHandlerData = objv[2];
1443
      Tcl_IncrRefCount(ds->dbHandlerData);
1444
      ret = TCL_OK;
1445
    }
1446
  }
1447
1448
  return ret;
1449
}
1450
1451
/* dbHandlerEval command */
1452
1453
int WtDbSessionHandlerEvalCmd(ClientData clientData, Tcl_Interp *interp,
1454
    WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1455
{
1456
  int ret = TCL_ERROR;
1457
1458
  if (objc < 3) {
1459
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1460
      WtToString(objv[0]), " ", WtToString(objv[1]),
1461
      " method ?parameter? ...", NULL);
1462
  } else {
1463
    ret = WtDbSessionHandlerStr(ds, ds->dbHandler, Tcl_GetString(objv[2]),
1464
      interp, objc - 3, objv + 3);
1465
  }
1466
1467
  return ret;
1468
}
1469
1470
/* unload command */
1471
1472
int WtDbSessionUnloadCmd(ClientData clientData, Tcl_Interp *interp,
1473
                         WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1474
{
1475
  int ret = TCL_ERROR;
1476
1477
  if (objc != 2) {
1478
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1479
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1480
  } else if (WtUnloadDbSession(ds, interp)) {
1481
    ret = TCL_OK;
1482
  }
1483
1484
  return ret;
1485
}
1486
1487
/* load command */
1488
1489
int WtDbSessionLoadModuleCmd(ClientData clientData, Tcl_Interp *interp,
1490
                             WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1491
{
1492
  int ret = TCL_ERROR;
1493
1494
  if (objc != 2) {
1495
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1496
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1497
  } else {
1498
    /* Do nothing */
1499
    ret = TCL_OK;
1500
  }
1501
1502
  return ret;
1503
}
1504
1505
/* unloadModule command */
1506
1507
int WtDbSessionUnloadModuleCmd(ClientData clientData, Tcl_Interp *interp,
1508
                               WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1509
{
1510
  WtContext *w;
1511
  int ret = TCL_ERROR;
1512
1513
  if (objc != 2) {
1514
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1515
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1516
  } else {
1517
    if (WtUnloadDbSession(ds, interp)) {
1518
      ret = TCL_OK;
1519
    }
1520
    w = WtGetAssocContext(interp);
1521
    Tcl_DecrRefCount(w->web->session.dbSession);
1522
    w->web->session.dbSession = NULL;
1523
  }
1524
1525
  return ret;
1526
}
1527
1528
/* finalizeRequest command */
1529
1530
int WtDbSessionFinalizeCmd(ClientData clientData, Tcl_Interp *interp,
1531
                           WtDbSession *ds, int objc, Tcl_Obj *const objv[])
1532
{
1533
  int ret = TCL_ERROR;
1534
1535
  if (objc != 2) {
1536
    Tcl_AppendResult(interp, wtBadUsagePrefix,
1537
      WtToString(objv[0]), " ", WtToString(objv[1]), NULL);
1538
    return ret;
1539
  } else if (WtDbSessionFinalizeRequest(ds, interp)) {
1540
    ret = TCL_OK;
1541
  }
1542
1543
  return ret;
1544
}
1545
1546
/* Invoke DB handler */
1547
1548
int WtDbSessionHandler(WtDbSession *ds, Tcl_Obj *handler,
1549
    Tcl_Obj *method, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
1550
{
1551
  return WtDbSessionHandlerInternal(ds, handler, method,
1552
    interp, objc, objv);
1553
}
1554
1555
/* Using a C string */
1556
1557
int WtDbSessionHandlerStr(WtDbSession *ds, Tcl_Obj *handler,
1558
    const char *methodStr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
1559
{
1560
  int ret;
1561
  Tcl_Obj *method = WtNewString(methodStr);
1562
  Tcl_IncrRefCount(method);
1563
  ret = WtDbSessionHandlerInternal(ds, handler, method,
1564
    interp, objc, objv);
1565
  Tcl_DecrRefCount(method);
1566
  return ret;
1567
}
1568
1569
/* All options */
1570
1571
int WtDbSessionHandlerInternal(WtDbSession *ds,
1572
    Tcl_Obj *handler, Tcl_Obj *method, Tcl_Interp *interp,
1573
    int objc, Tcl_Obj *const objv[])
1574
{
1575
  int ret = TCL_ERROR, i, len, n, addScope = 1;
1576
  Tcl_Obj **args, *cmd, *err, *res;
1577
  const char *handlerStr;
1578
1579
  if (WtPrepareDbSessionHandler(ds, method, interp)) {
1580
1581
    /* Build the command */
1582
1583
    cmd = Tcl_NewStringObj(NULL, 0);
1584
    Tcl_IncrRefCount(cmd);
1585
    Tcl_AppendObjToObj(cmd, ds->dbHandler);
1586
1587
    len = Tcl_GetCharLength(ds->dbHandler);
1588
    if (len >= 2) {
1589
      handlerStr = WtToString(ds->dbHandler);
1590
      if (handlerStr[len - 1] == ':' && handlerStr[len - 2] == ':') {
1591
        addScope = 0;
1592
      }
1593
    }
1594
1595
    if (addScope) {
1596
      Tcl_AppendToObj(cmd, "::", 2);
1597
    }
1598
1599
    Tcl_AppendObjToObj(cmd, method);
1600
1601
    n = sizeof(Tcl_Obj *) * (objc + 1);
1602
    args = (Tcl_Obj **)ckalloc(n);
1603
    args[0] = cmd;
1604
    n = objc * sizeof(Tcl_Obj *);
1605
    memcpy(args + 1, objv, n);
1606
1607
    for (i = 0; i < objc + 1; i++) {
1608
      Tcl_IncrRefCount(args[i]);
1609
    }
1610
1611
    /* Evaluate the command */
1612
1613
    WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, WtGetContext(),
1614
      "WtDbSessionHandlerInternal: Calling: \"%s\".",
1615
      WtToString(cmd));
1616
1617
    ret = Tcl_EvalObjv(interp, objc + 1, args, TCL_EVAL_DIRECT);
1618
1619
    err = Tcl_GetVar2Ex(interp, "errorInfo", NULL,
1620
     TCL_GLOBAL_ONLY);
1621
    res = Tcl_GetObjResult(interp);
1622
1623
    for (i = 0; i < objc + 1; i++) {
1624
      Tcl_DecrRefCount(args[i]);
1625
    }
1626
1627
    ckfree((char *)args);
1628
    Tcl_DecrRefCount(cmd);
1629
  }
1630
1631
  return ret;
1632
}
1633
1634
/* Prepare the db handler before passing along any commands */
1635
1636
int WtPrepareDbSessionHandler(WtDbSession *ds, Tcl_Obj *method, Tcl_Interp *interp)
1637
{
1638
  int ok = 1;
1639
  const char *methodStr = WtToString(method);
1640
1641
  if (!Tcl_GetCharLength(ds->dbHandler)) {
1642
    Tcl_AppendResult(interp, "No database handler namespace defined.",
1643
      NULL);
1644
    ok = 0;
1645
  } else {
1646
    /* Load the db handler */
1647
1648
    if (!ds->dbHandlerLoaded && strcmp(methodStr, "load") &&
1649
        strcmp(methodStr, "unload")) {
1650
      ok = WtLoadDbSessionStore(ds, interp);
1651
    }
1652
  }
1653
1654
  return ok;
1655
}
1656
1657
/* Create session commands */
1658
1659
void WtInitDbSessionCommands(Tcl_Interp *interp)
1660
{
1661
  Tcl_CreateObjCommand(interp, "::wt::session::dbSession::dbSessionHandler",
1662
    WtDbSessionCmd, NULL, NULL);
1663
}