kern_dat.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 "kern_p.h"
00027 
00028 #if 0
00029 #undef CHECK_X
00030 #define CHECK_X(dbh, msg) \
00031  if (!ESM_isExclusive(dbh)) \
00032      fprintf(stderr, "WARNING: exclusive database access is needed when " msg "\n")
00033 #endif
00034 
00035 namespace eyedbsm {
00036 
00037   static Status
00038   get_datid(DbHandle const *dbh, const char *datfile, short &datid,
00039             short *dspid = 0)
00040   {
00041     DbHeader _dbh(DBSADDR(dbh));
00042     DbHeader *h = &_dbh;
00043     assert(x2h_u32(h->__magic()) == MAGIC);
00044     if (!*datfile)
00045       return statusMake(INVALID_DATAFILE, "invalid empty datafile name");
00046 
00047     if (is_number(datfile))
00048       {
00049         datid = atoi(datfile);
00050         if (!isDatValid(dbh, datid))
00051           return statusMake(INVALID_DATAFILE, "datafile '%s' not found",
00052                             datfile);
00053         if (dspid)
00054           *dspid = getDataspace(&_dbh, datid);
00055         return Success;
00056       }
00057 
00058     unsigned int ndat = x2h_u32(h->__ndat());
00059     for (datid = 0; datid < ndat; datid++)
00060       if ((!strcmp(datfile, h->dat(datid).name()) ||
00061            !strcmp(datfile, h->dat(datid).file())) &&
00062           isDatValid(dbh, datid))
00063         break;
00064 
00065     if (datid == ndat)
00066       return statusMake(INVALID_DATAFILE, "datafile '%s' not found",
00067                         datfile);
00068 
00069     if (dspid)
00070       *dspid = getDataspace(h, datid);
00071 
00072     return Success;
00073   }
00074 
00075   Status
00076   checkNewDatafile(DbHeader *h, const char *file, const char *name)
00077   {
00078     if (is_number(name))
00079       return statusMake(INVALID_DATAFILE, "a datafile symbolic name (%s) "
00080                         "cannot be a number", name);
00081 
00082     if (strlen(name) >= L_NAME)
00083       return statusMake(INVALID_DATAFILE, "datafile name %s is too "
00084                         "large, maximum size is %d",
00085                         name, L_NAME);
00086 
00087     if (strlen(file) >= L_FILENAME)
00088       return statusMake(INVALID_DATAFILE, "datafile %s is too "
00089                         "large, maximum size is %d",
00090                         file, L_FILENAME);
00091 
00092     unsigned int ndat = x2h_u32(h->__ndat());
00093     if (*file)
00094       for (int i = 0; i < ndat; i++)
00095         if (!strcmp(file, h->dat(i).name()) || !strcmp(file, h->dat(i).file()))
00096           return statusMake(INVALID_DATAFILE,
00097                             "datafile %s is already in used", file);
00098 
00099     if (*name)
00100       for (int i = 0; i < ndat; i++)
00101         if (!strcmp(name, h->dat(i).name()) || !strcmp(name, h->dat(i).file()))
00102           return statusMake(INVALID_DATAFILE,
00103                             "datafile name %s is already in used", name);
00104 
00105     return Success;
00106   }
00107 
00108   extern short
00109   getDataspace(const DbHeader *dbh, short datid)
00110   {
00111     assert(x2h_u32(dbh->__magic()) == MAGIC);
00112     return DATTYPE_CLEAN(x2h_16(dbh->dat(datid).__dspid()));
00113   }
00114 
00115   extern short
00116   getDataspace_inplace(const DbHeader *dbh, short datid)
00117   {
00118     assert(dbh->__magic() == MAGIC);
00119     return DATTYPE_CLEAN(dbh->dat(datid).__dspid());
00120   }
00121 
00122   extern void
00123   setDataspace(DbHeader *dbh, short datid, short dspid)
00124   {
00125     assert(x2h_u32(dbh->__magic()) == MAGIC);
00126     short __dspid = x2h_16(dbh->dat(datid).__dspid());
00127     dbh->dat(datid).__dspid() = h2x_16(dspid | (__dspid & DATTYPE_BITMASK)); 
00128   }
00129 
00130   extern void
00131   setDataspace_inplace(DbHeader *dbh, short datid, short dspid)
00132   {
00133     assert(dbh->__magic() == MAGIC);
00134     dbh->dat(datid).__dspid() = 
00135       (dspid | (dbh->dat(datid).__dspid() & DATTYPE_BITMASK)); 
00136   }
00137 
00138   DatType
00139   getDatType(DbHeader const *dbh, short datid)
00140   {
00141     assert(x2h_u32(dbh->__magic()) == MAGIC);
00142     return (x2h_16(dbh->dat(datid).__dspid()) & DATTYPE_BITMASK)
00143       ? PhysicalOidType : LogicalOidType;
00144   }
00145 
00146   DatType
00147   getDatType_inplace(DbHeader const *dbh, short datid)
00148   {
00149     assert(dbh->__magic() == MAGIC);
00150     return (dbh->dat(datid).__dspid() & DATTYPE_BITMASK)
00151       ? PhysicalOidType : LogicalOidType;
00152   }
00153 
00154   void
00155   setDatType(DbHeader *dbh, short datid, DatType dtype)
00156   {
00157     assert(x2h_u32(dbh->__magic()) == MAGIC);
00158     short dspid = x2h_16(dbh->dat(datid).__dspid());
00159     if (dtype == PhysicalOidType)
00160       dspid |= DATTYPE_BITMASK;
00161     else
00162       dspid &= ~DATTYPE_BITMASK;
00163   
00164     dbh->dat(datid).__dspid() = h2x_16(dspid);
00165   }
00166 
00167   void
00168   setDatType_inplace(DbHeader *dbh, short datid, DatType dtype)
00169   {
00170     assert(dbh->__magic() == MAGIC);
00171     if (dtype == PhysicalOidType)
00172       dbh->dat(datid).__dspid() |= DATTYPE_BITMASK;
00173     else
00174       dbh->dat(datid).__dspid() &= ~DATTYPE_BITMASK;
00175   }
00176 
00177   Status
00178   ESM_datCheck(DbHandle const *dbh, const char *datfile, short *datid,
00179                short *dspid)
00180   {
00181     return get_datid(dbh, datfile, *datid, dspid);
00182   }
00183 
00184   Status
00185   ESM_datMoveObjects(DbHandle const *dbh, const char *dat_src,
00186                      const char *dat_dest)
00187   {
00188     short datid_src, datid_dest;
00189     Status s;
00190 
00191     if (s = get_datid(dbh, dat_src, datid_src))
00192       return s;
00193 
00194     DbHeader _dbh(DBSADDR(dbh));
00195     DatType dtype = getDatType(&_dbh, datid_src);
00196     if (dtype == PhysicalOidType)
00197       return statusMake(ERROR, "cannot move objects within a "
00198                         "physical oid type based datafile");
00199 
00200     if (s = get_datid(dbh, dat_dest, datid_dest))
00201       return s;
00202 
00203     if (datid_src == datid_dest)
00204       return Success;
00205 
00206     Boolean found = False;
00207     Oid oid;
00208 
00209     if (s = ESM_firstOidGet_omp(dbh, &oid, &found))
00210       return s;
00211 
00212     while (found) {
00213       /*
00214         if (s = ESM_objectLock(dbh, &oid, LOCKX, 0, 0))
00215         return s;
00216       */
00217 
00218       OidLoc oidloc = oidLocGet(dbh, &oid);
00219       if (oidloc.datid == datid_src) {
00220         if (s = ESM_objectMoveDatDsp(dbh, &oid, datid_dest, -1, True,
00221                                      OPDefault))
00222           return s;
00223       }
00224       
00225       Oid newoid;
00226       if (s = ESM_nextOidGet_omp(dbh, &oid, &newoid, &found))
00227         return s;
00228       
00229       oid = newoid;
00230     }
00231 
00232     return Success;
00233   }
00234 
00235   Status
00236   ESM_datCreate(DbHandle const *dbh, const char *file, const char *name,
00237                 unsigned long long maxsize, MapType mtype, unsigned int sizeslot,
00238                 DatType dtype, mode_t file_mask, const char *file_group)
00239   {
00240     CHECK_X(dbh, "creating a datafile");
00241 
00242     if (dtype != LogicalOidType &&
00243         dtype != PhysicalOidType)
00244       return statusMake(ERROR, "datafile creation: "
00245                         "invalid datatype %d", dtype);
00246 
00247     DbHeader _dbh(DBSADDR(dbh));
00248     int ndat = x2h_u32(_dbh.__ndat());
00249     short datid;
00250 
00251     for (datid = 0; datid < MAX_DATAFILES; datid++)
00252       if (!isDatValid(dbh, datid))
00253         break;
00254 
00255 #undef PR
00256 #define PR "datCreate: "
00257     if (datid == MAX_DATAFILES)
00258       return statusMake(INVALID_DATAFILE_CNT,
00259                         PR " datafile number too large: `%d'", ndat);
00260 
00261     DbCreateDescription dbc;
00262     strcpy(dbc.dat[datid].name, name);
00263     strcpy(dbc.dat[datid].file, file);
00264     dbc.dat[datid].maxsize = maxsize;
00265     dbc.dat[datid].mtype = mtype;
00266     dbc.dat[datid].sizeslot = sizeslot;
00267     dbc.dat[datid].dtype = dtype;
00268 
00269     mode_t file_mode;
00270     gid_t file_gid;
00271     Status s = getFileMaskGroup(file_mode, file_gid, file_mask, file_group);
00272     if (s)
00273       return s;
00274 
00275     DBFD dbfd;
00276     s = checkDatafile(PR, dbh->dbfile, &_dbh, &dbc,
00277                       datid, &dbfd, file_mode, file_gid, False, 0, True);
00278 
00279     if (s) return s;
00280 
00281     if (datid == ndat) {
00282       ndat++;
00283       _dbh.__ndat() = h2x_u32(ndat);
00284     }
00285 
00286     LASTNSBLKALLOC(dbh, datid) = 0;
00287     return Success;
00288   }
00289 
00290   Status
00291   ESM_datMove(DbHandle const *dbh, const char *datfile, const char *newdatfile,
00292               Boolean force)
00293   {
00294     if (!force) {
00295       CHECK_X(dbh, "moving a datafile");
00296     }
00297 
00298     int fd;
00299     short datid;
00300 
00301     DbHeader _dbh(DBSADDR(dbh));
00302     DbHeader *h = &_dbh;
00303 
00304     int ndat = x2h_u32(h->__ndat());
00305     const char *dbdir = get_dir(dbh->dbfile);
00306     Status s;
00307 
00308     //printf("datMove '%s' '%s'\n", datfile, newdatfile);
00309     /* check if newdatfile already exist */
00310     if ((fd = ::open(newdatfile, O_RDONLY)) >= 0)
00311       {
00312         close(fd);
00313         return statusMake(INVALID_DATAFILE,
00314                           "datafile '%s' already exists", newdatfile);
00315       }
00316 
00317     /* check if datfile is registered */
00318     s = get_datid(dbh, datfile, datid);
00319     if (s) return s;
00320 
00321     /* check extension */
00322     int newdatfile_len = strlen(newdatfile);
00323     if (newdatfile_len <= datext_len ||
00324         strcmp(&newdatfile[newdatfile_len-datext_len], datext))
00325       return statusMake(INVALID_DBFILE,
00326                         "invalid database file extension for `%s' "
00327                         "(must be %s)", newdatfile, datext);
00328 
00329     /* perform rename */
00330     char *from = makefile(dbdir, h->dat(datid).file());
00331     char *to = makefile(dbdir, newdatfile);
00332     if (renamefile(from, to, dbdir, dbdir, 1))
00333       return statusMake(INVALID_DATAFILE,
00334                         "move/operation failed between '%s' and '%s'",
00335                         from, to);
00336           
00337     from = makefile(dbdir, dmpfileGet(h->dat(datid).file()));
00338     to = makefile(dbdir, dmpfileGet(newdatfile));
00339     if (renamefile(from, to, dbdir, dbdir, 1))
00340       return statusMake(INVALID_DATAFILE,
00341                         "move/operation failed between '%s' and '%s'",
00342                         from, to);
00343           
00344     strcpy(h->dat(datid).file(), newdatfile);
00345     return Success;
00346   }
00347 
00348   Status
00349   ESM_datResize(DbHandle const *dbh, const char *datfile,
00350                 unsigned long long newmaxsize)
00351   {
00352     CHECK_X(dbh, "resizing a datafile");
00353 
00354     short datid;
00355     DbHeader _dbh(DBSADDR(dbh));
00356     DbHeader *h = &_dbh;
00357     Status s;
00358 
00359     /* check if datfile is registered */
00360     s = get_datid(dbh, datfile, datid);
00361     if (s) return s;
00362 
00363     /* check newmaxsize */
00364     if ((s = checkVolMaxSize(newmaxsize)))
00365       return s;
00366 
00367     DatafileDesc _dfd = h->dat(datid);
00368     DatafileDesc *dfd = &_dfd;
00369     MapHeader *xmp = dfd->mp();
00370     x2h_prologue(xmp, mp);
00371     unsigned int nslots;
00372 
00373     /* nslots number */
00374     if (mp->mtype() == BitmapType)
00375       {
00376         unsigned int sizeslot = mp->sizeslot();
00377         nslots = KB2SLOT(newmaxsize, mp->pow2());
00378       }
00379     else
00380       nslots = ((unsigned long long)(newmaxsize)*ONE_K)/32;
00381 
00382     /*
00383       if (nslots >= (unsigned long long)MAX_SLOTS)
00384       return statusMake(SIZE_TOO_LARGE, 
00385       "maximum slots `%d' exceeded", MAX_SLOTS);
00386     */
00387 
00388     if (nslots < mp->u_bmh_slot_lastbusy())
00389       return statusMake(INVALID_DATAFILEMAXSIZE,
00390                         "datafile '%s' is partially used: "
00391                         "size can be reduced to a minimum of "
00392                         "'%d' Kbytes or size maybe extended.",
00393                         dfd->file(),
00394                         SLOT2KB(mp->u_bmh_slot_lastbusy(), mp->sizeslot()));
00395 
00396     // should not !!!
00397     // LASTNSBLKALLOC(dbh, datid) = 0;
00398 
00399     dfd->__maxsize() = h2x_u32(newmaxsize);
00400 
00401     // EV: 31/01/07: must not swap as it is swapped in h2x_epilogue
00402     //mp->nslots() = h2x_u32(nslots);
00403     mp->nslots() = nslots;
00404 
00405     h2x_epilogue(xmp, mp);
00406 
00407     return Success;
00408   }
00409 
00410   static const char *
00411   get_dspname(DbHeader *h, short dspid)
00412   {
00413     const char *name = h->dsp(dspid).name();
00414     if (*name) return name;
00415     static char strname[16];
00416     sprintf(strname, "#%d", dspid);
00417     return strname;
00418   }
00419 
00420   Status
00421   ESM_datDelete(DbHandle const *dbh, const char *datfile, Boolean force)
00422   {
00423     if (!force) {
00424       CHECK_X(dbh, "deleting a datafile");
00425     }
00426 
00427     short datid;
00428     DbHeader _dbh(DBSADDR(dbh));
00429     DbHeader *h = &_dbh;
00430 
00431     Status s;
00432 
00433     /* check if datfile is registered */
00434     s = get_datid(dbh, datfile, datid);
00435     if (s) return s;
00436 
00437     DatafileDesc _dfd = h->dat(datid);
00438     DatafileDesc *dfd = &_dfd;
00439 
00440     short dspid = getDataspace(h, datid);
00441     if (!force && dspid != DefaultDspid)
00442       return statusMake(ERROR, "datafile '%s' is part of the dataspace "
00443                         "'%s': cannot be deleted",
00444                         datfile, get_dspname(h, dspid));
00445 
00446     MapHeader *mp = dfd->mp();
00447 
00448     if (!force && x2h_u32(mp->mstat_u_bmstat_busy_slots()))
00449       return statusMake(ERROR, "datafile '%s' is partially used: cannot "
00450                         "be deleted", datfile);
00451 
00452     char pwd[DEFAULT_PWD_SIZE];
00453     s = push_dir(dbh->dbfile, pwd, sizeof pwd);
00454     if (s) return s;
00455 
00456     unlink(dfd->file());
00457     unlink(dmpfileGet(dfd->file()));
00458 
00459     *h->dat(datid).file() = 0;
00460 
00461     s = pop_dir(pwd);
00462     if (s) return s;
00463 
00464     memset(dfd, 0, sizeof(*dfd));
00465     close(dbh->vd->dmd[datid].fd);
00466     dbh->vd->dmd[datid].fd = -1;
00467     unsigned int ndat = x2h_u32(h->__ndat());
00468     if (datid == ndat - 1) {
00469       ndat--;
00470       h->__ndat() = h2x_u32(ndat);
00471     }
00472 
00473     return Success;
00474   }
00475 
00476   static const char *
00477   get_tmp_datfile(const char *datfile)
00478   {
00479     static char tmp_datfile[512];
00480 
00481     const char *dir = get_dir(datfile);
00482     *tmp_datfile = 0;
00483 
00484     if (*dir)
00485       {
00486         strcat(tmp_datfile, dir);
00487         strcat(tmp_datfile, "/");
00488       }
00489 
00490     strcat(tmp_datfile, "__##__");
00491 
00492     const char *p = strrchr(datfile, '/');
00493     if (p)
00494       strcat(tmp_datfile, p+1);
00495     else
00496       strcat(tmp_datfile, datfile);
00497 
00498     return tmp_datfile;
00499   }
00500 
00501   Status
00502   ESM_datRename(DbHandle const *dbh, const char *datfile, const char *name)
00503   {
00504     CHECK_X(dbh, "renaming a datafile");
00505 
00506     short datid;
00507     Status s = get_datid(dbh, datfile, datid);
00508     if (s) return s;
00509 
00510     DbHeader _dbh(DBSADDR(dbh));
00511     s = checkNewDatafile(&_dbh, "", name);
00512     if (s) return s;
00513 
00514     strcpy(_dbh.dat(datid).name(), name);
00515 
00516     return Success;
00517   }
00518 
00519   Status
00520   ESM_datResetCurSlot(DbHandle const *dbh, const char *datfile)
00521   {
00522     CHECK_X(dbh, "reseting datafile current slot");
00523 
00524     short datid;
00525     Status s;
00526 
00527     /* check if datfile is registered */
00528     s = get_datid(dbh, datfile, datid);
00529     if (s) return s;
00530 
00531     DbHeader _dbh(DBSADDR(dbh));
00532     _dbh.dat(datid).mp()->u_bmh_slot_cur() = 0;
00533     
00534     return Success;
00535   }
00536 
00537   Status
00538   ESM_datDefragment(DbHandle const *dbh, const char *datfile, mode_t file_mask, const char *file_group)
00539   {
00540     CHECK_X(dbh, "defragmenting a datafile");
00541 
00542     short datid;
00543     DbHeader _dbh(DBSADDR(dbh));
00544     DbHeader *h = &_dbh;
00545 
00546     Status s;
00547 
00548     /* check if datfile is registered */
00549     s = get_datid(dbh, datfile, datid);
00550     if (s)
00551       return s;
00552 
00553     DatType dtype = getDatType(&_dbh, datid);
00554     if (dtype == PhysicalOidType)
00555       return statusMake(ERROR, "cannot defragment a physical oid type "
00556                         "based datafile");
00557 
00558     DatafileDesc _dfd = h->dat(datid);
00559     DatafileDesc *dfd = &_dfd;
00560     const MapHeader *mp = dfd->mp();
00561 
00562     const char *tmp_datfile = get_tmp_datfile(dfd->file());
00563 
00564     if (s = ESM_datCreate(dbh, tmp_datfile, "",
00565                           x2h_u32(dfd->__maxsize()),
00566                           (MapType)x2h_u16(mp->mtype()),
00567                           x2h_u32(mp->sizeslot()),
00568                           dtype, file_mask, file_group))
00569       return s;
00570 
00571     DbHandle *dbh_n;
00572     if (s = ESM_dbOpen(dbh->dbfile, VOLRW, 0, 0, 0, 0, 0, 0, &dbh_n)) {
00573       (void)ESM_datDelete(dbh, tmp_datfile, True);
00574       return s;
00575     }
00576 
00577     short tmp_datid;
00578     s = get_datid(dbh_n, tmp_datfile, tmp_datid);
00579 
00580     if (s) {
00581       (void)ESM_datDelete(dbh, tmp_datfile, True);
00582       return s;
00583     }
00584 
00585     if (s = ESM_datMoveObjects(dbh_n, datfile, tmp_datfile))
00586       return s;
00587 
00588     char *datfile_keep = strdup(dfd->file());
00589     char *datname_keep = strdup(dfd->name());
00590 
00591     if (s = ESM_datDelete(dbh_n, datfile, True)) {
00592       free(datfile_keep);
00593       free(datname_keep);
00594       return s;
00595     }
00596 
00597     if (s = ESM_datMove(dbh_n, tmp_datfile, datfile_keep, True)) {
00598       free(datfile_keep);
00599       free(datname_keep);
00600       return s;
00601     }
00602 
00603     DbHeader _dbh_n(DBSADDR(dbh_n));
00604     
00605     DatafileDesc dat = _dbh_n.dat(datid);
00606     DatafileDesc tmp_dat = _dbh_n.dat(tmp_datid);
00607 
00608     _dbh_n.dat(datid).mp()->u_bmh_slot_cur() = 0; // added 20/09/07
00609 
00610     _dbh_n.dat(datid).__lastslot() = _dbh_n.dat(tmp_datid).__lastslot();
00611     _dbh_n.dat(datid).__maxsize() = _dbh_n.dat(tmp_datid).__maxsize();
00612 
00613     // ABSOLUTELY WRONG: _dbh_n.dat(datid) will be freed after the expression,
00614     // so dmp and smp will not been available after this expression !!!
00615     /*
00616     MapHeader *dmp = _dbh_n.dat(datid).mp();
00617     MapHeader *smp = _dbh_n.dat(tmp_datid).mp();
00618     */
00619 
00620     MapHeader *dmp = dat.mp();
00621     MapHeader *smp = tmp_dat.mp();
00622 
00623 #ifdef TRACE
00624     NS nns = _dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots();
00625         
00626     std::cerr << "eyedbsm: before busy slots " <<
00627       _dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots() <<
00628       " " <<
00629       nns <<
00630       " " <<
00631       x2h_u32(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots()) <<
00632       " " <<
00633       dmp->mstat_u_bmstat_busy_slots() <<
00634       " " <<
00635       x2h_u32(dmp->mstat_u_bmstat_busy_slots()) << '\n';
00636 
00637     std::cerr << "eyedbsm: before busy size " <<
00638       x2h_u64(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_size()) <<
00639       " " <<
00640       x2h_u64(dmp->mstat_u_bmstat_busy_size()) << '\n';
00641 #endif
00642 
00643 #if 1
00644     //    printf("dmp->_addr() %p smp->_addr() %p\n", dmp->_addr(), smp->_addr());
00645     memcpy(dmp->_addr(), smp->_addr(), MapHeader_SIZE);
00646 #else
00647     dmp->mtype() = smp->mtype();
00648     dmp->sizeslot() = smp->sizeslot();
00649     dmp->pow2() = smp->pow2();
00650     dmp->nslots() = smp->nslots();
00651     dmp->nbobjs() = smp->nbobjs();
00652     dmp->mstat_mtype() = smp->mstat_mtype();
00653  
00654     dmp->u_bmh_slot_cur() = smp->u_bmh_slot_cur();
00655     dmp->u_bmh_slot_lastbusy() = smp->u_bmh_slot_lastbusy();
00656     dmp->u_bmh_retry() = smp->u_bmh_retry();
00657  
00658     dmp->mstat_u_bmstat_obj_count() = smp->mstat_u_bmstat_obj_count();
00659     dmp->mstat_u_bmstat_busy_slots() = smp->mstat_u_bmstat_busy_slots();
00660     dmp->mstat_u_bmstat_busy_size() = smp->mstat_u_bmstat_busy_size();
00661     dmp->mstat_u_bmstat_hole_size() = smp->mstat_u_bmstat_hole_size();
00662 #endif
00663 
00664 #ifdef TRACE
00665     std::cerr << "eyedbsm: after busy slots " <<
00666       x2h_u32(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots()) <<
00667       " " <<
00668       x2h_u32(dmp->mstat_u_bmstat_busy_slots()) << '\n';
00669 
00670     std::cerr << "eyedbsm: after busy size " <<
00671       x2h_u64(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_size()) <<
00672       " " <<
00673       x2h_u64(dmp->mstat_u_bmstat_busy_size()) << '\n';
00674 
00675     std::cerr << "eyedbsm: defragment dataid " <<  datid << " "  << tmp_datid << '\n';
00676 
00677     std::cerr << "eyedbsm: tmp busy slots " <<
00678       x2h_u32(_dbh_n.dat(tmp_datid).mp()->mstat_u_bmstat_busy_slots()) <<
00679       " " <<
00680       x2h_u32(smp->mstat_u_bmstat_busy_slots()) << '\n';
00681 
00682     std::cerr << "eyedbsm: tmp busy size " <<
00683       x2h_u64(_dbh_n.dat(tmp_datid).mp()->mstat_u_bmstat_busy_size()) <<
00684       " " <<
00685       x2h_u64(smp->mstat_u_bmstat_busy_size()) << '\n';
00686 
00687     if (dmp->mstat_u_bmstat_busy_slots() != smp->mstat_u_bmstat_busy_slots()) {
00688       abort();
00689     }
00690 #endif
00691 
00692     strcpy(_dbh_n.dat(datid).file(), datfile_keep);
00693     strcpy(_dbh_n.dat(datid).name(), datname_keep);
00694     *_dbh_n.dat(tmp_datid).file() = 0;
00695     *_dbh_n.dat(tmp_datid).name() = 0;
00696 
00697     // added the 20/03/02
00698     LASTNSBLKALLOC(dbh_n, datid) = LASTNSBLKALLOC(dbh_n, tmp_datid);
00699 
00700     unsigned int ndat = x2h_u32(_dbh_n.__ndat());
00701     if (tmp_datid == ndat - 1) {
00702       ndat--;
00703       _dbh_n.__ndat() = h2x_u32(ndat);
00704     }
00705 
00706     ESM_dbClose(dbh_n);
00707 
00708     free(datfile_keep);
00709     free(datname_keep);
00710     return Success;
00711   }
00712 
00713   static void
00714   ESM_datGetFragmentation(DbHandle const *dbh, MapHeader *mp, short datid,
00715                           unsigned int &nfrags)
00716   {
00717     char *mapaddr = dbh->vd->dmp_addr[datid];
00718     char *s, *start, *end;
00719     int nbusy, ns;
00720 
00721     start = mapaddr;
00722     end = mapaddr + (mp->u_bmh_slot_lastbusy() / 8);
00723     nfrags = 0;
00724     ns = 0;
00725 
00726     for (s = start; s <= end; s++)
00727       {
00728         char v = *s;
00729         int b;
00730 
00731         for (b = 7; b >= 0; b--, ns++)
00732           {
00733             if (!(v & (1 << b)))
00734               nfrags++;
00735 
00736             if (ns >= mp->u_bmh_slot_lastbusy())
00737               break;
00738           }
00739       }
00740 
00741     if (nfrags > mp->u_bmh_slot_lastbusy())
00742       nfrags = mp->u_bmh_slot_lastbusy();
00743   }     
00744 
00745   Status
00746   ESM_datGetDspid(DbHandle const *dbh, short datid, short *dspid)
00747   {
00748     if (!isDatValid(dbh, datid))
00749       return statusMake(INVALID_DATAFILE, "datafile #%d not found",
00750                         datid);
00751     DbHeader _dbh(DBSADDR(dbh));
00752     *dspid = getDataspace(&_dbh, datid);
00753     return Success;
00754   }
00755 
00756   Status
00757   ESM_datGetInfo(DbHandle const *dbh, const char *datfile, DatafileInfo *info)
00758   {
00759     short datid;
00760     Status s;
00761 
00762     /* check if datfile is registered */
00763     s = get_datid(dbh, datfile, datid);
00764     if (s) return s;
00765 
00766     DbHeader _dbh(DBSADDR(dbh));
00767     DbHeader *h = &_dbh;
00768 
00769     DatafileDesc _dat = h->dat(datid);
00770     DatafileDesc *dat = &_dat;
00771     const MapHeader *xmp = dat->mp();
00772     x2h_prologue(xmp, mp);
00773 
00774     char pwd[DEFAULT_PWD_SIZE];
00775     s = push_dir(dbh->dbfile, pwd, sizeof pwd);
00776     if (s) return s;
00777 
00778     strcpy(info->datafile.file, dat->file());
00779     strcpy(info->datafile.name, dat->name());
00780     info->datid = datid;
00781     info->datafile.dspid = getDataspace(&_dbh, datid);
00782     info->datafile.maxsize = x2h_u32(dat->__maxsize());
00783     info->datafile.mtype = mp->mtype();
00784     info->datafile.sizeslot = mp->sizeslot();
00785     info->slotcnt = mp->nslots();
00786     info->objcnt = mp->mstat_u_bmstat_obj_count();
00787     info->totalsize = mp->mstat_u_bmstat_busy_size();
00788     info->avgsize = (mp->mstat_u_bmstat_obj_count() ?
00789                      mp->mstat_u_bmstat_busy_size()/mp->mstat_u_bmstat_obj_count() : 0);
00790 
00791     info->busyslotcnt = mp->mstat_u_bmstat_busy_slots();
00792     info->lastbusyslot = mp->u_bmh_slot_lastbusy();
00793     info->lastslot = x2h_u32(dat->__lastslot());
00794     info->busyslotsize = (unsigned long long)mp->mstat_u_bmstat_busy_slots() * mp->sizeslot();
00795     s = fileSizesGet(dat->file(),
00796                      info->datfilesize, info->datfileblksize);
00797     if (s) {pop_dir(pwd); return s;}
00798 
00799     s = fileSizesGet(dmpfileGet(dat->file()),
00800                      info->dmpfilesize, info->dmpfileblksize);
00801     pop_dir(pwd);
00802     if (s) return s;
00803 
00804     //info->totafilesize = (unsigned long long)mp->u_bmh_slot_lastbusy * mp->sizeslot;
00805 
00806     info->curslot = mp->u_bmh_slot_cur();
00807     if (!mp->u_bmh_slot_cur())
00808       info->defragmentablesize = 0;
00809     else
00810       info->defragmentablesize = (((unsigned long long)mp->u_bmh_slot_lastbusy()+1 - mp->mstat_u_bmstat_busy_slots()) * mp->sizeslot());
00811 
00812     // 22/08/01: it is not necessary to compute fragmentation with
00813     // ESM_datGetFragmentation
00814     //ESM_datGetFragmentation(dbh, mp, datid, info->slotfragcnt);
00815     // instead:
00816     info->slotfragcnt = info->defragmentablesize / mp->sizeslot();
00817 
00818     //printf("stats : mp->nslots %d\n", mp->nslots);
00819     info->used = ((double)mp->mstat_u_bmstat_busy_slots()/(double)mp->nslots())*100.;
00820 
00821     return Success;
00822   }
00823 }

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