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 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
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
00384
00385
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
00397
00398
00399 dfd->__maxsize() = h2x_u32(newmaxsize);
00400
00401
00402
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
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
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
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;
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
00614
00615
00616
00617
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
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
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
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
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
00813
00814
00815
00816 info->slotfragcnt = info->defragmentablesize / mp->sizeslot();
00817
00818
00819 info->used = ((double)mp->mstat_u_bmstat_busy_slots()/(double)mp->nslots())*100.;
00820
00821 return Success;
00822 }
00823 }