00001
00002
00003
00004
00005
00006
00007
00008 #include "config.h"
00009
00010 #ifndef lint
00011 static const char revid[] = "$Id: txn__region_8c-source.html,v 1.1 2008/06/08 10:24:57 sebdiaz Exp $";
00012 #endif
00013
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016
00017 #if TIME_WITH_SYS_TIME
00018 #include <sys/time.h>
00019 #include <time.h>
00020 #else
00021 #if HAVE_SYS_TIME_H
00022 #include <sys/time.h>
00023 #else
00024 #include <time.h>
00025 #endif
00026 #endif
00027
00028 #include <string.h>
00029 #endif
00030
00031 #ifdef HAVE_RPC
00032 #include "db_server.h"
00033 #endif
00034
00035 #include "db_int.h"
00036 #include "db_page.h"
00037 #include "txn.h"
00038 #include "db_am.h"
00039
00040 #ifdef HAVE_RPC
00041 #include "gen_client_ext.h"
00042 #include "rpc_client_ext.h"
00043 #endif
00044
00045 static int __txn_init __P((DB_ENV *, DB_TXNMGR *));
00046 static int __txn_set_tx_max __P((DB_ENV *, u_int32_t));
00047 static int __txn_set_tx_recover __P((DB_ENV *,
00048 int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *)));
00049 static int __txn_set_tx_timestamp __P((DB_ENV *, time_t *));
00050
00051
00052
00053
00054
00055
00056
00057 void
00058 CDB___txn_dbenv_create(dbenv)
00059 DB_ENV *dbenv;
00060 {
00061 dbenv->tx_max = DEF_MAX_TXNS;
00062
00063 dbenv->set_tx_max = __txn_set_tx_max;
00064 dbenv->set_tx_recover = __txn_set_tx_recover;
00065 dbenv->set_tx_timestamp = __txn_set_tx_timestamp;
00066
00067 #ifdef HAVE_RPC
00068
00069
00070
00071
00072 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
00073 dbenv->set_tx_max = __dbcl_set_tx_max;
00074 dbenv->set_tx_recover = __dbcl_set_tx_recover;
00075 dbenv->set_tx_timestamp = __dbcl_set_tx_timestamp;
00076 }
00077 #endif
00078 }
00079
00080
00081
00082
00083
00084 static int
00085 __txn_set_tx_max(dbenv, tx_max)
00086 DB_ENV *dbenv;
00087 u_int32_t tx_max;
00088 {
00089 ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_max");
00090
00091 dbenv->tx_max = tx_max;
00092 return (0);
00093 }
00094
00095
00096
00097
00098
00099 static int
00100 __txn_set_tx_recover(dbenv, tx_recover)
00101 DB_ENV *dbenv;
00102 int (*tx_recover) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00103 {
00104 dbenv->tx_recover = tx_recover;
00105 return (0);
00106 }
00107
00108
00109
00110
00111
00112 static int
00113 __txn_set_tx_timestamp(dbenv, timestamp)
00114 DB_ENV *dbenv;
00115 time_t *timestamp;
00116 {
00117 ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_timestamp");
00118
00119 dbenv->tx_timestamp = *timestamp;
00120 return (0);
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 int
00130 CDB___txn_open(dbenv)
00131 DB_ENV *dbenv;
00132 {
00133 DB_TXNMGR *tmgrp;
00134 int ret;
00135
00136
00137 if ((ret = CDB___os_calloc(dbenv, 1, sizeof(DB_TXNMGR), &tmgrp)) != 0)
00138 return (ret);
00139 TAILQ_INIT(&tmgrp->txn_chain);
00140 tmgrp->dbenv = dbenv;
00141 tmgrp->recover =
00142 dbenv->tx_recover == NULL ? CDB___db_dispatch : dbenv->tx_recover;
00143
00144
00145 tmgrp->reginfo.id = REG_ID_TXN;
00146 tmgrp->reginfo.mode = dbenv->db_mode;
00147 if (F_ISSET(dbenv, DB_ENV_CREATE))
00148 F_SET(&tmgrp->reginfo, REGION_CREATE_OK);
00149 if ((ret = CDB___db_r_attach(dbenv,
00150 &tmgrp->reginfo, TXN_REGION_SIZE(dbenv->tx_max))) != 0)
00151 goto err;
00152
00153
00154 if (F_ISSET(&tmgrp->reginfo, REGION_CREATE))
00155 if ((ret = __txn_init(dbenv, tmgrp)) != 0)
00156 goto err;
00157
00158
00159 tmgrp->reginfo.primary =
00160 R_ADDR(&tmgrp->reginfo, tmgrp->reginfo.rp->primary);
00161
00162 R_UNLOCK(dbenv, &tmgrp->reginfo);
00163
00164
00165 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00166 if ((ret = CDB___db_mutex_alloc(
00167 dbenv, &tmgrp->reginfo, &tmgrp->mutexp)) != 0)
00168 goto detach;
00169 if ((ret = __db_mutex_init(
00170 dbenv, tmgrp->mutexp, 0, MUTEX_THREAD)) != 0)
00171 goto detach;
00172 }
00173
00174 dbenv->tx_handle = tmgrp;
00175 return (0);
00176
00177 err: if (tmgrp->reginfo.addr != NULL) {
00178 if (F_ISSET(&tmgrp->reginfo, REGION_CREATE))
00179 F_SET(tmgrp->reginfo.rp, REG_DEAD);
00180 R_UNLOCK(dbenv, &tmgrp->reginfo);
00181
00182 detach: (void)CDB___db_r_detach(dbenv, &tmgrp->reginfo, 0);
00183 }
00184 CDB___os_free(tmgrp, sizeof(*tmgrp));
00185 return (ret);
00186 }
00187
00188
00189
00190
00191
00192 static int
00193 __txn_init(dbenv, tmgrp)
00194 DB_ENV *dbenv;
00195 DB_TXNMGR *tmgrp;
00196 {
00197 DB_TXNREGION *region;
00198 int ret;
00199
00200 if ((ret = CDB___db_shalloc(tmgrp->reginfo.addr,
00201 sizeof(DB_TXNREGION), 0, &tmgrp->reginfo.primary)) != 0) {
00202 CDB___db_err(dbenv,
00203 "Unable to allocate memory for the transaction region");
00204 return (ret);
00205 }
00206 tmgrp->reginfo.rp->primary =
00207 R_OFFSET(&tmgrp->reginfo, tmgrp->reginfo.primary);
00208 region = tmgrp->reginfo.primary;
00209 memset(region, 0, sizeof(*region));
00210
00211 region->maxtxns = dbenv->tx_max;
00212 region->last_txnid = TXN_MINIMUM;
00213 ZERO_LSN(region->pending_ckp);
00214 ZERO_LSN(region->last_ckp);
00215 region->time_ckp = time(NULL);
00216
00217
00218
00219
00220
00221 region->logtype = 0;
00222 region->locktype = 0;
00223 region->naborts = 0;
00224 region->ncommits = 0;
00225 region->nbegins = 0;
00226 region->nactive = 0;
00227 region->maxnactive = 0;
00228
00229 SH_TAILQ_INIT(®ion->active_txn);
00230
00231 return (0);
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 int
00241 CDB___txn_close(dbenv)
00242 DB_ENV *dbenv;
00243 {
00244 DB_TXN *txnp;
00245 DB_TXNMGR *tmgrp;
00246 int ret, t_ret;
00247
00248 ret = 0;
00249 tmgrp = dbenv->tx_handle;
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 while ((txnp =
00263 TAILQ_FIRST(&tmgrp->txn_chain)) != TAILQ_END(&tmgrp->txn_chain))
00264 if ((t_ret = CDB_txn_abort(txnp)) != 0) {
00265 CDB___db_err(dbenv,
00266 "Unable to abort transaction 0x%x: %s\n",
00267 txnp->txnid, CDB_db_strerror(t_ret));
00268 CDB___txn_end(txnp, 0);
00269 if (ret == 0)
00270 ret = t_ret == 0 ? 0 : DB_RUNRECOVERY;
00271 }
00272
00273
00274 if (LOGGING_ON(dbenv) &&
00275 (t_ret = CDB_log_flush(dbenv, NULL)) != 0 && ret == 0)
00276 ret = t_ret;
00277
00278
00279 if (tmgrp->mutexp != NULL)
00280 CDB___db_mutex_free(dbenv, &tmgrp->reginfo, tmgrp->mutexp);
00281
00282
00283 if ((t_ret = CDB___db_r_detach(dbenv, &tmgrp->reginfo, 0)) != 0 && ret == 0)
00284 ret = t_ret;
00285
00286 CDB___os_free(tmgrp, sizeof(*tmgrp));
00287
00288 dbenv->tx_handle = NULL;
00289 return (ret);
00290 }
00291
00292 int
00293 CDB_txn_stat(dbenv, statp, db_malloc)
00294 DB_ENV *dbenv;
00295 DB_TXN_STAT **statp;
00296 void *(*db_malloc) __P((size_t));
00297 {
00298 DB_TXNMGR *mgr;
00299 DB_TXNREGION *region;
00300 DB_TXN_STAT *stats;
00301 TXN_DETAIL *txnp;
00302 size_t nbytes;
00303 u_int32_t nactive, ndx;
00304 int ret, slop;
00305
00306 #ifdef HAVE_RPC
00307 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00308 return (__dbcl_txn_stat(dbenv, statp, db_malloc));
00309 #endif
00310
00311 PANIC_CHECK(dbenv);
00312 ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, DB_INIT_TXN);
00313
00314 *statp = NULL;
00315
00316 slop = 200;
00317 mgr = dbenv->tx_handle;
00318 region = mgr->reginfo.primary;
00319
00320 retry: R_LOCK(dbenv, &mgr->reginfo);
00321 nactive = region->nactive;
00322 R_UNLOCK(dbenv, &mgr->reginfo);
00323
00324
00325
00326
00327
00328 nbytes = sizeof(DB_TXN_STAT) + sizeof(DB_TXN_ACTIVE) * (nactive + slop);
00329 if ((ret = CDB___os_malloc(dbenv, nbytes, db_malloc, &stats)) != 0)
00330 return (ret);
00331
00332 R_LOCK(dbenv, &mgr->reginfo);
00333 stats->st_last_txnid = region->last_txnid;
00334 stats->st_last_ckp = region->last_ckp;
00335 stats->st_maxtxns = region->maxtxns;
00336 stats->st_naborts = region->naborts;
00337 stats->st_nbegins = region->nbegins;
00338 stats->st_ncommits = region->ncommits;
00339 stats->st_pending_ckp = region->pending_ckp;
00340 stats->st_time_ckp = region->time_ckp;
00341 stats->st_nactive = region->nactive;
00342 if (stats->st_nactive > nactive + 200) {
00343 R_UNLOCK(dbenv, &mgr->reginfo);
00344 slop *= 2;
00345 goto retry;
00346 }
00347 stats->st_maxnactive = region->maxnactive;
00348 stats->st_txnarray = (DB_TXN_ACTIVE *)&stats[1];
00349
00350 ndx = 0;
00351 for (txnp = SH_TAILQ_FIRST(®ion->active_txn, __txn_detail);
00352 txnp != NULL;
00353 txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) {
00354 stats->st_txnarray[ndx].txnid = txnp->txnid;
00355 if (txnp->parent == INVALID_ROFF)
00356 stats->st_txnarray[ndx].parentid = TXN_INVALID_ID;
00357 else
00358 stats->st_txnarray[ndx].parentid =
00359 ((TXN_DETAIL *)R_ADDR(&mgr->reginfo,
00360 txnp->parent))->txnid;
00361 stats->st_txnarray[ndx].lsn = txnp->begin_lsn;
00362 ndx++;
00363
00364 if (ndx >= stats->st_nactive)
00365 break;
00366 }
00367
00368 stats->st_region_wait = mgr->reginfo.rp->mutex.mutex_set_wait;
00369 stats->st_region_nowait = mgr->reginfo.rp->mutex.mutex_set_nowait;
00370 stats->st_regsize = mgr->reginfo.rp->size;
00371
00372 R_UNLOCK(dbenv, &mgr->reginfo);
00373
00374 *statp = stats;
00375 return (0);
00376 }