00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00215
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
00309
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
00318 s = get_datid(dbh, datfile, datid);
00319 if (s) return s;
00320
00321
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
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
00360 s = get_datid(dbh, datfile, datid);
00361 if (s) return s;
00362
00363
00364 if ((s = checkVolMaxSize(newmaxsize))) {
00365 return s;
00366 }
00367
00368 DatafileDesc _dfd = h->dat(datid);
00369 DatafileDesc *dfd = &_dfd;
00370 MapHeader *xmp = dfd->mp();
00371 x2h_prologue(xmp, mp);
00372 unsigned long long nslots_l;
00373
00374
00375 if (mp->mtype() == BitmapType) {
00376 unsigned int sizeslot = mp->sizeslot();
00377 nslots_l = KB2SLOT(newmaxsize, mp->pow2());
00378 }
00379 else {
00380 nslots_l = ((unsigned long long)(newmaxsize)*ONE_K)/32;
00381 }
00382
00383 #if 0
00384 std::cout << "nslots_l: " << nslots_l << " (unsigned int)" << (unsigned int)nslots_l <<
00385 " pow2: " << mp->pow2() << " newmaxsize: " << newmaxsize << '\n';
00386 std::cout << "lastbusy: " << mp->u_bmh_slot_lastbusy() << '\n';
00387 #endif
00388
00389 if (s = checkDatafileSize(nslots_l, dfd->file(), mp->sizeslot(), newmaxsize)) {
00390 return s;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 unsigned int nslots = (unsigned int)nslots_l;
00405 if (nslots < mp->u_bmh_slot_lastbusy()) {
00406 return statusMake(INVALID_DATAFILEMAXSIZE,
00407 "datafile %s is partially used: "
00408 "size can be reduced to a size of %u MB",
00409 dfd->file(),
00410 SLOT2KB(mp->u_bmh_slot_lastbusy(), mp->sizeslot())/ONE_K);
00411 }
00412
00413
00414
00415
00416 dfd->__maxsize() = h2x_u32(newmaxsize);
00417
00418
00419
00420 mp->nslots() = nslots;
00421
00422 h2x_epilogue(xmp, mp);
00423
00424 return Success;
00425 }
00426
00427 static const char *
00428 get_dspname(DbHeader *h, short dspid)
00429 {
00430 const char *name = h->dsp(dspid).name();
00431 if (*name) return name;
00432 static char strname[16];
00433 sprintf(strname, "#%d", dspid);
00434 return strname;
00435 }
00436
00437 Status
00438 ESM_datDelete(DbHandle const *dbh, const char *datfile, Boolean force)
00439 {
00440 if (!force) {
00441 CHECK_X(dbh, "deleting a datafile");
00442 }
00443
00444 short datid;
00445 DbHeader _dbh(DBSADDR(dbh));
00446 DbHeader *h = &_dbh;
00447
00448 Status s;
00449
00450
00451 s = get_datid(dbh, datfile, datid);
00452 if (s) return s;
00453
00454 DatafileDesc _dfd = h->dat(datid);
00455 DatafileDesc *dfd = &_dfd;
00456
00457 short dspid = getDataspace(h, datid);
00458 if (!force && dspid != DefaultDspid)
00459 return statusMake(ERROR, "datafile '%s' is part of the dataspace "
00460 "'%s': cannot be deleted",
00461 datfile, get_dspname(h, dspid));
00462
00463 MapHeader *mp = dfd->mp();
00464
00465 if (!force && x2h_u32(mp->mstat_u_bmstat_busy_slots()))
00466 return statusMake(ERROR, "datafile '%s' is partially used: cannot "
00467 "be deleted", datfile);
00468
00469 char pwd[DEFAULT_PWD_SIZE];
00470 s = push_dir(dbh->dbfile, pwd, sizeof pwd);
00471 if (s) return s;
00472
00473 unlink(dfd->file());
00474 unlink(dmpfileGet(dfd->file()));
00475
00476 *h->dat(datid).file() = 0;
00477
00478 s = pop_dir(pwd);
00479 if (s) return s;
00480
00481 memset(dfd, 0, sizeof(*dfd));
00482 close(dbh->vd->dmd[datid].fd);
00483 dbh->vd->dmd[datid].fd = -1;
00484 unsigned int ndat = x2h_u32(h->__ndat());
00485 if (datid == ndat - 1) {
00486 ndat--;
00487 h->__ndat() = h2x_u32(ndat);
00488 }
00489
00490 return Success;
00491 }
00492
00493 static const char *
00494 get_tmp_datfile(const char *datfile)
00495 {
00496 static char tmp_datfile[512];
00497
00498 const char *dir = get_dir(datfile);
00499 *tmp_datfile = 0;
00500
00501 if (*dir)
00502 {
00503 strcat(tmp_datfile, dir);
00504 strcat(tmp_datfile, "/");
00505 }
00506
00507 strcat(tmp_datfile, "__##__");
00508
00509 const char *p = strrchr(datfile, '/');
00510 if (p)
00511 strcat(tmp_datfile, p+1);
00512 else
00513 strcat(tmp_datfile, datfile);
00514
00515 return tmp_datfile;
00516 }
00517
00518 Status
00519 ESM_datRename(DbHandle const *dbh, const char *datfile, const char *name)
00520 {
00521 CHECK_X(dbh, "renaming a datafile");
00522
00523 short datid;
00524 Status s = get_datid(dbh, datfile, datid);
00525 if (s) return s;
00526
00527 DbHeader _dbh(DBSADDR(dbh));
00528 s = checkNewDatafile(&_dbh, "", name);
00529 if (s) return s;
00530
00531 strcpy(_dbh.dat(datid).name(), name);
00532
00533 return Success;
00534 }
00535
00536 Status
00537 ESM_datResetCurSlot(DbHandle const *dbh, const char *datfile)
00538 {
00539 CHECK_X(dbh, "reseting datafile current slot");
00540
00541 short datid;
00542 Status s;
00543
00544
00545 s = get_datid(dbh, datfile, datid);
00546 if (s) return s;
00547
00548 DbHeader _dbh(DBSADDR(dbh));
00549 _dbh.dat(datid).mp()->u_bmh_slot_cur() = 0;
00550
00551 return Success;
00552 }
00553
00554 Status
00555 ESM_datDefragment(DbHandle const *dbh, const char *datfile, mode_t file_mask, const char *file_group)
00556 {
00557 CHECK_X(dbh, "defragmenting a datafile");
00558
00559 short datid;
00560 DbHeader _dbh(DBSADDR(dbh));
00561 DbHeader *h = &_dbh;
00562
00563 Status s;
00564
00565
00566 s = get_datid(dbh, datfile, datid);
00567 if (s)
00568 return s;
00569
00570 DatType dtype = getDatType(&_dbh, datid);
00571 if (dtype == PhysicalOidType)
00572 return statusMake(ERROR, "cannot defragment a physical oid type "
00573 "based datafile");
00574
00575 DatafileDesc _dfd = h->dat(datid);
00576 DatafileDesc *dfd = &_dfd;
00577 const MapHeader *mp = dfd->mp();
00578
00579 const char *tmp_datfile = get_tmp_datfile(dfd->file());
00580
00581 if (s = ESM_datCreate(dbh, tmp_datfile, "",
00582 x2h_u32(dfd->__maxsize()),
00583 (MapType)x2h_u16(mp->mtype()),
00584 x2h_u32(mp->sizeslot()),
00585 dtype, file_mask, file_group))
00586 return s;
00587
00588 DbHandle *dbh_n;
00589 if (s = ESM_dbOpen(dbh->dbfile, VOLRW, 0, 0, 0, 0, 0, 0, &dbh_n)) {
00590 (void)ESM_datDelete(dbh, tmp_datfile, True);
00591 return s;
00592 }
00593
00594 short tmp_datid;
00595 s = get_datid(dbh_n, tmp_datfile, tmp_datid);
00596
00597 if (s) {
00598 (void)ESM_datDelete(dbh, tmp_datfile, True);
00599 return s;
00600 }
00601
00602 if (s = ESM_datMoveObjects(dbh_n, datfile, tmp_datfile))
00603 return s;
00604
00605 char *datfile_keep = strdup(dfd->file());
00606 char *datname_keep = strdup(dfd->name());
00607
00608 if (s = ESM_datDelete(dbh_n, datfile, True)) {
00609 free(datfile_keep);
00610 free(datname_keep);
00611 return s;
00612 }
00613
00614 if (s = ESM_datMove(dbh_n, tmp_datfile, datfile_keep, True)) {
00615 free(datfile_keep);
00616 free(datname_keep);
00617 return s;
00618 }
00619
00620 DbHeader _dbh_n(DBSADDR(dbh_n));
00621
00622 DatafileDesc dat = _dbh_n.dat(datid);
00623 DatafileDesc tmp_dat = _dbh_n.dat(tmp_datid);
00624
00625 _dbh_n.dat(datid).mp()->u_bmh_slot_cur() = 0;
00626
00627 _dbh_n.dat(datid).__lastslot() = _dbh_n.dat(tmp_datid).__lastslot();
00628 _dbh_n.dat(datid).__maxsize() = _dbh_n.dat(tmp_datid).__maxsize();
00629
00630
00631
00632
00633
00634
00635
00636
00637 MapHeader *dmp = dat.mp();
00638 MapHeader *smp = tmp_dat.mp();
00639
00640 #ifdef TRACE
00641 NS nns = _dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots();
00642
00643 std::cerr << "eyedbsm: before busy slots " <<
00644 _dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots() <<
00645 " " <<
00646 nns <<
00647 " " <<
00648 x2h_u32(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots()) <<
00649 " " <<
00650 dmp->mstat_u_bmstat_busy_slots() <<
00651 " " <<
00652 x2h_u32(dmp->mstat_u_bmstat_busy_slots()) << '\n';
00653
00654 std::cerr << "eyedbsm: before busy size " <<
00655 x2h_u64(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_size()) <<
00656 " " <<
00657 x2h_u64(dmp->mstat_u_bmstat_busy_size()) << '\n';
00658 #endif
00659
00660 #if 1
00661
00662 memcpy(dmp->_addr(), smp->_addr(), MapHeader_SIZE);
00663 #else
00664 dmp->mtype() = smp->mtype();
00665 dmp->sizeslot() = smp->sizeslot();
00666 dmp->pow2() = smp->pow2();
00667 dmp->nslots() = smp->nslots();
00668 dmp->nbobjs() = smp->nbobjs();
00669 dmp->mstat_mtype() = smp->mstat_mtype();
00670
00671 dmp->u_bmh_slot_cur() = smp->u_bmh_slot_cur();
00672 dmp->u_bmh_slot_lastbusy() = smp->u_bmh_slot_lastbusy();
00673 dmp->u_bmh_retry() = smp->u_bmh_retry();
00674
00675 dmp->mstat_u_bmstat_obj_count() = smp->mstat_u_bmstat_obj_count();
00676 dmp->mstat_u_bmstat_busy_slots() = smp->mstat_u_bmstat_busy_slots();
00677 dmp->mstat_u_bmstat_busy_size() = smp->mstat_u_bmstat_busy_size();
00678 dmp->mstat_u_bmstat_hole_size() = smp->mstat_u_bmstat_hole_size();
00679 #endif
00680
00681 #ifdef TRACE
00682 std::cerr << "eyedbsm: after busy slots " <<
00683 x2h_u32(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_slots()) <<
00684 " " <<
00685 x2h_u32(dmp->mstat_u_bmstat_busy_slots()) << '\n';
00686
00687 std::cerr << "eyedbsm: after busy size " <<
00688 x2h_u64(_dbh_n.dat(datid).mp()->mstat_u_bmstat_busy_size()) <<
00689 " " <<
00690 x2h_u64(dmp->mstat_u_bmstat_busy_size()) << '\n';
00691
00692 std::cerr << "eyedbsm: defragment dataid " << datid << " " << tmp_datid << '\n';
00693
00694 std::cerr << "eyedbsm: tmp busy slots " <<
00695 x2h_u32(_dbh_n.dat(tmp_datid).mp()->mstat_u_bmstat_busy_slots()) <<
00696 " " <<
00697 x2h_u32(smp->mstat_u_bmstat_busy_slots()) << '\n';
00698
00699 std::cerr << "eyedbsm: tmp busy size " <<
00700 x2h_u64(_dbh_n.dat(tmp_datid).mp()->mstat_u_bmstat_busy_size()) <<
00701 " " <<
00702 x2h_u64(smp->mstat_u_bmstat_busy_size()) << '\n';
00703
00704 if (dmp->mstat_u_bmstat_busy_slots() != smp->mstat_u_bmstat_busy_slots()) {
00705 abort();
00706 }
00707 #endif
00708
00709 strcpy(_dbh_n.dat(datid).file(), datfile_keep);
00710 strcpy(_dbh_n.dat(datid).name(), datname_keep);
00711 *_dbh_n.dat(tmp_datid).file() = 0;
00712 *_dbh_n.dat(tmp_datid).name() = 0;
00713
00714
00715 LASTNSBLKALLOC(dbh_n, datid) = LASTNSBLKALLOC(dbh_n, tmp_datid);
00716
00717 unsigned int ndat = x2h_u32(_dbh_n.__ndat());
00718 if (tmp_datid == ndat - 1) {
00719 ndat--;
00720 _dbh_n.__ndat() = h2x_u32(ndat);
00721 }
00722
00723 ESM_dbClose(dbh_n);
00724
00725 free(datfile_keep);
00726 free(datname_keep);
00727 return Success;
00728 }
00729
00730 static void
00731 ESM_datGetFragmentation(DbHandle const *dbh, MapHeader *mp, short datid,
00732 unsigned int &nfrags)
00733 {
00734 char *mapaddr = dbh->vd->dmp_addr[datid];
00735 char *s, *start, *end;
00736 int nbusy, ns;
00737
00738 start = mapaddr;
00739 end = mapaddr + (mp->u_bmh_slot_lastbusy() / 8);
00740 nfrags = 0;
00741 ns = 0;
00742
00743 for (s = start; s <= end; s++)
00744 {
00745 char v = *s;
00746 int b;
00747
00748 for (b = 7; b >= 0; b--, ns++)
00749 {
00750 if (!(v & (1 << b)))
00751 nfrags++;
00752
00753 if (ns >= mp->u_bmh_slot_lastbusy())
00754 break;
00755 }
00756 }
00757
00758 if (nfrags > mp->u_bmh_slot_lastbusy())
00759 nfrags = mp->u_bmh_slot_lastbusy();
00760 }
00761
00762 Status
00763 ESM_datGetDspid(DbHandle const *dbh, short datid, short *dspid)
00764 {
00765 if (!isDatValid(dbh, datid))
00766 return statusMake(INVALID_DATAFILE, "datafile #%d not found",
00767 datid);
00768 DbHeader _dbh(DBSADDR(dbh));
00769 *dspid = getDataspace(&_dbh, datid);
00770 return Success;
00771 }
00772
00773 Status
00774 ESM_datGetInfo(DbHandle const *dbh, const char *datfile, DatafileInfo *info)
00775 {
00776 short datid;
00777 Status s;
00778
00779
00780 s = get_datid(dbh, datfile, datid);
00781 if (s) return s;
00782
00783 DbHeader _dbh(DBSADDR(dbh));
00784 DbHeader *h = &_dbh;
00785
00786 DatafileDesc _dat = h->dat(datid);
00787 DatafileDesc *dat = &_dat;
00788 const MapHeader *xmp = dat->mp();
00789 x2h_prologue(xmp, mp);
00790
00791 char pwd[DEFAULT_PWD_SIZE];
00792 s = push_dir(dbh->dbfile, pwd, sizeof pwd);
00793 if (s) return s;
00794
00795 strcpy(info->datafile.file, dat->file());
00796 strcpy(info->datafile.name, dat->name());
00797 info->datid = datid;
00798 info->datafile.dspid = getDataspace(&_dbh, datid);
00799 info->datafile.maxsize = x2h_u32(dat->__maxsize());
00800 info->datafile.mtype = mp->mtype();
00801 info->datafile.sizeslot = mp->sizeslot();
00802 info->slotcnt = mp->nslots();
00803 info->objcnt = mp->mstat_u_bmstat_obj_count();
00804 info->totalsize = mp->mstat_u_bmstat_busy_size();
00805 info->avgsize = (mp->mstat_u_bmstat_obj_count() ?
00806 mp->mstat_u_bmstat_busy_size()/mp->mstat_u_bmstat_obj_count() : 0);
00807
00808 info->busyslotcnt = mp->mstat_u_bmstat_busy_slots();
00809 info->lastbusyslot = mp->u_bmh_slot_lastbusy();
00810 info->lastslot = x2h_u32(dat->__lastslot());
00811 info->busyslotsize = (unsigned long long)mp->mstat_u_bmstat_busy_slots() * mp->sizeslot();
00812 s = fileSizesGet(dat->file(),
00813 info->datfilesize, info->datfileblksize);
00814 if (s) {pop_dir(pwd); return s;}
00815
00816 s = fileSizesGet(dmpfileGet(dat->file()),
00817 info->dmpfilesize, info->dmpfileblksize);
00818 pop_dir(pwd);
00819 if (s) return s;
00820
00821
00822
00823 info->curslot = mp->u_bmh_slot_cur();
00824 if (!mp->u_bmh_slot_cur())
00825 info->defragmentablesize = 0;
00826 else
00827 info->defragmentablesize = (((unsigned long long)mp->u_bmh_slot_lastbusy()+1 - mp->mstat_u_bmstat_busy_slots()) * mp->sizeslot());
00828
00829
00830
00831
00832
00833 info->slotfragcnt = info->defragmentablesize / mp->sizeslot();
00834
00835
00836 info->used = ((double)mp->mstat_u_bmstat_busy_slots()/(double)mp->nslots())*100.;
00837
00838 return Success;
00839 }
00840 }