mirror of
https://github.com/berkeleydb/libdb.git
synced 2024-11-16 17:16:25 +00:00
245 lines
5 KiB
C++
245 lines
5 KiB
C++
/*-
|
|
* See the file LICENSE for redistribution information.
|
|
*
|
|
* Copyright (c) 1997, 2011 Oracle and/or its affiliates. All rights reserved.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <errno.h>
|
|
#include <iostream>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <db_cxx.h>
|
|
|
|
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);
|
|
}
|