00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <sys/types.h>
00011
00012 #include <errno.h>
00013 #include <iostream>
00014 #include <stdlib.h>
00015 #include <string.h>
00016
00017 #include <db_cxx.h>
00018
00019 using std::cin;
00020 using std::cout;
00021 using std::cerr;
00022
00023 const char *progname = "LockExample";
00024
00025
00026
00027
00028 class LockExample : public DbEnv
00029 {
00030 public:
00031 void run();
00032 int error_code() { return (ecode); }
00033
00034 LockExample(const char *home, u_int32_t maxlocks, int do_unlink);
00035
00036 private:
00037 static const char FileName[];
00038 int ecode;
00039
00040
00041 LockExample(const LockExample &);
00042 void operator = (const LockExample &);
00043 };
00044
00045 static int usage();
00046
00047 int
00048 main(int argc, char *argv[])
00049 {
00050 const char *home;
00051 int do_unlink;
00052 u_int32_t maxlocks;
00053 int i;
00054
00055 home = "TESTDIR";
00056 maxlocks = 0;
00057 do_unlink = 0;
00058 for (int argnum = 1; argnum < argc; ++argnum) {
00059 if (strcmp(argv[argnum], "-h") == 0) {
00060 if (++argnum >= argc)
00061 return (usage());
00062 home = argv[argnum];
00063 }
00064 else if (strcmp(argv[argnum], "-m") == 0) {
00065 if (++argnum >= argc)
00066 return (usage());
00067 if ((i = atoi(argv[argnum])) <= 0)
00068 return (usage());
00069 maxlocks = (u_int32_t)i;
00070 }
00071 else if (strcmp(argv[argnum], "-u") == 0) {
00072 do_unlink = 1;
00073 }
00074 else {
00075 return (usage());
00076 }
00077 }
00078
00079 try {
00080 int ecode;
00081
00082 if (do_unlink) {
00083
00084
00085 LockExample tmp(home, maxlocks, do_unlink);
00086 if ((ecode = tmp.error_code()) != 0)
00087 return (ecode);
00088 }
00089
00090 LockExample app(home, maxlocks, do_unlink);
00091 if ((ecode = app.error_code()) != 0)
00092 return (ecode);
00093 app.run();
00094 app.close(0);
00095 return (EXIT_SUCCESS);
00096 }
00097 catch (DbException &dbe) {
00098 cerr << "LockExample: " << dbe.what() << "\n";
00099 return (EXIT_FAILURE);
00100 }
00101 }
00102
00103 LockExample::LockExample(const char *home, u_int32_t maxlocks, int do_unlink)
00104 : DbEnv(0)
00105 , ecode(0)
00106 {
00107 int ret;
00108
00109 if (do_unlink) {
00110 if ((ret = remove(home, DB_FORCE)) != 0) {
00111 cerr << progname << ": DbEnv::remove: "
00112 << strerror(errno) << "\n";
00113 ecode = EXIT_FAILURE;
00114 }
00115 }
00116 else {
00117 set_error_stream(&cerr);
00118 set_errpfx("LockExample");
00119 if (maxlocks != 0)
00120 set_lk_max_locks(maxlocks);
00121 open(home, DB_CREATE | DB_INIT_LOCK, 0);
00122 }
00123 }
00124
00125 void LockExample::run()
00126 {
00127 long held;
00128 size_t len;
00129 u_int32_t locker;
00130 int did_get, ret;
00131 DbLock *locks = 0;
00132 int lockcount = 0;
00133 int lockid = 0;
00134 char objbuf[1024];
00135
00136
00137
00138
00139 lock_id(&locker);
00140 for (held = 0;;) {
00141 cout << "Operation get/release [get]> ";
00142 cout.flush();
00143
00144 char opbuf[16];
00145 cin.getline(opbuf, sizeof(opbuf));
00146 if (cin.eof())
00147 break;
00148 if ((len = strlen(opbuf)) <= 1 || strcmp(opbuf, "get") == 0) {
00149
00150 cout << "input object (text string) to lock> ";
00151 cout.flush();
00152 cin.getline(objbuf, sizeof(objbuf));
00153 if (cin.eof())
00154 break;
00155 if ((len = strlen(objbuf)) <= 0)
00156 continue;
00157
00158 char lockbuf[16];
00159 do {
00160 cout << "lock type read/write [read]> ";
00161 cout.flush();
00162 cin.getline(lockbuf, sizeof(lockbuf));
00163 if (cin.eof())
00164 break;
00165 len = strlen(lockbuf);
00166 } while (len >= 1 &&
00167 strcmp(lockbuf, "read") != 0 &&
00168 strcmp(lockbuf, "write") != 0);
00169
00170 db_lockmode_t lock_type;
00171 if (len <= 1 || strcmp(lockbuf, "read") == 0)
00172 lock_type = DB_LOCK_READ;
00173 else
00174 lock_type = DB_LOCK_WRITE;
00175
00176 Dbt dbt(objbuf, (u_int32_t)strlen(objbuf));
00177
00178 DbLock lock;
00179 ret = lock_get(locker, DB_LOCK_NOWAIT, &dbt,
00180 lock_type, &lock);
00181 did_get = 1;
00182 lockid = lockcount++;
00183 if (locks == NULL) {
00184 locks = new DbLock[1];
00185 }
00186 else {
00187 DbLock *newlocks = new DbLock[lockcount];
00188 for (int lockno = 0;
00189 lockno < lockid; lockno++) {
00190 newlocks[lockno] = locks[lockno];
00191 }
00192 delete locks;
00193 locks = newlocks;
00194 }
00195 locks[lockid] = lock;
00196 } else {
00197
00198 do {
00199 cout << "input lock to release> ";
00200 cout.flush();
00201 cin.getline(objbuf, sizeof(objbuf));
00202 if (cin.eof())
00203 break;
00204 } while ((len = strlen(objbuf)) <= 0);
00205 lockid = strtol(objbuf, NULL, 16);
00206 if (lockid < 0 || lockid >= lockcount) {
00207 cout << "Lock #" << lockid << " out of range\n";
00208 continue;
00209 }
00210 DbLock lock = locks[lockid];
00211 ret = lock_put(&lock);
00212 did_get = 0;
00213 }
00214
00215 switch (ret) {
00216 case 0:
00217 cout << "Lock #" << lockid << " "
00218 << (did_get ? "granted" : "released")
00219 << "\n";
00220 held += did_get ? 1 : -1;
00221 break;
00222 case DB_LOCK_NOTGRANTED:
00223 cout << "Lock not granted\n";
00224 break;
00225 case DB_LOCK_DEADLOCK:
00226 cerr << "LockExample: lock_"
00227 << (did_get ? "get" : "put")
00228 << ": " << "returned DEADLOCK";
00229 break;
00230 default:
00231 cerr << "LockExample: lock_get: %s",
00232 strerror(errno);
00233 }
00234 }
00235 cout << "\n";
00236 cout << "Closing lock region " << held << " locks held\n";
00237 if (locks != 0)
00238 delete locks;
00239 }
00240
00241 static int
00242 usage()
00243 {
00244 cerr << "usage: LockExample [-u] [-h home] [-m maxlocks]\n";
00245 return (EXIT_FAILURE);
00246 }