eyedbsmtool.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 #include <eyedbconfig.h>
00025 
00026 #include <stdlib.h>
00027 #include <stdarg.h>
00028 #include <fcntl.h>
00029 #include <string.h>
00030 #include <signal.h>
00031 #include <unistd.h>
00032 #include <errno.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <sys/mman.h>
00036 #include <pthread.h>
00037 
00038 #include <eyedblib/machtypes.h>
00039 #include <eyedblib/filelib.h>
00040 #include <eyedblib/butils.h>
00041 #include <transaction.h>
00042 #include <eyedbsm_p.h>
00043 #include <hashtable.h>
00044 #include <lock.h>
00045 #include <eyedblib/iassert.h>
00046 #include <kern.h>
00047 #include <kern_p.h>
00048 
00049 using namespace eyedbsm;
00050 
00051 #define PROG "eyedbsmtool"
00052 
00053 static const TransactionParams params_X = {
00054   TransactionOn,
00055   DatabaseW,
00056   RecoveryFull,
00057   0,
00058   0,
00059   1
00060 };
00061 
00062 #define sm_CHECK(S, MSG) (statusPrint(S, MSG) ? 1 : 0)
00063 
00064 #define BEGIN(s) \
00065    s = transactionBegin(dbh, (const TransactionParams *)0); \
00066    if (s) return sm_CHECK(s, "transaction begin")
00067 
00068 #define BEGIN_X(s) \
00069    s = transactionBegin(dbh, &params_X); \
00070    if (s) {if (s->err == LOCK_TIMEOUT) fprintf(stderr, "cannot acquire exclusive access on database %s\n", argv[0]); return 1; return sm_CHECK(s, "transaction begin"); }
00071 
00072 #define END(s, msg) \
00073    if (getenv("_ABORT_") || s) transactionAbort(dbh); \
00074    else transactionCommit(dbh); \
00075    return sm_CHECK(s, msg)
00076 
00077 #define OPEN(DBFILE, MODE) \
00078   if (sm_CHECK(dbOpen(DBFILE, MODE, 0, 0, 0, &dbh), \
00079        "database open")) \
00080     return 1
00081 
00082 #define sm_OPEN(DBFILE, MODE) \
00083   if (sm_CHECK(ESM_dbOpen(DBFILE, MODE, 0, 0, 0, 0, 0, 0, &sm_dbh), \
00084        "database open")) \
00085     return 1; \
00086   DbHeader _dbh_(DBSADDR(sm_dbh)); \
00087   sm_h = &_dbh_
00088 
00089 #define sm_SHMH_INIT(DBFILE, WRITE) \
00090   if (shmh_init(DBFILE, WRITE)) { \
00091      fprintf(stderr,"cannot open database file '%s'\n", DBFILE); \
00092      return 1; \
00093    }
00094 
00095 #define sm_XL(x) (((x) == LockX) ? "X" : ((x) == LockS ? "S" : "SX"))
00096 #define sm_LOCK()   sm_locked = 1; MUTEX_LOCK_VOID(sm_mutex, MAXCLS)
00097 #define sm_UNLOCK() MUTEX_UNLOCK(sm_mutex, MAXCLS); sm_locked = 0
00098 
00099 static DbHandle *sm_dbh;
00100 static DbHandle *dbh;
00101 static DbShmHeader *sm_shmh;
00102 static DbHeader *sm_h;
00103 static XMHandle *sm_xmh;
00104 static int sm_fdshm;
00105 static int unsigned sm_shmsize;
00106 static const char *sm_shmfile;
00107 static Mutex *sm_mutex;
00108 static int sm_locked;
00109 
00110 static unsigned int
00111 shmsize_get(int shmfd)
00112 {
00113   struct stat stat;
00114 
00115   if (fstat(shmfd, &stat) < 0)
00116     return 0;
00117 
00118   return stat.st_size;
00119 }
00120 
00121 static int
00122 shmh_init(const char *dbfile, Boolean write)
00123 {
00124   int fddb;
00125   caddr_t shm_addr;
00126   Status status;
00127 
00128   if ((fddb = open(dbfile, write ? O_RDWR : O_RDONLY)) < 0)
00129     return 1;
00130 
00131   close(fddb);
00132 
00133   sm_shmfile = shmfileGet(dbfile);
00134 
00135   if ((sm_fdshm = open(shmfileGet(dbfile), write ? O_RDWR : O_RDONLY)) < 0)
00136     return 1;
00137 
00138   sm_shmsize = shmsize_get(sm_fdshm);
00139 
00140   shm_addr = (caddr_t)mmap(0, sm_shmsize, PROT_READ|(write ? PROT_WRITE : 0),
00141                            MAP_SHARED, sm_fdshm, 0);
00142 
00143   if (shm_addr == MAP_FAILED)
00144     {
00145       fprintf(stderr, PROG ": cannot map file '%s' for %s.\n", sm_shmfile,
00146               (write ? "reading" : "writing"));
00147       return 1;
00148     }
00149 
00150   sm_shmh = (DbShmHeader *)shm_addr;
00151   sm_xmh = XMOpen(shm_addr + SHM_HEADSIZE, 0);
00152   //sm_mutex = &sm_shmh->mtx.mp[TRS];
00153 
00154   return 0;
00155 }
00156 
00157 #define M_DATABASE    0x01000
00158 #define M_DATAFILE    0x02000
00159 #define M_DATASPACE   0x04000
00160 #define M_SHMEM       0x08000
00161 #define M_MUTEX       0x10000
00162 #define M_TRANSACTION 0x20000
00163 #define M_OID         0x40000
00164 
00165 enum mAction {
00166   mDatabaseCreate = 1,
00167   mDatabaseDelete,
00168   mDatabaseMove,
00169   mDatabaseCopy,
00170   mDatabaseSetobjmax,
00171   mDatabaseDisplay,
00172   mDatafileCreate,
00173   mDatafileMove,
00174   mDatafileResize,
00175   mDatafileDelete,
00176   mDatafileDefragment,
00177   mDatafileDisplay,
00178   mDatafileRename,
00179   mDataspaceCreate,
00180   mDataspaceUpdate,
00181   mDataspaceDelete,
00182   mDataspaceRename,
00183   mDataspaceDisplay,
00184   mDataspaceSetDefault,
00185   mDataspaceGetDefault,
00186   mDataspaceGetCurDat,
00187   mDataspaceSetCurDat,
00188   mShmemResize,
00189   mShmemDspmap,
00190   mShmemDspsize,
00191   mShmemCheck,
00192   mShmemCleanup,
00193   mMutexUnlock,
00194   mMutexReset,
00195   mMutexDisplay,
00196   mTransactionDisplay,
00197   mTransactionDspoidlock,
00198   mTransactionDsphead,
00199   mTransactionAbrtInact,
00200   mOidMoveDat,
00201   mOidMoveDsp,
00202   mOidDspList,
00203   mOidDspCount,
00204   mOidGetCurLastNx,
00205   mOidSetLastNx,
00206   mOidSetCurNx,
00207   mOidSyncCurLastNx,
00208   mOidDspLoca,
00209   mOidDspLocaStats
00210 };
00211 
00212 static const char *prog;
00213 
00214 static int
00215 usage(unsigned int mode = 0)
00216 {
00217   if (!mode || mode == mDatabaseCreate || (mode & M_DATABASE))
00218     fprintf(stderr, "%s database create DBFILE DBID OBJMAX {DATAFILE NAME MAXSIZE_KB linkmap|SIZESLOT phy|log}...\n", prog);
00219 
00220   if (!mode || mode == mDatabaseDelete || (mode & M_DATABASE))
00221     fprintf(stderr, "%s database delete DBFILE\n", prog);
00222 
00223   if (!mode || mode == mDatabaseMove || (mode & M_DATABASE))
00224     fprintf(stderr, "%s database move DBFILE NEW_DBFILE NEW_DATAFILES...\n", prog);
00225 
00226   if (!mode || mode == mDatabaseCopy || (mode & M_DATABASE))
00227     fprintf(stderr, "%s database copy DBFILE NEW_DBFILE NEW_DATAFILES...\n", prog);
00228 
00229   if (!mode || mode == mDatabaseSetobjmax || (mode & M_DATABASE))
00230     fprintf(stderr, "%s database set:objmax DBFILE NEW_OBJMAX\n", prog);
00231 
00232   if (!mode || mode == mDatabaseDisplay || (mode & M_DATABASE))
00233     fprintf(stderr, "%s database display DBFILE\n", prog);
00234  
00235   if (!mode)
00236     fprintf(stderr, "\n");
00237 
00238   if (!mode || mode == mDatafileCreate || (mode & M_DATAFILE))
00239     fprintf(stderr, "%s datafile create DBFILE FILE NAME SIZE_KB linkmap|SIZESLOT log|phy\n", prog);
00240 
00241   if (!mode || mode == mDatafileMove || (mode & M_DATAFILE))
00242     fprintf(stderr, "%s datafile move DBFILE DATAFILE NEW_DATAFILE\n", prog);
00243 
00244   if (!mode || mode == mDatafileResize || (mode & M_DATAFILE))
00245     fprintf(stderr, "%s datafile resize DBFILE DATAFILE NEW_SIZE_KB\n", prog);
00246 
00247   if (!mode || mode == mDatafileDelete || (mode & M_DATAFILE))
00248     fprintf(stderr, "%s datafile delete DBFILE DATAFILE\n", prog);
00249 
00250   if (!mode || mode == mDatafileDefragment || (mode & M_DATAFILE))
00251     fprintf(stderr, "%s datafile defragment DBFILE DATAFILE\n", prog);
00252 
00253   if (!mode || mode == mDatafileDisplay || (mode & M_DATAFILE))
00254     fprintf(stderr, "%s datafile display DBFILE [DATAFILES...]\n", prog);
00255 
00256   if (!mode || mode == mDatafileRename || (mode & M_DATAFILE))
00257     fprintf(stderr, "%s datafile rename DBFILE DATAFILE NAME\n", prog);
00258 
00259   if (!mode)
00260     fprintf(stderr, "\n");
00261 
00262   if (!mode || mode == mDataspaceCreate || (mode & M_DATASPACE))
00263     fprintf(stderr, "%s dataspace create DBFILE DATASPACE DATAFILES...\n", prog);
00264 
00265   if (!mode || mode == mDataspaceUpdate || (mode & M_DATASPACE))
00266     fprintf(stderr, "%s dataspace update DBFILE DATASPACE DATAFILES...\n", prog);
00267 
00268   if (!mode || mode == mDataspaceDelete || (mode & M_DATASPACE))
00269     fprintf(stderr, "%s dataspace delete DBFILE DATASPACE\n", prog);
00270 
00271   if (!mode || mode == mDataspaceRename || (mode & M_DATASPACE))
00272     fprintf(stderr, "%s dataspace rename DBFILE DATASPACE NEW_DATASPACE\n", prog);
00273 
00274   if (!mode || mode == mDataspaceDisplay || (mode & M_DATASPACE))
00275     fprintf(stderr, "%s dataspace display DBFILE [DATASPACES...]\n", prog);
00276 
00277   if (!mode || mode == mDataspaceSetDefault || (mode & M_DATASPACE))
00278     fprintf(stderr, "%s dataspace set:default DBFILE DATASPACE\n", prog);
00279 
00280   if (!mode || mode == mDataspaceGetDefault || (mode & M_DATASPACE))
00281     fprintf(stderr, "%s dataspace get:default DBFILE\n", prog);
00282 
00283   if (!mode || mode == mDataspaceSetCurDat || (mode & M_DATASPACE))
00284     fprintf(stderr, "%s dataspace set:curdat DBFILE DATASPACE CURDAT\n", prog);
00285 
00286   if (!mode || mode == mDataspaceGetCurDat || (mode & M_DATASPACE))
00287     fprintf(stderr, "%s dataspace get:curdat DBFILE DATASPACE\n", prog);
00288 
00289   if (!mode)
00290     fprintf(stderr, "\n");
00291 
00292   if (!mode || mode == mShmemResize || (mode & M_SHMEM))
00293     fprintf(stderr, "%s shmem resize DBFILE NEW_SIZE_KB\n", prog);
00294 
00295   if (!mode || mode == mShmemDspmap || (mode & M_SHMEM))
00296     fprintf(stderr, "%s shmem display:map DBFILE\n", prog);
00297 
00298   if (!mode || mode == mShmemDspsize || (mode & M_SHMEM))
00299     fprintf(stderr, "%s shmem display:size DBFILE\n", prog);
00300 
00301   if (!mode || mode == mShmemCheck || (mode & M_SHMEM))
00302     fprintf(stderr, "%s shmem check DBFILE\n", prog);
00303 
00304   if (!mode || mode == mShmemCleanup || (mode & M_SHMEM))
00305     fprintf(stderr, "%s shmem cleanup DBFILE\n", prog);
00306 
00307   if (!mode)
00308     fprintf(stderr, "\n");
00309 
00310   if (!mode || mode == mMutexUnlock || (mode & M_MUTEX))
00311     fprintf(stderr, "%s mutex unlock DBFILE\n", prog);
00312 
00313   if (!mode || mode == mMutexReset || (mode & M_MUTEX))
00314     fprintf(stderr, "%s mutex reset DBFILE\n", prog);
00315 
00316   if (!mode || mode == mMutexDisplay || (mode & M_MUTEX))
00317     fprintf(stderr, "%s mutex display DBFILE\n", prog);
00318 
00319   if (!mode)
00320     fprintf(stderr, "\n");
00321 
00322   if (!mode || mode == mTransactionDisplay || (mode & M_TRANSACTION))
00323     fprintf(stderr, "%s transaction display [SERVER_PID] DBFILE\n", prog);
00324 
00325   if (!mode || mode == mTransactionDspoidlock || (mode & M_TRANSACTION))
00326     fprintf(stderr, "%s transaction display:lockedoids DBFILE\n", prog);
00327 
00328   if (!mode || mode == mTransactionDsphead || (mode & M_TRANSACTION))
00329     fprintf(stderr, "%s transaction display:header [SERVER_PID] DBFILE\n", prog);
00330 
00331   if (!mode || mode == mTransactionAbrtInact || (mode & M_TRANSACTION))
00332     fprintf(stderr, "%s transaction abort:inactive DBFILE\n", prog);
00333 
00334   if (!mode)
00335     fprintf(stderr, "\n");
00336 
00337   if (!mode || mode == mOidMoveDat || (mode & M_OID))
00338     fprintf(stderr, "%s oid move:datafile DBFILE FROM_DATAFILE TO_DATAFILE\n", prog);
00339 
00340   if (!mode || mode == mOidMoveDsp || (mode & M_OID))
00341     fprintf(stderr, "%s oid move:dataspace DBFILE FROM_DATASPACE TO_DATASPACE\n", prog);
00342 
00343   if (!mode || mode == mOidDspList || (mode & M_OID))
00344     fprintf(stderr, "%s oid display:list DBFILE [DATAFILE]\n", prog);
00345 
00346   if (!mode || mode == mOidDspCount || (mode & M_OID))
00347     fprintf(stderr, "%s oid display:count DBFILE [DATAFILE]\n", prog);
00348 
00349   if (!mode || mode == mOidGetCurLastNx || (mode & M_OID))
00350     fprintf(stderr, "%s oid get:curlastnx DBFILE\n", prog);
00351 
00352   if (!mode || mode == mOidSetLastNx || (mode & M_OID))
00353     fprintf(stderr, "%s oid set:lastnx DBFILE LASTNX\n", prog);
00354 
00355   if (!mode || mode == mOidSetCurNx || (mode & M_OID))
00356     fprintf(stderr, "%s oid set:curnx DBFILE CURNX\n", prog);
00357 
00358   if (!mode || mode == mOidSyncCurLastNx || (mode & M_OID))
00359     fprintf(stderr, "%s oid sync:curlastnx DBFILE\n", prog);
00360 
00361   if (!mode || mode == mOidDspLoca || (mode & M_OID))
00362     fprintf(stderr, "%s oid display:loca DBFILE [DATAFILE]\n", prog);
00363 
00364   if (!mode || mode == mOidDspLoca || (mode & M_OID))
00365     fprintf(stderr, "%s oid display:locastats DBFILE [DATAFILE]\n", prog);
00366 
00367   return 1;
00368 }
00369 
00370 static int
00371 databacreate_realize(int argc, char *argv[])
00372 {
00373   if (argc < 4 || ((argc - 3) % 5))
00374     return usage(mDatabaseCreate);
00375 
00376   DbCreateDescription dbc;
00377 
00378   char *dbfile = argv[0];
00379   dbc.ndat = 0;
00380   dbc.dbid = atoi(argv[1]);
00381   dbc.nbobjs = atoi(argv[2]);
00382 
00383   for (int i = 3; i < argc; i += 5)
00384     {
00385       strcpy(dbc.dat[dbc.ndat].file, argv[i]);
00386       strcpy(dbc.dat[dbc.ndat].name, argv[i+1]);
00387       dbc.dat[dbc.ndat].maxsize = atoi(argv[i+2]);
00388       if (!strcmp(argv[i+3], "linkmap"))
00389         dbc.dat[dbc.ndat].mtype = LinkmapType;
00390       else
00391         {
00392           dbc.dat[dbc.ndat].mtype = BitmapType;
00393           dbc.dat[dbc.ndat].sizeslot = atoi(argv[i+3]);
00394         }
00395       if (!strcmp(argv[i+4], "log"))
00396         dbc.dat[dbc.ndat].dtype = LogicalOidType;
00397       else if (!strcmp(argv[i+4], "phy"))
00398         dbc.dat[dbc.ndat].dtype = PhysicalOidType;
00399       else
00400         return usage(mDatabaseCreate);
00401       dbc.ndat++;
00402     }     
00403   
00404   return sm_CHECK(dbCreate(dbfile, 205015, &dbc, 0, 0), "database create");
00405 }
00406 
00407 static int
00408 databadelete_realize(int argc, char *argv[])
00409 {
00410   if (argc != 1)
00411     return usage(mDatabaseDelete);
00412   return sm_CHECK(dbDelete(argv[0]), "database delete");
00413 }
00414 
00415 static int
00416 databamove_copy_realize(int argc, char *argv[], Boolean move)
00417 {
00418   if (argc < 3)
00419     return usage(move ? mDatabaseMove : mDatabaseCopy);
00420 
00421   DbMoveDescription dbc;
00422   DbCreateDescription *dcr = &dbc.dcr;
00423 
00424   char *dbfile = argv[0];
00425   strcpy(dbc.dbfile, argv[1]);
00426   dcr->ndat = 0;
00427 
00428   for (int i = 2; i < argc; i++)
00429     {
00430       strcpy(dcr->dat[dcr->ndat].file, argv[i]);
00431       dcr->ndat++;
00432     }     
00433   
00434   return sm_CHECK((move ? dbMove(dbfile, &dbc) : dbCopy(dbfile, &dbc)),
00435                (move ? "database move" : "database copy"));
00436 }
00437 
00438 static int
00439 databasetobjmax_realize(int argc, char *argv[])
00440 {
00441   if (argc != 2)
00442     return usage(mDatabaseSetobjmax);
00443 
00444   sm_OPEN(argv[0], VOLRW);
00445   return sm_CHECK(objectNumberSet(sm_dbh, atoi(argv[1])), "database setobjmax");
00446 }
00447 
00448 static int
00449 sm_get_refcount()
00450 {
00451   return sm_shmh->trs_hdr.tr_cnt;
00452 }
00453 
00454 static int
00455 shmem_check_realize(int argc, char *argv[])
00456 {
00457   if (argc != 1)
00458     return usage(mShmemCheck);
00459 
00460   sm_SHMH_INIT(argv[0], True);
00461 
00462   if (!mutexLock(sm_mutex, 0))
00463     {
00464       printf("Database shmem %s is in a coherent state\n", argv[0]);
00465       mutexUnlock(sm_mutex, 0);
00466       return 0;
00467     }
00468     
00469   printf("Database shmem %s is in an incoherent state. You must perform:\n"
00470          "eyedbsmtool shmem cleanup %s\n", argv[0], argv[0]);
00471   return 1;
00472 }
00473 
00474 static int
00475 shmem_cleanup_realize(int argc, char *argv[])
00476 {
00477   if (argc != 1)
00478     return usage(mShmemCleanup);
00479 
00480   int cnt = 0;
00481 
00482   printf("\nDo you really want to cleanup the shmem for the "
00483           "database '%s'? ", argv[0]);
00484 
00485   for (;;)
00486     {
00487       char s[128];
00488       fgets(s, sizeof s, stdin);
00489       s[strlen(s)-1] = 0;
00490       if (!strcasecmp(s, "y") || !strcasecmp(s, "yes"))
00491         {
00492           Status status = dbCleanup(argv[0]);
00493           if (status){
00494             statusPrint(status, "");
00495             return 1;
00496           }
00497           break;
00498         }
00499       else if (!strcasecmp(s, "n") || !strcasecmp(s, "no"))
00500         {
00501           printf("\nOperation aborted by user request.\n");
00502           break;
00503         }
00504       else
00505         printf("Please, answer `y[es]' or `n[o]'? ");
00506     }
00507 
00508   return 0;
00509 }
00510 
00511 #define OFFSET(T, X) (unsigned long)(&((T *)0)->X)
00512 //#define DSPSIZEOF(T) printf("sizeof " #T ": %d\n", sizeof(T))
00513 //#define DSPOFFSET(T, X) printf("offset of " #T "::" #X ": %d\n", OFFSET(T, X))
00514 #define DSPSIZEOF(T) printf("#define " #T "_SIZE %d\n", sizeof(T))
00515 #define DSPOFFSET(T, X) printf("#define " #T "_" #X "_OFF %d\n", OFFSET(T, X))
00516 
00517 static void
00518 display_structs()
00519 {
00520 #if 0
00521   DSPSIZEOF(DatafileDesc);
00522   DSPSIZEOF(DataspaceDesc);
00523   DSPSIZEOF(DbHeader);
00524   DSPSIZEOF(MapHeader);
00525   DSPSIZEOF(BitmapHeader);
00526   DSPSIZEOF(LinkmapHeader);
00527   DSPSIZEOF(MapStat);
00528 
00529   DSPOFFSET(MapStat, u);
00530 #endif
00531 
00532 #if 0
00533   DSPSIZEOF(MapHeader);
00534   DSPSIZEOF(DatafileDesc);
00535   DSPSIZEOF(DataspaceDesc);
00536   DSPSIZEOF(DbHeader);
00537   DSPSIZEOF(DbRootEntry);
00538   //DSPSIZEOF(DbRootEntries);
00539   printf("\n");
00540 
00541   DSPOFFSET(MapHeader, mtype);
00542   DSPOFFSET(MapHeader, sizeslot);
00543   DSPOFFSET(MapHeader, pow2);
00544   DSPOFFSET(MapHeader, nslots);
00545 
00546   DSPOFFSET(MapHeader, nbobjs);
00547   DSPOFFSET(MapHeader, mstat);
00548   DSPOFFSET(MapHeader, mstat.mtype);
00549 
00550   DSPOFFSET(MapHeader, u.bmh);
00551 
00552   DSPOFFSET(MapHeader, u.bmh.slot_cur);
00553   DSPOFFSET(MapHeader, u.bmh.slot_lastbusy);
00554   DSPOFFSET(MapHeader, u.bmh.retry);
00555 
00556   DSPOFFSET(MapHeader, mstat.u.bmstat);
00557   DSPOFFSET(MapHeader, mstat.u.bmstat.obj_count);
00558   DSPOFFSET(MapHeader, mstat.u.bmstat.busy_slots);
00559   DSPOFFSET(MapHeader, mstat.u.bmstat.busy_size);
00560   DSPOFFSET(MapHeader, mstat.u.bmstat.hole_size);
00561 
00562   DSPOFFSET(MapHeader, mstat.u.lmstat);
00563   DSPOFFSET(MapHeader, mstat.u.lmstat.nfreecells);
00564 
00565   DSPOFFSET(MapHeader, u.lmh);
00566   DSPOFFSET(MapHeader, u.lmh.firstcell);
00567 
00568   printf("\n");
00569 
00570   DSPOFFSET(DatafileDesc, file);
00571   DSPOFFSET(DatafileDesc, name);
00572   DSPOFFSET(DatafileDesc, __maxsize);
00573   DSPOFFSET(DatafileDesc, mp);
00574   DSPOFFSET(DatafileDesc, __lastslot);
00575   DSPOFFSET(DatafileDesc, __dspid);
00576 
00577   printf("\n");
00578 
00579   DSPOFFSET(DataspaceDesc, name);
00580   DSPOFFSET(DataspaceDesc, __cur);
00581   DSPOFFSET(DataspaceDesc, __ndat);
00582   DSPOFFSET(DataspaceDesc, __datid);
00583 
00584   printf("\n");
00585 
00586   DSPOFFSET(DbRootEntry, key);
00587   DSPOFFSET(DbRootEntry, data);
00588 
00589   printf("\n");
00590 
00591   DSPOFFSET(DbHeader, __magic);
00592   DSPOFFSET(DbHeader, __dbid);
00593   DSPOFFSET(DbHeader, state);
00594   DSPOFFSET(DbHeader, __guest_uid);
00595   DSPOFFSET(DbHeader, __prot_uid_oid);
00596   DSPOFFSET(DbHeader, __prot_list_oid);
00597   DSPOFFSET(DbHeader, __prot_lock_oid);
00598   DSPOFFSET(DbHeader, shmfile);
00599   DSPOFFSET(DbHeader, __nbobjs);
00600   DSPOFFSET(DbHeader, __ndat);
00601   DSPOFFSET(DbHeader, dat);
00602   DSPOFFSET(DbHeader, __ndsp);
00603   DSPOFFSET(DbHeader, dsp);
00604   DSPOFFSET(DbHeader, __def_dspid);
00605   DSPOFFSET(DbHeader, vre);
00606   DSPOFFSET(DbHeader, __lastidxbusy);
00607   DSPOFFSET(DbHeader, __curidxbusy);
00608   DSPOFFSET(DbHeader, __lastidxblkalloc);
00609   DSPOFFSET(DbHeader, __lastnsblkalloc);
00610 #endif
00611 
00612 #if 0
00613   DSPSIZEOF(HIdx::_Idx);
00614   DSPOFFSET(HIdx::_Idx, key_count);
00615   DSPOFFSET(HIdx::_Idx, dspid);
00616   DSPOFFSET(HIdx::_Idx, keytype);
00617   DSPOFFSET(HIdx::_Idx, keysz);
00618   DSPOFFSET(HIdx::_Idx, datasz);
00619   
00620   DSPSIZEOF(MutexP);
00621 
00622   DSPOFFSET(MutexP, u.key);
00623   DSPOFFSET(MutexP, xid);
00624   DSPOFFSET(MutexP, wait_cnt);
00625   DSPOFFSET(MutexP, pcond);
00626 
00627   DSPSIZEOF(DbShmHeader);
00628   DSPOFFSET(DbShmHeader, version);
00629   DSPOFFSET(DbShmHeader, xid);
00630   DSPOFFSET(DbShmHeader, hostid);
00631   DSPOFFSET(DbShmHeader, arch);
00632   DSPOFFSET(DbShmHeader, lock);
00633   DSPOFFSET(DbShmHeader, trs_hdr);
00634   DSPOFFSET(DbShmHeader, mtx);
00635   DSPOFFSET(DbShmHeader, stat);
00636 #endif
00637 }
00638 
00639 static int
00640 databadisplay_realize(int argc, char *argv[])
00641 {
00642   if (argc != 1)
00643     return usage(mDatabaseDisplay);
00644 
00645   sm_OPEN(argv[0], VOLREAD);
00646   sm_SHMH_INIT(argv[0], False);
00647 
00648   printf(" Database ID #%d\n", sm_dbh->vd->dbid);
00649   printf(" Version %d\n", x2h_u32(sm_shmh->version));
00650   printf(" Max Object Count %d\n", x2h_u32(sm_h->__nbobjs()));
00651   printf(" Datafile Count %d\n", x2h_u32(sm_h->__ndat()));
00652   printf(" Reference Count %d\n", sm_get_refcount());
00653   if (sm_shmh->hostid || *sm_shmh->hostname)
00654     printf(" Host Owner \"%s\", Host ID %p\n", 
00655             sm_shmh->hostname, x2h_u32(sm_shmh->hostid));
00656   
00657   printf("\n");
00658   printf(" Total Access Number   %d\n", x2h_u32(sm_shmh->stat.total_db_access_cnt));
00659   printf(" Current Access Number %d\n", x2h_u32(sm_shmh->stat.current_db_access_cnt));
00660   printf(" Transaction Started   %d\n", x2h_u32(sm_shmh->stat.tr_begin_cnt));
00661   printf(" Transaction Committed %d\n", x2h_u32(sm_shmh->stat.tr_commit_cnt));
00662   printf(" Transaction Aborted   %d\n", x2h_u32(sm_shmh->stat.tr_abort_cnt));
00663 
00664   return 0;
00665 }
00666 
00667 static int
00668 databarealize(int argc, char *argv[])
00669 {
00670   const char *action = argv[0];
00671   
00672   if (!action)
00673     return usage(M_DATABASE);
00674 
00675   if (!strcmp(action, "create"))
00676     return databacreate_realize(argc-1, &argv[1]);
00677 
00678   if (!strcmp(action, "delete"))
00679     return databadelete_realize(argc-1, &argv[1]);
00680 
00681   if (!strcmp(action, "move"))
00682     return databamove_copy_realize(argc-1, &argv[1], True);
00683 
00684   if (!strcmp(action, "copy"))
00685     return databamove_copy_realize(argc-1, &argv[1], False);
00686 
00687   if (!strcmp(action, "set:objmax"))
00688     return databasetobjmax_realize(argc-1, &argv[1]);
00689 
00690   if (!strcmp(action, "display"))
00691     return databadisplay_realize(argc-1, &argv[1]);
00692 
00693   return usage(M_DATABASE);
00694 }
00695 
00696 static int
00697 datafile_create_realize(int argc, char *argv[])
00698 {
00699   if (argc != 6)
00700     return usage(mDatafileCreate);
00701 
00702   DatType dtype;
00703 
00704   if (!strcmp(argv[5], "log"))
00705     dtype = LogicalOidType;
00706   else if (!strcmp(argv[5], "phy"))
00707     dtype = PhysicalOidType;
00708   else
00709     return usage(mDatafileCreate);
00710     
00711   Status s;
00712   OPEN(argv[0], VOLRW);
00713   BEGIN_X(s);
00714 
00715   MapType mtype;
00716   unsigned int sizeslot;
00717   if (!strcmp(argv[4], "linkmap"))
00718     mtype = LinkmapType;
00719   else
00720     {
00721       mtype = BitmapType;
00722       sizeslot = atoi(argv[4]);
00723     }
00724 
00725   s = datCreate(dbh, argv[1], argv[2], atoi(argv[3]), mtype,
00726                    sizeslot, dtype, 0, 0);
00727   END(s, "datafile create");
00728 }
00729 
00730 static int
00731 datafile_resize_realize(int argc, char *argv[])
00732 {
00733   if (argc != 3)
00734     return usage(mDatafileResize);
00735 
00736   Status s;
00737   OPEN(argv[0], VOLRW);
00738   BEGIN_X(s);
00739   s = datResize(dbh, argv[1], atoi(argv[2]));
00740   END(s, "datafile resize");
00741 }
00742 
00743 static int
00744 datafile_move_realize(int argc, char *argv[])
00745 {
00746   if (argc != 3)
00747     return usage(mDatafileMove);
00748 
00749   Status s;
00750   OPEN(argv[0], VOLRW);
00751   BEGIN_X(s);
00752 
00753   s = datMove(dbh, argv[1], argv[2]);
00754   END(s, "datafile move");
00755 }
00756 
00757 static int
00758 datafile_delete_realize(int argc, char *argv[])
00759 {
00760   if (argc != 2)
00761     return usage(mDatafileDelete);
00762 
00763   Status s;
00764   OPEN(argv[0], VOLRW);
00765   BEGIN_X(s);
00766 
00767   s = datDelete(dbh, argv[1]);
00768   END(s, "datafile delete");
00769 }
00770 
00771 static int
00772 datafile_defragment_realize(int argc, char *argv[])
00773 {
00774   if (argc != 2)
00775     return usage(mDatafileDefragment);
00776 
00777   Status s;
00778   OPEN(argv[0], VOLRW);
00779   BEGIN_X(s);
00780 
00781   s = datDefragment(dbh, argv[1], 0, 0);
00782   END(s, "datafile defragment");
00783 }
00784 
00785 static int
00786 datafile_rename_realize(int argc, char *argv[])
00787 {
00788   if (argc != 3)
00789     return usage(mDatafileRename);
00790 
00791   Status s;
00792   OPEN(argv[0], VOLRW);
00793   BEGIN_X(s);
00794 
00795   s = datRename(dbh, argv[1], argv[2]);
00796   END(s, "datafile rename");
00797 }
00798 
00799 static short
00800 datafile_get(const char *dat)
00801 {
00802   int ndat = x2h_u32(sm_h->__ndat());
00803   for (int i = 0; i < ndat; i++)
00804     if (!strcmp(dat, sm_h->dat(i).file()))
00805       return i;
00806 
00807   return -1;
00808 }
00809 
00810 static void
00811 datafile_display_fragmentation(short datid)
00812 {
00813   DatafileDesc dat = sm_h->dat(datid);
00814   MapHeader *xmp = dat.mp();
00815   x2h_prologue(xmp, mp);
00816   char *mapaddr = sm_dbh->vd->dmp_addr[datid];
00817   char *s, *start, *end;
00818   int nfrags, nbusy, ns;
00819 
00820   start = mapaddr;
00821   end = mapaddr + (mp->u_bmh_slot_lastbusy() / 8);
00822   nfrags = 0;
00823   ns = 0;
00824 
00825   for (s = start; s <= end; s++)
00826     {
00827       char v = *s;
00828       int b;
00829 
00830       for (b = 7; b >= 0; b--, ns++)
00831         {
00832           if (!(v & (1 << b)))
00833             nfrags++;
00834 
00835           if (ns >= mp->u_bmh_slot_lastbusy())
00836             break;
00837         }
00838     }
00839 
00840   if (nfrags > mp->u_bmh_slot_lastbusy())
00841     nfrags = mp->u_bmh_slot_lastbusy();
00842 
00843   printf("   Fragmentation        %d/%d slots [%2.2f%%]\n",
00844          nfrags, mp->u_bmh_slot_lastbusy(),
00845          (mp->u_bmh_slot_lastbusy() ?
00846           (double)(100.*nfrags)/mp->u_bmh_slot_lastbusy() : 0));
00847 }       
00848 
00849 static void
00850 display_size(unsigned long long sz)
00851 {
00852   printf("%lldb", sz);
00853   sz /= ONE_K;
00854   if (sz)
00855     {
00856       printf(", %lldKb", sz);
00857       sz /= ONE_K;
00858       if (sz)
00859         {
00860           printf(", ~%lldMb", sz);
00861           sz /= ONE_K;
00862           if (sz)
00863             printf(", ~%lldGb", sz);
00864         }
00865     }
00866   printf("\n");
00867 }
00868 
00869 static void
00870 datafile_display_info(short datid, DatafileDesc *dfd)
00871 {
00872   MapHeader *xmp = dfd->mp();
00873   x2h_prologue(xmp, mp);
00874   
00875   printf(" Datafile #%d\n", datid);
00876   if (!*dfd->file())
00877     {
00878       printf("   <empty slot>\n");
00879       return;
00880     }
00881 
00882   unsigned long Ksz;
00883   printf("   File                 %s\n", dfd->file());
00884   printf("   Name                 %s\n",
00885          (*dfd->name() ? dfd->name() : "<unnamed>"));
00886   if (getDatType(sm_h, datid) == LogicalOidType)
00887     printf("   Oid Type             Logical\n");
00888   else
00889     printf("   Oid Type             Physical\n");
00890 
00891   short dspid = getDataspace(sm_h, datid);
00892   if (dspid != DefaultDspid)
00893     printf("   Dataspace            %s\n", sm_h->dsp(dspid).name());
00894   printf("   Maximum Size         ");
00895   display_size((unsigned long long)x2h_u32(dfd->__maxsize())*ONE_K);
00896   if (mp->mtype() == BitmapType)
00897     {
00898       printf("   Bitmap Allocator\n");
00899       printf("     Max Slots          %u\n", mp->nslots());
00900       printf("     Slot Size          %u\n\n", mp->sizeslot());
00901     }
00902   else
00903     printf("   Linkmap Allocator\n\n");
00904 
00905   printf("   Object Number        %d\n", mp->mstat_u_bmstat_obj_count());
00906   printf("   Total Object Size    ");
00907   display_size(mp->mstat_u_bmstat_busy_size());
00908       
00909   printf("   Average Object Size  ");
00910   display_size(mp->mstat_u_bmstat_obj_count() ?
00911                mp->mstat_u_bmstat_busy_size()/mp->mstat_u_bmstat_obj_count() : 0);
00912 
00913   printf("\n");
00914   printf("   Busy Slots           %d\n", mp->mstat_u_bmstat_busy_slots());
00915   printf("   Last Busy Slot       %u\n", mp->u_bmh_slot_lastbusy());
00916   printf("   Last Volume Slot     %u\n", x2h_u32(dfd->__lastslot()));
00917   printf("   Busy Slot Size       ");
00918   display_size((unsigned long long)mp->mstat_u_bmstat_busy_slots() * mp->sizeslot());
00919 
00920   printf("   Total File Size      ");
00921   display_size((unsigned long long)mp->u_bmh_slot_lastbusy() * mp->sizeslot());
00922          
00923   printf("   Current Slot Pointer %u\n", mp->u_bmh_slot_cur());
00924   printf("   Defragmentable Size  ");
00925   display_size((unsigned long long)(mp->u_bmh_slot_lastbusy()+1 - mp->mstat_u_bmstat_busy_slots()) * mp->sizeslot());
00926   //datafile_display_fragmentation(datid);
00927   printf("   DMP Up Slot          %u\n", x2h_u32(sm_h->__lastnsblkalloc(datid)*BITS_PER_BYTE));
00928   printf("   DMP Allocated Size   ");
00929   display_size(x2h_u32(sm_h->__lastnsblkalloc(datid)));
00930   printf("   Used                 %2.2f%%\n",
00931          ((double)mp->mstat_u_bmstat_busy_slots()/(double)mp->nslots())*100.);
00932 }
00933 
00934 static int
00935 datafile_display_realize(int argc, char *argv[])
00936 {
00937   if (argc < 1)
00938     return usage(mDatabaseDisplay);
00939 
00940   sm_OPEN(argv[0], VOLREAD);
00941   sm_SHMH_INIT(argv[0], False);
00942 
00943   int datid_cnt = argc-1;
00944   int i;
00945   char **dats;
00946   short *datids;
00947   dats = (datid_cnt ? new char*[datid_cnt] : 0);
00948   datids = (datid_cnt ? new short[datid_cnt] : 0);
00949 
00950   for (i = 0; i < datid_cnt; i++)
00951     dats[i] = argv[i+1];
00952 
00953   if (!datid_cnt) {
00954     unsigned int ndat = x2h_u32(sm_h->__ndat());
00955     printf(" Database %s contains %d Data File%s\n\n", sm_dbh->dbfile, ndat, (ndat > 1 ? "s" : ""));
00956   }
00957 
00958   for (i = 0; i < datid_cnt; i++)
00959     if (sm_CHECK(ESM_datCheck(sm_dbh, dats[i], &datids[i], 0),
00960                  "unknown datafile"))
00961       return 1;
00962 
00963   if (!datid_cnt)
00964     {
00965       unsigned int ndat = x2h_u32(sm_h->__ndat());
00966       for (i = 0; i < ndat; i++)
00967         {
00968           if (i) printf("\n");
00969           DatafileDesc d = sm_h->dat(i);
00970           datafile_display_info(i, &d);
00971         }
00972       return 0;
00973     }
00974 
00975   for (i = 0; i < datid_cnt; i++)
00976     {
00977       if (i) printf("\n");
00978       DatafileDesc d = sm_h->dat(datids[i]);
00979       datafile_display_info(datids[i], &d);
00980     }
00981 
00982   return 0;
00983 }
00984 
00985 static int
00986 datafile_realize(int argc, char *argv[])
00987 {
00988   const char *action = argv[0];
00989   
00990   if (!action)
00991     return usage(M_DATAFILE);
00992 
00993   if (!strcmp(action, "create"))
00994     return datafile_create_realize(argc-1, &argv[1]);
00995 
00996   if (!strcmp(action, "resize"))
00997     return datafile_resize_realize(argc-1, &argv[1]);
00998 
00999   if (!strcmp(action, "move"))
01000     return datafile_move_realize(argc-1, &argv[1]);
01001 
01002   if (!strcmp(action, "delete"))
01003     return datafile_delete_realize(argc-1, &argv[1]);
01004 
01005   if (!strcmp(action, "defragment"))
01006     return datafile_defragment_realize(argc-1, &argv[1]);
01007 
01008   if (!strcmp(action, "display"))
01009     return datafile_display_realize(argc-1, &argv[1]);
01010 
01011   if (!strcmp(action, "rename"))
01012     return datafile_rename_realize(argc-1, &argv[1]);
01013 
01014   return usage(M_DATAFILE);
01015 }
01016 
01017 static int
01018 dataspace_create_realize(int argc, char *argv[])
01019 {
01020   if (argc < 3)
01021     return usage(mDataspaceCreate);
01022 
01023   Status s;
01024   OPEN(argv[0], VOLRW);
01025   BEGIN_X(s);
01026   s = dspCreate(dbh, argv[1], (const char **)&argv[2], argc-2);
01027   END(s, "dataspace create");
01028 }
01029 
01030 static int
01031 dataspace_update_realize(int argc, char *argv[])
01032 {
01033   if (argc < 3)
01034     return usage(mDataspaceUpdate);
01035 
01036   Status s;
01037   OPEN(argv[0], VOLRW);
01038   BEGIN_X(s);
01039 
01040   s = dspUpdate(dbh, argv[1], (const char **)&argv[2], argc-2);
01041   END(s, "dataspace update");
01042 }
01043 
01044 static int
01045 dataspace_delete_realize(int argc, char *argv[])
01046 {
01047   if (argc != 2)
01048     return usage(mDataspaceDelete);
01049 
01050   Status s;
01051   OPEN(argv[0], VOLRW);
01052   BEGIN_X(s);
01053 
01054   s = dspDelete(dbh, argv[1]);
01055   END(s, "dataspace delete");
01056 }
01057 
01058 static int
01059 dataspace_rename_realize(int argc, char *argv[])
01060 {
01061   if (argc != 3)
01062     return usage(mDataspaceRename);
01063 
01064   Status s;
01065   OPEN(argv[0], VOLRW);
01066   BEGIN_X(s);
01067   s = dspRename(dbh, argv[1], argv[2]);
01068   END(s, "dataspace rename");
01069 }
01070 
01071 static int
01072 dataspace_display_info(short dspid, DataspaceDesc *dsp)
01073 {
01074   if (!*dsp->name())
01075     return 0;
01076 
01077   printf(" Dataspace #%d\n", dspid);
01078   printf(" Name %s\n", dsp->name());
01079   printf(" Current datafile #%d\n", x2h_16(dsp->__datid(x2h_32(dsp->__cur()))));
01080   unsigned int ndat = x2h_u32(dsp->__ndat());
01081   for (int i = 0; i < ndat; i++) {
01082     printf("    Datafile #%d\n", x2h_16(dsp->__datid(i)));
01083     DatafileDesc _dat = sm_h->dat(x2h_16(dsp->__datid(i)));
01084     DatafileDesc *dat = &_dat;
01085     MapHeader *xmp = dat->mp();
01086     x2h_prologue(xmp, mp);
01087     if (*dat->name())
01088       printf("      Name     %s\n", dat->name());
01089     printf("      File     %s\n", dat->file());
01090     if (getDatType(sm_h, x2h_16(dsp->__datid(i))) == LogicalOidType)
01091       printf("      Oid Type Logical\n");
01092     else
01093       printf("      Oid Type Physical\n");
01094     printf("      Maxsize  %d\n", x2h_u32(dat->__maxsize()));
01095     printf("      Used     %2.2f%%\n",
01096            ((double)mp->mstat_u_bmstat_busy_slots()/(double)mp->nslots())*100.);
01097   }
01098 
01099   return 1;
01100 }
01101 
01102 static int
01103 dataspace_display_realize(int argc, char *argv[])
01104 {
01105   if (argc < 1)
01106     return usage(mDataspaceDisplay);
01107 
01108   sm_OPEN(argv[0], VOLREAD);
01109   sm_SHMH_INIT(argv[0], False);
01110 
01111   int dspid_cnt = argc-1;
01112   int i;
01113   char **dsps;
01114   short *dspids;
01115   dsps = (dspid_cnt ? new char*[dspid_cnt] : 0);
01116   dspids = (dspid_cnt ? new short[dspid_cnt] : 0);
01117 
01118   for (i = 0; i < dspid_cnt; i++)
01119     dsps[i] = argv[i+1];
01120 
01121   if (!dspid_cnt) {
01122     unsigned int ndsp = x2h_u32(sm_h->__ndsp());
01123     printf(" Database %s contains %d Dataspace%s\n\n", sm_dbh->dbfile, ndsp, (ndsp > 1 ? "s" : ""));
01124   }
01125 
01126   for (i = 0; i < dspid_cnt; i++)
01127     if (sm_CHECK(ESM_dspGet(sm_dbh, dsps[i], &dspids[i]),
01128                  "unknown dataspace"))
01129       return 1;
01130 
01131   int n = 0;
01132   if (!dspid_cnt)
01133     {
01134       unsigned int ndsp = x2h_u32(sm_h->__ndsp());
01135       for (i = 0, n = 0; i < ndsp; i++)
01136         {
01137           if (n) printf("\n");
01138           DataspaceDesc d = sm_h->dsp(i);
01139           n += dataspace_display_info(i, &d);
01140         }
01141       return 0;
01142     }
01143 
01144   for (i = 0; i < dspid_cnt; i++)
01145     {
01146       if (n) printf("\n");
01147       DataspaceDesc d = sm_h->dsp(dspids[i]);
01148       n += dataspace_display_info(dspids[i], &d);
01149     }
01150 
01151   return 0;
01152 }
01153 
01154 static int
01155 dataspace_setdefault_realize(int argc, char *argv[])
01156 {
01157   if (argc != 2)
01158     return usage(mDataspaceSetDefault);
01159 
01160   Status s;
01161   OPEN(argv[0], VOLRW);
01162   BEGIN_X(s);
01163 
01164   s = dspSetDefault(dbh, argv[1]);
01165   END(s, "dataspace setdefault");
01166 }
01167 
01168 static int
01169 dataspace_getdefault_realize(int argc, char *argv[])
01170 {
01171   if (argc != 1)
01172     return usage(mDataspaceGetDefault);
01173 
01174   OPEN(argv[0], VOLREAD);
01175 
01176   short dspid;
01177   int r = sm_CHECK(dspGetDefault(dbh, &dspid), "dataspace getdefault");
01178   if (r) return r;
01179 
01180   printf("Dataspace default:\n");
01181   printf("  Dspid #%d\n", dspid);
01182 
01183   return 0;
01184 }
01185 
01186 static int
01187 dataspace_setcurdat_realize(int argc, char *argv[])
01188 {
01189   if (argc != 3)
01190     return usage(mDataspaceSetCurDat);
01191 
01192   Status s;
01193   OPEN(argv[0], VOLRW);
01194   BEGIN_X(s);
01195 
01196   s = dspSetCurDat(dbh, argv[1], argv[2]);
01197   END(s, "dataspace setcurdat");
01198 }
01199 
01200 static int
01201 dataspace_getcurdat_realize(int argc, char *argv[])
01202 {
01203   if (argc != 2)
01204     return usage(mDataspaceGetCurDat);
01205 
01206   OPEN(argv[0], VOLREAD);
01207 
01208   short cur;
01209   int r = sm_CHECK(dspGetCurDat(dbh, argv[1], &cur),
01210                    "dataspace getcurdat");
01211   if (r) return r;
01212 
01213   printf("Current Datafile is #%d\n", cur);
01214 
01215   return 0;
01216 }
01217 
01218 static int
01219 dataspace_realize(int argc, char *argv[])
01220 {
01221   const char *action = argv[0];
01222   
01223   if (!action)
01224     return usage(M_DATASPACE);
01225 
01226   if (!strcmp(action, "create"))
01227     return dataspace_create_realize(argc-1, &argv[1]);
01228 
01229   if (!strcmp(action, "update"))
01230     return dataspace_update_realize(argc-1, &argv[1]);
01231 
01232   if (!strcmp(action, "delete"))
01233     return dataspace_delete_realize(argc-1, &argv[1]);
01234 
01235   if (!strcmp(action, "rename"))
01236     return dataspace_rename_realize(argc-1, &argv[1]);
01237 
01238   if (!strcmp(action, "display"))
01239     return dataspace_display_realize(argc-1, &argv[1]);
01240 
01241   if (!strcmp(action, "set:default"))
01242     return dataspace_setdefault_realize(argc-1, &argv[1]);
01243 
01244   if (!strcmp(action, "get:default"))
01245     return dataspace_getdefault_realize(argc-1, &argv[1]);
01246 
01247   if (!strcmp(action, "set:curdat"))
01248     return dataspace_setcurdat_realize(argc-1, &argv[1]);
01249 
01250   if (!strcmp(action, "get:curdat"))
01251     return dataspace_getcurdat_realize(argc-1, &argv[1]);
01252 
01253   return usage(M_DATASPACE);
01254 }
01255 
01256 #define MINSHMSIZE   0x400000U
01257 
01258 // 1. must be detected by configure
01259 // 2. the amount of memory may be detected by configure also
01260 //#define HAVE_WIDE_MEMORY_MAPPED
01261 #undef HAVE_WIDE_MEMORY_MAPPED
01262 
01263 #ifdef HAVE_WIDE_MEMORY_MAPPED
01264 #define MAXSHMSIZE 0x120000000U
01265 #else
01266 #define MAXSHMSIZE 0x40000000U
01267 #endif
01268 
01269 static int
01270 activetrans_get()
01271 {
01272   TransHeader *trshd = &sm_shmh->trs_hdr;
01273   Transaction *trs = (Transaction *)XM_ADDR(sm_xmh, trshd->first_trs);
01274   int cnt = 0;
01275 
01276   while (trs)
01277     {
01278       if (ESM_isTransactionActive(trs))
01279         cnt++;
01280       trs = (Transaction *)XM_ADDR(sm_xmh, trs->next);
01281     }
01282 
01283   return cnt;
01284 }
01285 
01286 static int
01287 shmem_resize_realize(int argc, char *argv[])
01288 {
01289   if (argc != 2)
01290     return usage(mShmemResize);
01291 
01292   sm_OPEN(argv[0], VOLRW);
01293   sm_SHMH_INIT(argv[0], True);
01294 
01295   unsigned int newshmsize = (unsigned int)atoi(argv[1])*ONE_K;
01296 
01297   DbShmHeader dbhshm;
01298   int r = 1;
01299 
01300 #ifndef NO_FILE_LOCK
01301   if (!filelockX(sm_dbh->vd->shmfd))
01302     {
01303       fprintf(stderr, "shmem file '%s' is in use\n", sm_shmfile);
01304       return 1;
01305     }
01306 #endif
01307 
01308   if (newshmsize < MINSHMSIZE)
01309     fprintf(stderr, "size %d is too small (minimum is %d bytes)\n",
01310            newshmsize, MINSHMSIZE);
01311   else if (newshmsize > MAXSHMSIZE)
01312     fprintf(stderr, "size %d too large (maximum is %d bytes)\n",
01313             newshmsize, MAXSHMSIZE);
01314   else if (read(sm_fdshm, &dbhshm, sizeof(dbhshm)) < 0)
01315     fprintf(stderr, "cannot read shmfile '%s'\n", sm_shmfile);
01316   else if (dbhshm.magic != MAGIC)
01317     fprintf(stderr, "shmfile '%s' is not a valid EyeDB shmfile\n",
01318             sm_shmfile);
01319   else if (sm_get_refcount())
01320     {
01321       /* seems to be in used: must check for active transactions */
01322       int cnt = activetrans_get();
01323       printf("shmfile '%s' is currenly in use: "
01324              "ref. count %d", sm_shmfile, sm_get_refcount());
01325       if (cnt)
01326         printf(", %d active transaction%s",
01327                 cnt, (cnt > 1 ? "s" : ""));
01328       printf("\n");
01329     }
01330   else if (ftruncate(sm_fdshm, newshmsize))
01331     fprintf(stderr, "ftruncate(\"%s\", %u) returns: '%s'\n",
01332             sm_shmfile, newshmsize, strerror(errno));
01333   else
01334     r = 0;
01335 
01336   if (!r) {
01337     munmap((caddr_t)sm_shmh, sm_shmsize);
01338     sm_shmsize = newshmsize;
01339     sm_SHMH_INIT(argv[0], True);
01340     ESM_transInit(sm_dbh->vd, (char *)sm_shmh, newshmsize);
01341   }
01342 
01343   ut_file_unlock(sm_fdshm);
01344   return r;
01345 }
01346 
01347 static int
01348 shm_dspmap_realize(int argc, char *argv[])
01349 {
01350   if (argc != 1)
01351     return usage(mShmemDspmap);
01352 
01353   sm_SHMH_INIT(argv[0], True);
01354   XMCheckMemory(sm_xmh);
01355   return 0;
01356 }
01357 
01358 static int
01359 shm_dspsize_realize(int argc, char *argv[])
01360 {
01361   if (argc != 1)
01362     return usage(mShmemDspsize);
01363 
01364   sm_SHMH_INIT(argv[0], False);
01365   printf("Shm Size %u bytes [~ %uM]\n", sm_shmsize, sm_shmsize/(1024*1024));
01366 
01367   return 0;
01368 }
01369 
01370 static int
01371 shmem_realize(int argc, char *argv[])
01372 {
01373   const char *action = argv[0];
01374 
01375   if (!action)
01376     return usage(M_SHMEM);
01377 
01378   if (!strcmp(action, "resize"))
01379     return shmem_resize_realize(argc-1, &argv[1]);
01380 
01381   if (!strcmp(action, "display:map"))
01382     return shm_dspmap_realize(argc-1, &argv[1]);
01383 
01384   if (!strcmp(action, "display:size"))
01385     return shm_dspsize_realize(argc-1, &argv[1]);
01386 
01387   if (!strcmp(action, "check"))
01388     return shmem_check_realize(argc-1, &argv[1]);
01389 
01390   if (!strcmp(action, "cleanup"))
01391     return shmem_cleanup_realize(argc-1, &argv[1]);
01392 
01393   return usage(M_SHMEM);
01394 }
01395 
01396 static int
01397 mutex_display_realize(int argc, char *argv[])
01398 {
01399   if (argc != 1)
01400     return usage(mMutexDisplay);
01401 
01402   sm_SHMH_INIT(argv[0], True);
01403 
01404   int lockX;
01405 
01406   DbLock *dblocks[] = {&sm_shmh->dblock_W, &sm_shmh->dblock_RW,
01407                        &sm_shmh->dblock_Wtrans};
01408   for (unsigned int i = 0; i < sizeof(dblocks)/sizeof(dblocks[0]); i++) {
01409     DbLock *dblock = dblocks[i];
01410     printf("  Mutex %s ", dblock->mp.mtname);
01411     if (dblock->mp.xid || dblock->S || dblock->X) {
01412       printf("Locked ");
01413       if (dblock->mp.xid)
01414         printf("by Server Pid %d ", dblock->mp.xid);
01415       printf("[S=%d, X=%d]\n", dblock->S, dblock->X);
01416     }
01417     else
01418       printf("not Locked\n");
01419   }
01420 
01421   MutexP *mt = sm_shmh->mtx.mp;
01422   for (unsigned i = 0; i < MTX_CNT; i++, mt++)
01423     {
01424 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
01425       printf("  Mutex %-4s ", mt->mtname);
01426 #else
01427       int r = pthread_mutex_trylock(&mt->u.mp);
01428 
01429       printf("  Mutex %-4s [POSIX mutex ", mt->mtname);
01430       if (!r)
01431         {
01432           printf("not locked] ");
01433           pthread_mutex_unlock(&mt->u.mp);
01434         }
01435       else
01436         printf("LOCKED] ");
01437 #endif
01438       printf("[eyedbsm mutex ");
01439       if (mt->locked)
01440         printf("LOCKED");
01441       else
01442         printf("not locked");
01443       if (mt->xid)
01444         printf(" by Server Pid = %d", mt->xid);
01445       printf("]\n");
01446     }
01447 
01448   return 0;
01449 }
01450 
01451 static void
01452 unlock_mutex_realize(int which, const char *mtname)
01453 {
01454   /*
01455 #ifdef HAVE_SEMAPHORE_POLICY_POSIX
01456   Status se;
01457   se = mutexLock(&sm_shmh->mtx.mp[which], 0);
01458   if (se && se->err == LOCK_TIMEOUT)
01459     {
01460       printf("unlocking mutex %s...\n", mtname);
01461       mutexInit(sm_dbh->vd, &sm_shmh->mtx.mp[which], mtname);
01462     }
01463   else
01464     mutexUnlock(&sm_shmh->mtx.mp[which], 0);
01465 #endif
01466 */
01467 }
01468 
01469 static int
01470 mutex_unlock_realize(int argc, char *argv[])
01471 {
01472   if (argc != 1)
01473     return usage(mMutexUnlock);
01474 
01475   sm_SHMH_INIT(argv[0], True);
01476 
01477   unlock_mutex_realize(MAP, "map");
01478   unlock_mutex_realize(TRS, "trs");
01479   unlock_mutex_realize(NX,  "nx");
01480   unlock_mutex_realize(SLT, "slt");
01481   unlock_mutex_realize(LSL, "lsl");
01482 
01483   return 0;
01484 }
01485 
01486 static int
01487 mutex_reset_realize(int argc, char *argv[])
01488 {
01489   if (argc != 1)
01490     return usage(mMutexReset);
01491 
01492   sm_SHMH_INIT(argv[0], True);
01493 
01494   DbMutexesInit(0, sm_shmh);
01495 
01496   return 0;
01497 }
01498 
01499 static int
01500 mutex_realize(int argc, char *argv[])
01501 {
01502   const char *action = argv[0];
01503   
01504   if (!action)
01505     return usage(M_MUTEX);
01506 
01507   if (!strcmp(action, "display"))
01508     return mutex_display_realize(argc-1, &argv[1]);
01509 
01510   if (!strcmp(action, "unlock"))
01511     return mutex_unlock_realize(argc-1, &argv[1]);
01512 
01513   if (!strcmp(action, "reset"))
01514     return mutex_reset_realize(argc-1, &argv[1]);
01515 
01516   return usage(M_MUTEX);
01517 }
01518 
01519 static int
01520 transowner_display(XMHandle *xmh, PObject *po)
01521 {
01522   TransOwner *trs_own;
01523   printf("{owners=#%u [%s]", po->trs_own.trs_off, sm_XL(po->trs_own.trs_lock));
01524 
01525   trs_own = (TransOwner *)XM_ADDR(xmh, po->trs_own.next);
01526 
01527   while (trs_own)
01528     {
01529       printf(", %u [%s]", trs_own->trs_off, sm_XL(trs_own->trs_lock));
01530       trs_own = (TransOwner *)XM_ADDR(xmh, trs_own->next);
01531     }
01532 
01533   printf("}\n");
01534   return 0;
01535 }
01536 
01537 static void
01538 one_transaction_display(XMHandle *xmh, TransHeader *trshd,
01539                         Transaction *trs, Boolean all)
01540 {
01541   HashTable *obj_ht;
01542   HashTable *trs_ht;
01543   int i, count;
01544   XMOffset *tro_poff;
01545   int cnt = 0;
01546 
01547   if (trs->trs_state == TransCOMMITING)
01548     {
01549       printf("    COMMITING...\n");
01550       return;
01551     }
01552 
01553   if (trs->trs_state == TransABORTING)
01554     {
01555       printf("    ABORTING...\n");
01556       return;
01557     }
01558 
01559   if (trs->trs_state != TransACTIVE)
01560     {
01561       printf("    STATE %d...\n", trs->trs_state);
01562       return;
01563     }
01564 
01565   obj_ht = (HashTable *)XM_ADDR(xmh, trshd->obj_ht);
01566 
01567   trs_ht = (HashTable *)XM_ADDR(xmh, trs->ht_off);
01568 
01569   count = trs_ht->mask + 1;
01570 
01571   if (!all)
01572     {
01573       printf("\n");
01574       return;
01575     }
01576 
01577   printf(" <<<\n");
01578   for (i = 0, tro_poff = &trs_ht->offs[0]; i < count; i++, tro_poff++)
01579     if (*tro_poff)
01580       {
01581         TRObject *tro = (TRObject *)XM_ADDR(xmh, *tro_poff);
01582         while (tro)
01583           {
01584             PObject *po = (PObject *)XM_ADDR(xmh, tro->po_off);
01585               printf("    %-20s ", getOidString(&po->oid));
01586 
01587             if (trs->trobj_wait == *tro_poff)
01588               {
01589                 printf("WAITING for lock %s ", sm_XL(trs->lock_wait));
01590                 cnt--;
01591               }
01592             else if (tro->lockX)
01593               printf("lock X ");
01594             else if (tro->lockS)
01595               printf("lock S ");
01596             else if (tro->lockP)
01597               printf("lock P ");
01598 
01599             printf("[X=%d, S=%d, P=%d] ", tro->lockX, tro->lockS,
01600                    tro->lockP);
01601 #ifndef EYEDB_USE_DATA_VMEM
01602             if (tro->data) {
01603               void *data = XM_ADDR(xmh, tro->data);
01604               printf("[datasz=%d, mapped=%s] ", objDataSize(data),
01605                      objDataAll(data) ? "whole" : "partial");
01606                      
01607             }
01608 #endif
01609             transowner_display(xmh, po);
01610             tro = (TRObject *)XM_ADDR(xmh, tro->next);
01611             cnt++;
01612           }
01613       }
01614 
01615   if (cnt != trs->obj_cnt)
01616     printf("    incoherency locked objects count %d vs. %d\n",
01617            cnt, trs->obj_cnt);
01618   printf(" >>>\n\n");
01619 }
01620 
01621 static void
01622 transaction_display_realize(int server_pid, Boolean all)
01623 {
01624   TransHeader *trshd;
01625   Transaction *trs;
01626   XMOffset trs_x[256];
01627   int cnt;
01628 
01629   trshd = &sm_shmh->trs_hdr;
01630 
01631   trs = (Transaction *)XM_ADDR(sm_xmh, trshd->first_trs);
01632 
01633   cnt = 0;
01634 
01635   /*
01636   if (!force)
01637     {
01638       LOCK();
01639     }
01640     */
01641 
01642 #define SEC_PER_MIN 60
01643 #define MIN_PER_HOUR 60
01644 #define SEC_PER_HOUR (SEC_PER_MIN * MIN_PER_HOUR)
01645 #define USEC_PER_SECOND 1000000
01646 #define USEC_PER_MS        1000
01647   while (trs)
01648     {
01649       if (!server_pid || trs->xid == server_pid)
01650         {
01651           printf(" Transaction #%d\n", cnt);
01652           printf(" Server Pid %d\n", trs->xid);
01653           printf(" Object Count %d\n", trs->obj_cnt);
01654           printf(" Deleted Object Count %d\n", trs->del_obj_cnt);
01655           printf(" Hash Table Entries %u\n", ((HashTable *)XM_ADDR(sm_xmh, trs->ht_off))->mask+1);
01656           printf(" Created on %s\n", eyedblib::setbuftime(trs->create_time));
01657           printf(" Last Access on %s\n", eyedblib::setbuftime(trs->access_time));
01658           unsigned long duration = trs->access_time - trs->create_time;
01659           unsigned int h = duration / (SEC_PER_HOUR * USEC_PER_SECOND);
01660 
01661           unsigned int m = (duration - h * SEC_PER_HOUR * USEC_PER_SECOND) / (long)(SEC_PER_MIN * USEC_PER_SECOND);
01662           unsigned int s = (duration - h * SEC_PER_HOUR * USEC_PER_SECOND - m * SEC_PER_MIN * USEC_PER_SECOND) / USEC_PER_SECOND;
01663           unsigned int ms = (duration - h * SEC_PER_HOUR * USEC_PER_SECOND - m * SEC_PER_MIN * USEC_PER_SECOND - s * USEC_PER_SECOND) / USEC_PER_MS;
01664           unsigned int us = (duration - h * SEC_PER_HOUR * USEC_PER_SECOND - m * SEC_PER_MIN * USEC_PER_SECOND - s * USEC_PER_SECOND - ms * USEC_PER_MS);
01665           
01666           printf(" Duration %02u:%02u:%02u %03u.%03ums\n", h, m, s, ms, us);
01667           printf(" State %s\n",
01668                   (ESM_isTransactionActive(trs) ? "ACTIVE" : "INACTIVE"));
01669           one_transaction_display(sm_xmh, trshd, trs, all);
01670           cnt++;
01671         }
01672       trs = (Transaction *)XM_ADDR(sm_xmh, trs->next);
01673     }
01674 
01675   /*
01676   if (!force)
01677     {
01678       UNLOCK();
01679     }
01680     */
01681 
01682   if (!cnt)
01683     {
01684       if (server_pid)
01685         printf("No Current Transaction for Server Pid %d.\n",
01686                 server_pid);
01687       else
01688         printf("No Current Transactions.\n");
01689     }
01690 }
01691 
01692 static int
01693 transaction_abrtinact_realize(int argc, char *argv[], Boolean all)
01694 {
01695   if (argc != 1)
01696     return usage(mTransactionAbrtInact);
01697 
01698   trace_garb_trs = True;
01699   OPEN(argv[0], VOLRW);
01700   return 0;
01701 }
01702 
01703 static int
01704 transaction_display_realize(int argc, char *argv[], Boolean all)
01705 {
01706   if (argc != 1 && argc != 2)
01707     return usage(all ? mTransactionDisplay : mTransactionDsphead);
01708 
01709   sm_SHMH_INIT(argv[0], True);
01710   transaction_display_realize((argc == 2 ? atoi(argv[1]) : 0), all);
01711   return 0;
01712 }
01713 
01714 static void
01715 item_print(TransOwner *trs_own)
01716 {
01717   Transaction *trs = (Transaction *)XM_ADDR(sm_xmh, trs_own->trs_off);
01718   printf("[xid=%d, lock=%s]", trs->xid, sm_XL(trs_own->trs_lock));
01719 }
01720 
01721 static int
01722 transaction_dspoidlock_realize(int argc, char *argv[])
01723 {
01724   int i, n;
01725   HashTable *obj_ht;
01726   TransOwner *trs_own;
01727 
01728   sm_SHMH_INIT(argv[0], True);
01729 
01730   obj_ht = (HashTable *)XM_ADDR(sm_xmh, sm_shmh->trs_hdr.obj_ht);
01731 
01732   for (i = 0, n = 0; i < obj_ht->mask+1; i++)
01733     {
01734       XMOffset po_off = obj_ht->offs[i];
01735 
01736       while (po_off)
01737         {
01738           PObject *po = (PObject *)XM_ADDR(sm_xmh, po_off);
01739           
01740           printf("#%d %s, ", n, getOidString(&po->oid));
01741           n++;
01742           printf("lockS=%d, lockX=%d, lockSX=%d, ", po->lockS, po->lockX,
01743                  po->lockSX);
01744           printf("state=");
01745           if (po->state = Active)
01746             printf("Active");
01747           else if (po->state = Deleted)
01748             printf("Deleted");
01749           else if (po->state = Zombie)
01750             printf("Zombie");
01751           if (po->wait_cnt)
01752             printf(", wait count=%d", po->wait_cnt);
01753           printf(", transaction count=%d {", po->trs_cnt);
01754 
01755           item_print(&po->trs_own);
01756           trs_own = (TransOwner *)XM_ADDR(sm_xmh, po->trs_own.next);
01757 
01758           while (trs_own)
01759             {
01760               printf(", ");
01761               item_print(trs_own);
01762               trs_own = (TransOwner *)XM_ADDR(sm_xmh, trs_own->next);
01763             }
01764           
01765           printf("}\n");
01766           po_off = po->next;
01767         }
01768     }
01769 
01770   return 0;
01771 }
01772 
01773 static int
01774 transaction_realize(int argc, char *argv[])
01775 {
01776   const char *action = argv[0];
01777 
01778   if (!action)
01779     return usage(M_TRANSACTION);
01780 
01781   if (!strcmp(action, "display"))
01782     return transaction_display_realize(argc-1, &argv[1], True);
01783 
01784   if (!strcmp(action, "display:header"))
01785     return transaction_display_realize(argc-1, &argv[1], False);
01786 
01787   if (!strcmp(action, "display:lockedoids"))
01788     return transaction_dspoidlock_realize(argc-1, &argv[1]);
01789 
01790   if (!strcmp(action, "abort:inactive"))
01791     return transaction_abrtinact_realize(argc-1, &argv[1], False);
01792 
01793   return usage(M_TRANSACTION);
01794 }
01795 
01796 struct PageStats {
01797   unsigned long long totalsize;
01798   unsigned long long totalsize_align;
01799   unsigned int totaldatpages_max; // for check
01800   unsigned int totalomppages_max; // for check
01801   unsigned int totaldmppages_max; // for check
01802 
01803   unsigned int totaldatpages_cnt;
01804   char *totaldatpages;
01805 
01806   unsigned int totaldmppages_cnt;
01807   char *totaldmppages;
01808 
01809   unsigned int totalomppages_cnt;
01810   char *totalomppages;
01811 
01812   unsigned int oid_cnt;
01813   unsigned short datid;
01814 
01815   PageStats() {
01816     totalsize = 0;
01817     totalsize_align = 0;
01818 
01819     totaldatpages_max = 0;
01820     totalomppages_max = 0;
01821     totaldmppages_max = 0;
01822 
01823     totaldatpages = (char *)0;
01824     totalomppages = (char *)0;
01825     totaldmppages = (char *)0;
01826 
01827     totaldatpages_cnt = 0;
01828     totalomppages_cnt = 0;
01829     totaldmppages_cnt = 0;
01830 
01831     oid_cnt = 0;
01832     datid = (unsigned short)-1;
01833   }
01834   
01835   void setDatid(short _datid) {
01836     this->datid = _datid;
01837     DatafileDesc _dfd = sm_h->dat(datid); 
01838     DatafileDesc *dfd = &_dfd;
01839     MapHeader *xmp = dfd->mp();
01840     x2h_prologue(xmp, mp);
01841 
01842     totaldatpages_max = (x2h_u32(dfd->__maxsize())*ONE_K>>pgsize_pow2)+1;
01843     totaldatpages = (char *)m_calloc(totaldatpages_max, 1);
01844 
01845     totalomppages_max = (x2h_u32(sm_h->__nbobjs())*OIDLOCSIZE>>pgsize_pow2)+1;
01846     totalomppages = (char *)m_calloc(totalomppages_max, 1);
01847 
01848     totaldmppages_max = (((x2h_u32(dfd->__maxsize())*ONE_K)/(mp->sizeslot()*8))>>pgsize_pow2)+1;
01849     totaldmppages = (char *)m_calloc(totaldmppages_max, 1);
01850   }
01851 
01852   void set(const ObjectLocation &objloc) {
01853     if (!objloc.is_valid)
01854       return;
01855     unsigned int size = objloc.size + sizeof(ObjectHeader);
01856     NS ns = SZ2NS(size, sm_h->dat(datid).mp());
01857     totalsize += size;
01858     totalsize_align += ns * sm_h->dat(datid).mp()->sizeslot();
01859 
01860     assert(objloc.dat_start_pagenum < totaldatpages_max);
01861     if (!totaldatpages[objloc.dat_start_pagenum])
01862       {
01863         totaldatpages[objloc.dat_start_pagenum] = 1;
01864         totaldatpages_cnt++;
01865       }
01866 
01867     assert(objloc.dat_end_pagenum < totaldatpages_max);
01868     if (!totaldatpages[objloc.dat_end_pagenum])
01869       {
01870         totaldatpages[objloc.dat_end_pagenum] = 1;
01871         totaldatpages_cnt++;
01872       }
01873 
01874     assert(objloc.omp_start_pagenum < totalomppages_max);
01875     if (!totalomppages[objloc.omp_start_pagenum])
01876       {
01877         totalomppages[objloc.omp_start_pagenum] = 1;
01878         totalomppages_cnt++;
01879       }
01880 
01881     assert(objloc.omp_end_pagenum < totalomppages_max);
01882     if (!totalomppages[objloc.omp_end_pagenum])
01883       {
01884         totalomppages[objloc.omp_end_pagenum] = 1;
01885         totalomppages_cnt++;
01886       }
01887 
01888     assert(objloc.dmp_start_pagenum < totaldmppages_max);
01889     if (!totaldmppages[objloc.dmp_start_pagenum])
01890       {
01891         totaldmppages[objloc.dmp_start_pagenum] = 1;
01892         totaldmppages_cnt++;
01893       }
01894 
01895     assert(objloc.dmp_end_pagenum < totaldmppages_max);
01896     if (!totaldmppages[objloc.dmp_end_pagenum])
01897       {
01898         totaldmppages[objloc.dmp_end_pagenum] = 1;
01899         totaldmppages_cnt++;
01900       }
01901     oid_cnt++;
01902   }
01903 };
01904 
01905 static int
01906 lastnx_action_realize(int argc, char *argv[], mAction action)
01907 {
01908   if ((action == mOidSetLastNx && argc != 2) ||
01909       (action == mOidSetCurNx && argc != 2) ||
01910       (action == mOidSyncCurLastNx && argc != 1) ||
01911       (action == mOidGetCurLastNx && argc != 1))
01912     return usage(action);
01913 
01914   sm_OPEN(argv[0], (action == mOidGetCurLastNx ? VOLREAD : VOLRW));
01915   sm_SHMH_INIT(argv[0], True);
01916 
01917   if (action == mOidGetCurLastNx) {
01918     printf("current nx: %u\n", x2h_u32(sm_h->__curidxbusy()));
01919     printf("last nx: %u\n", x2h_u32(sm_h->__lastidxbusy()));
01920     printf("last nx blkalloc: %u\n", x2h_u32(sm_h->__lastidxblkalloc()));
01921     return 0;
01922   }
01923 
01924   if (action == mOidSyncCurLastNx) {
01925     sm_h->__curidxbusy() = sm_h->__lastidxbusy();
01926     return 0;
01927   }
01928 
01929   unsigned int idxbusy = atoi(argv[1]);
01930   if (idxbusy <= 0)
01931     return usage(action);
01932 
01933   if (action == mOidSetCurNx) {
01934     sm_h->__curidxbusy() = h2x_u32(idxbusy);
01935     return 0;
01936   }
01937 
01938   if (x2h_u32(sm_h->__lastidxbusy()) != idxbusy) {
01939     if (x2h_u32(sm_h->__lastidxbusy()) > idxbusy)
01940       printf("\n** YOU ASK TO DECREASE lastnx PARAMETER: OPERATION STRICTLY NOT RECOMMENDED **\n");
01941     printf("\nDo you really want to change lastnx from %u to %u in "
01942            "database '%s'? ", x2h_u32(sm_h->__lastidxbusy()), idxbusy, argv[0]);
01943     for (;;)
01944       {
01945         char s[128];
01946         fgets(s, sizeof s, stdin);
01947         s[strlen(s)-1] = 0;
01948         if (!strcasecmp(s, "y") || !strcasecmp(s, "yes"))
01949           {
01950             sm_h->__lastidxbusy() = h2x_u32(idxbusy);
01951             break;
01952           }
01953         else if (!strcasecmp(s, "n") || !strcasecmp(s, "no"))
01954           {
01955             printf("\nOperation aborted by user request.\n");
01956             break;
01957           }
01958         else
01959           printf("Please, answer `y[es]' or `n[o]'? ");
01960       }
01961   }
01962 
01963   return 0;
01964 }
01965 
01966 Boolean
01967 is_in_dsp(short datid, short datids[], int ndatids)
01968 {
01969   for (int i = 0; i < ndatids; i++)
01970     if (datids[i] == datid)
01971       return True;
01972 
01973   return False;
01974 }
01975 
01976 static int
01977 oid_move_realize(int argc, char *argv[], mAction action)
01978 {
01979   if (argc != 3)
01980     return usage(action);
01981 
01982   OPEN(argv[0], VOLRW);
01983   short from_datid, to_datid;
01984   short from_dspid, to_dspid;
01985   short datids[MAX_DAT_PER_DSP];
01986   unsigned int ndatids;
01987   if (action == mOidMoveDat) {
01988     if (sm_CHECK(datCheck(dbh, argv[1], &from_datid, 0), "datafile"))
01989       return 1;
01990 
01991     if (sm_CHECK(datCheck(dbh, argv[2], &to_datid, 0), "datafile"))
01992       return 1;
01993     from_dspid = to_dspid = -1;
01994   }
01995   else {
01996     if (sm_CHECK(dspCheck(dbh, argv[1], &from_dspid, datids, &ndatids), "dataspace"))
01997       return 1;
01998 
01999     if (sm_CHECK(dspCheck(dbh, argv[2], &to_dspid, 0, 0), "dataspace"))
02000       return 1;
02001     from_datid = to_datid = -1;
02002   }
02003 
02004   Boolean found;
02005   Oid oid;
02006   int oid_cnt = 0;
02007   int oid_moved = 0;
02008   int oid_invalid = 0;
02009 
02010   Status s;
02011   BEGIN(s);
02012 
02013   if (sm_CHECK(firstOidDatGet(dbh, from_datid, &oid, &found), "first oid get"))
02014     return 1;
02015 
02016   while (found) {
02017     ObjectLocation objloc;
02018     if (sm_CHECK(objectLocationGet(dbh, &oid, &objloc),
02019                  "object location"))
02020       return 1;
02021 
02022     if (from_datid >= 0) {
02023       assert(objloc.datid == from_datid);
02024       if (objloc.datid == from_datid) {
02025         if (sm_CHECK(objectMoveDat(dbh, &oid, to_datid),
02026                      "moving oid"))
02027           return 1;
02028         oid_moved++;
02029       }
02030     }
02031     else if (is_in_dsp(objloc.datid, datids, ndatids)) {
02032       if (sm_CHECK(objectMoveDsp(dbh, &oid, to_dspid),
02033                    "moving oid"))
02034         return 1;
02035       oid_moved++;
02036     }
02037 
02038     oid_cnt++;
02039 
02040     Oid newoid;
02041     if (sm_CHECK(nextOidDatGet(dbh, from_datid, &oid, &newoid, &found), "next oid get"))
02042       return 1;
02043     oid = newoid;
02044   }
02045 
02046   printf("%d/%d oid%s moved\n", oid_moved, oid_cnt, (oid_moved != 1 ? "s" : ""));
02047 
02048   END(s, "oid move");
02049   return 0;
02050 }
02051 
02052 static int
02053 get_def_rawdata_hash_key(const void *key, unsigned int len)
02054 {
02055   int x = 0;
02056   unsigned char *k = (unsigned char *)(key)+len-1;
02057 
02058   for (int i = 0; i < len; i++)
02059     x += *k-- << (i*8);
02060 
02061   return x;
02062 }
02063 
02064 static int test_hash = getenv("ESM_TEST_HASH") ? atoi(getenv("ESM_TEST_HASH")) : 0;
02065 static int *hash_keys;
02066 
02067 #define IDEAL(SZ) ((SZ) ? ((((SZ)-1)>>pgsize_pow2)+1) :  0)
02068 
02069 static int
02070 oid_action_realize(int argc, char *argv[], mAction action)
02071 {
02072   if (action == mOidMoveDat || action == mOidMoveDsp)
02073     return oid_move_realize(argc, argv, action);
02074 
02075   if (argc != 1 && argc != 2)
02076     return usage(action);
02077 
02078   if (test_hash) {
02079     hash_keys = new int[test_hash+1];
02080     memset(hash_keys, 0, sizeof(int)*(test_hash+1));
02081   }
02082 
02083   sm_OPEN(argv[0], (action == mOidMoveDat ? VOLRW : VOLREAD));
02084   sm_SHMH_INIT(argv[0], True);
02085 
02086   Boolean found;
02087   Oid oid;
02088   short from_datid, to_datid;
02089   if (action == mOidMoveDat) {
02090     if (sm_CHECK(ESM_datCheck(sm_dbh, argv[1], &from_datid, 0), "datafile"))
02091       return 1;
02092     if (sm_CHECK(ESM_datCheck(sm_dbh, argv[2], &to_datid, 0), "datafile"))
02093       return 1;
02094   }
02095   else if (argc == 2) {
02096     if (sm_CHECK(ESM_datCheck(sm_dbh, argv[1], &from_datid, 0), "datafile"))
02097       return 1;
02098   }
02099   else
02100     from_datid = -1;
02101 
02102   unsigned int oid_cnt = 0;
02103   unsigned int oid_log_cnt = 0;
02104   unsigned int oid_phy_cnt = 0;
02105   unsigned int oid_moved = 0;
02106   unsigned int oid_invalid = 0;
02107 
02108   PageStats *page_stats;
02109 
02110   if (action == mOidDspLocaStats)
02111     {
02112       unsigned int ndat = x2h_u32(sm_h->__ndat());
02113       page_stats = new PageStats[ndat];
02114       for (int i = 0; i < ndat; i++)
02115         page_stats[i].setDatid(i);
02116     }
02117 
02118   short s_datid, e_datid;
02119   if (from_datid >= 0) {
02120     s_datid = from_datid;
02121     e_datid = from_datid+1;
02122   }
02123   else {
02124     s_datid = 0;
02125     e_datid = x2h_u32(sm_h->__ndat());
02126   }
02127 
02128   for (int datid = s_datid; datid < e_datid; datid++) {
02129     if (!isDatValid(sm_dbh, datid))
02130       continue;
02131 
02132     if (sm_CHECK(ESM_firstOidDatGet(sm_dbh, datid, &oid, &found), "first oid get"))
02133       return 1;
02134 
02135     while (found)
02136       {
02137         /*
02138         if (isPhy(sm_dbh, &oid))
02139           printf("#%d %s %s\n", datid, getOidString(&oid), isPhy(sm_dbh, &oid)
02140                  ? "phy" : "log");
02141         */
02142 
02143         ObjectLocation objloc = {0};
02144         if (action != mOidDspCount) {
02145           if (sm_CHECK(ESM_objectLocationGet(sm_dbh, &oid, &objloc),
02146                        "object location"))
02147             return 1;
02148         }
02149 
02150         if (action == mOidMoveDat)
02151           {
02152             if (objloc.datid == from_datid) {
02153               if (sm_CHECK(ESM_objectMoveDatDsp(sm_dbh, &oid, to_datid, -1,
02154                                                False, OPDefault),
02155                            "moving oid"))
02156                 return 1;
02157               oid_moved++;
02158             }
02159             oid_cnt++;
02160           }
02161         else if (from_datid < 0 || objloc.datid == from_datid)
02162           {
02163             if (action == mOidDspLoca) {
02164               printf("%s: %s%s datid #%d, slots [%u, %u], size %u, "
02165                      "dat pages [%u. %u], omp pages [%u, %u], "
02166                      "dmp pages [%u, %u]\n",
02167                      getOidString(&oid),
02168                      (objloc.is_valid ? "" : "*invalid* "),
02169                      (isPhy(sm_dbh, &oid) ? "physical" : "logical"),
02170                      objloc.datid,
02171                      objloc.slot_start_num, objloc.slot_end_num, objloc.size,
02172                      objloc.dat_start_pagenum, objloc.dat_end_pagenum,
02173                      objloc.omp_start_pagenum,
02174                      objloc.omp_end_pagenum,
02175                      objloc.dmp_start_pagenum,
02176                      objloc.dmp_end_pagenum);
02177               oid_cnt++;
02178             }
02179             else if (action == mOidDspLocaStats)
02180               page_stats[objloc.datid].set(objloc);
02181             else if (action == mOidDspList)
02182               {
02183                 if (test_hash) {
02184                   hash_keys[get_def_rawdata_hash_key(&oid, sizeof(oid)) & test_hash]++;
02185                 }
02186                 else {
02187                   unsigned int size;
02188                   if (sm_CHECK(ESM_objectSizeGet(sm_dbh, &size, DefaultLock,
02189                                                 &oid, OPDefault),
02190                                "size get"))
02191                     return 1;
02192                   printf("%s [size=%d]\n", getOidString(&oid), size);
02193                 }
02194                 oid_cnt++;
02195               }
02196             else if (action == mOidDspCount) {
02197               oid_cnt++;
02198               if (isPhy(sm_dbh, &oid))
02199                 oid_phy_cnt++;
02200               else
02201                 oid_log_cnt++;
02202             }
02203           }
02204 
02205         Oid newoid;
02206         if (sm_CHECK(ESM_nextOidDatGet(sm_dbh, datid, &oid, &newoid, &found), "next oid get"))
02207           return 1;
02208         oid = newoid;
02209       }
02210   }
02211 
02212   if (action == mOidDspLocaStats) {
02213     unsigned int ndat = x2h_u32(sm_h->__ndat());
02214     for (int i = 0; i < ndat; i++)
02215       if (from_datid < 0 || i == from_datid)
02216         {
02217           printf("Datafile #%d\n", i);
02218           printf("  Object Count   %d\n", page_stats[i].oid_cnt);
02219           printf("  Size           ");
02220           display_size(page_stats[i].totalsize);
02221           printf("  Slot Size      ");
02222           display_size(page_stats[i].totalsize_align);
02223           printf("  DAT Page Count %d",
02224                  page_stats[i].totaldatpages_cnt);
02225           printf(" (Ideal Page Count %lld, ",
02226                  IDEAL(page_stats[i].totalsize));
02227           printf("Ideal Slot Based Page Count %lld)\n",
02228                  IDEAL(page_stats[i].totalsize_align));
02229           //((page_stats[i].totalsize_align-1)>>pgsize_pow2)+1);
02230           printf("  OMP Page Count %d",
02231                  page_stats[i].totalomppages_cnt);
02232           printf(" (Ideal Page Count %d)\n",
02233                  page_stats[i].oid_cnt ?
02234                  ((page_stats[i].oid_cnt*OIDLOCSIZE)>>pgsize_pow2)+1 : 0);
02235           /*
02236             (page_stats[i].totalomppages_cnt ?
02237             (((page_stats[i].totalomppages_cnt*OIDLOCSIZE)>>pgsize_pow2)+1)) : 0);
02238           */
02239           printf("  DMP Page Count %d",
02240                  page_stats[i].totaldmppages_cnt);
02241           printf(" (Ideal Page Count %lld)\n",
02242                  (page_stats[i].totalsize_align ?
02243                   ((((page_stats[i].totalsize_align-1)/(sm_h->dat(i).mp()->sizeslot()*8))>>pgsize_pow2)+1) : 0));
02244           printf("\n");
02245         }
02246   }
02247   else if (action == mOidMoveDat)
02248     printf("%d oid%s moved\n", oid_moved, (oid_moved != 1 ? "s" : ""));
02249   else if (test_hash) {
02250     //printf("HASH MIN %d HASH MAX %d TOTAL %d AVG %f\n", hash_min, hash_max,
02251     //hash_total, (float)hash_total/(oid_cnt*sizeof(Oid)));
02252     for (int i = 0; i <= test_hash; i++)
02253       printf("%d %d\n", i, hash_keys[i]);
02254   }
02255   else
02256     printf("%u OID%s found [%u log/%u phy]\n", oid_cnt,
02257            (oid_cnt != 1 ? "s" : ""), oid_log_cnt, oid_phy_cnt);
02258   return 0;
02259 }
02260 
02261 static int
02262 oid_realize(int argc, char *argv[])
02263 {
02264   const char *action = argv[0];
02265 
02266   if (!action)
02267     return usage(M_OID);
02268 
02269   if (!strcmp(action, "move:datafile"))
02270     return oid_action_realize(argc-1, &argv[1], mOidMoveDat);
02271 
02272   if (!strcmp(action, "move:dataspace"))
02273     return oid_action_realize(argc-1, &argv[1], mOidMoveDsp);
02274 
02275   if (!strcmp(action, "display:list"))
02276     return oid_action_realize(argc-1, &argv[1], mOidDspList);
02277 
02278   if (!strcmp(action, "display:count"))
02279     return oid_action_realize(argc-1, &argv[1], mOidDspCount);
02280 
02281   if (!strcmp(action, "get:curlastnx"))
02282     return lastnx_action_realize(argc-1, &argv[1], mOidGetCurLastNx);
02283 
02284   if (!strcmp(action, "set:lastnx"))
02285     return lastnx_action_realize(argc-1, &argv[1], mOidSetLastNx);
02286 
02287   if (!strcmp(action, "set:curnx"))
02288     return lastnx_action_realize(argc-1, &argv[1], mOidSetCurNx);
02289 
02290   if (!strcmp(action, "sync:curlastnx"))
02291     return lastnx_action_realize(argc-1, &argv[1], mOidSyncCurLastNx);
02292 
02293   if (!strcmp(action, "display:loca"))
02294     return oid_action_realize(argc-1, &argv[1], mOidDspLoca);
02295 
02296   if (!strcmp(action, "display:locastats"))
02297     return oid_action_realize(argc-1, &argv[1], mOidDspLocaStats);
02298 
02299   return usage(M_OID);
02300 }
02301 
02302 int
02303 main(int argc, char *argv[])
02304 {
02305   if (sm_CHECK(init(), "se init"))
02306     return 1;
02307 
02308   // for debug
02309   if (getenv("EYEDBSM_DISPLAY_STRUCTS")) {
02310     display_structs();
02311     return 0;
02312   }
02313 
02314   prog = argv[0];
02315 
02316   const char *major = argv[1];
02317 
02318   if (!major)
02319     return usage();
02320 
02321   if (!strcmp(major, "database"))
02322     return databarealize(argc-2, &argv[2]);
02323 
02324   if (!strcmp(major, "datafile"))
02325     return datafile_realize(argc-2, &argv[2]);
02326 
02327   if (!strcmp(major, "dataspace"))
02328     return dataspace_realize(argc-2, &argv[2]);
02329 
02330   if (!strcmp(major, "shmem"))
02331     return shmem_realize(argc-2, &argv[2]);
02332 
02333   if (!strcmp(major, "mutex"))
02334     return mutex_realize(argc-2, &argv[2]);
02335 
02336   if (!strcmp(major, "transaction"))
02337     return transaction_realize(argc-2, &argv[2]);
02338 
02339   if (!strcmp(major, "oid"))
02340     return oid_realize(argc-2, &argv[2]);
02341 
02342   return usage();
02343 }
02344 
02345 

Generated on Mon Dec 22 18:15:55 2008 for eyedb by  doxygen 1.5.3