/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1997,2008 Oracle. All rights reserved. * * $Id: LockExample.cpp,v 12.6 2008/01/08 20:58:26 bostic Exp $ */ #include #include #include #include #include #include using std::cin; using std::cout; using std::cerr; const char *progname = "LockExample"; // Program name. // // An example of a program using DBLock and related classes. // class LockExample : public DbEnv { public: void run(); int error_code() { return (ecode); } LockExample(const char *home, u_int32_t maxlocks, int do_unlink); private: static const char FileName[]; int ecode; // no need for copy and assignment LockExample(const LockExample &); void operator = (const LockExample &); }; static int usage(); // forward int main(int argc, char *argv[]) { const char *home; int do_unlink; u_int32_t maxlocks; int i; home = "TESTDIR"; maxlocks = 0; do_unlink = 0; for (int argnum = 1; argnum < argc; ++argnum) { if (strcmp(argv[argnum], "-h") == 0) { if (++argnum >= argc) return (usage()); home = argv[argnum]; } else if (strcmp(argv[argnum], "-m") == 0) { if (++argnum >= argc) return (usage()); if ((i = atoi(argv[argnum])) <= 0) return (usage()); maxlocks = (u_int32_t)i; /* XXX: possible overflow. */ } else if (strcmp(argv[argnum], "-u") == 0) { do_unlink = 1; } else { return (usage()); } } try { int ecode; if (do_unlink) { // Create an environment that immediately // removes all files. LockExample tmp(home, maxlocks, do_unlink); if ((ecode = tmp.error_code()) != 0) return (ecode); } LockExample app(home, maxlocks, do_unlink); if ((ecode = app.error_code()) != 0) return (ecode); app.run(); app.close(0); return (EXIT_SUCCESS); } catch (DbException &dbe) { cerr << "LockExample: " << dbe.what() << "\n"; return (EXIT_FAILURE); } } LockExample::LockExample(const char *home, u_int32_t maxlocks, int do_unlink) : DbEnv(0) , ecode(0) { int ret; if (do_unlink) { if ((ret = remove(home, DB_FORCE)) != 0) { cerr << progname << ": DbEnv::remove: " << strerror(errno) << "\n"; ecode = EXIT_FAILURE; } } else { set_error_stream(&cerr); set_errpfx("LockExample"); if (maxlocks != 0) set_lk_max_locks(maxlocks); open(home, DB_CREATE | DB_INIT_LOCK, 0); } } void LockExample::run() { long held; size_t len; u_int32_t locker; int did_get, ret; DbLock *locks = 0; int lockcount = 0; int lockid = 0; char objbuf[1024]; // // Accept lock requests. // lock_id(&locker); for (held = 0;;) { cout << "Operation get/release [get]> "; cout.flush(); char opbuf[16]; cin.getline(opbuf, sizeof(opbuf)); if (cin.eof()) break; if ((len = strlen(opbuf)) <= 1 || strcmp(opbuf, "get") == 0) { // Acquire a lock. cout << "input object (text string) to lock> "; cout.flush(); cin.getline(objbuf, sizeof(objbuf)); if (cin.eof()) break; if ((len = strlen(objbuf)) <= 0) continue; char lockbuf[16]; do { cout << "lock type read/write [read]> "; cout.flush(); cin.getline(lockbuf, sizeof(lockbuf)); if (cin.eof()) break; len = strlen(lockbuf); } while (len >= 1 && strcmp(lockbuf, "read") != 0 && strcmp(lockbuf, "write") != 0); db_lockmode_t lock_type; if (len <= 1 || strcmp(lockbuf, "read") == 0) lock_type = DB_LOCK_READ; else lock_type = DB_LOCK_WRITE; Dbt dbt(objbuf, (u_int32_t)strlen(objbuf)); DbLock lock; ret = lock_get(locker, DB_LOCK_NOWAIT, &dbt, lock_type, &lock); did_get = 1; lockid = lockcount++; if (locks == NULL) { locks = new DbLock[1]; } else { DbLock *newlocks = new DbLock[lockcount]; for (int lockno = 0; lockno < lockid; lockno++) { newlocks[lockno] = locks[lockno]; } delete locks; locks = newlocks; } locks[lockid] = lock; } else { // Release a lock. do { cout << "input lock to release> "; cout.flush(); cin.getline(objbuf, sizeof(objbuf)); if (cin.eof()) break; } while ((len = strlen(objbuf)) <= 0); lockid = strtol(objbuf, NULL, 16); if (lockid < 0 || lockid >= lockcount) { cout << "Lock #" << lockid << " out of range\n"; continue; } DbLock lock = locks[lockid]; ret = lock_put(&lock); did_get = 0; } switch (ret) { case 0: cout << "Lock #" << lockid << " " << (did_get ? "granted" : "released") << "\n"; held += did_get ? 1 : -1; break; case DB_LOCK_NOTGRANTED: cout << "Lock not granted\n"; break; case DB_LOCK_DEADLOCK: cerr << "LockExample: lock_" << (did_get ? "get" : "put") << ": " << "returned DEADLOCK"; break; default: cerr << "LockExample: lock_get: %s", strerror(errno); } } cout << "\n"; cout << "Closing lock region " << held << " locks held\n"; if (locks != 0) delete locks; } static int usage() { cerr << "usage: LockExample [-u] [-h home] [-m maxlocks]\n"; return (EXIT_FAILURE); }