00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "eyedbconfig.h"
00036
00037 #include <iostream>
00038 #include <sys/types.h>
00039 #include <grp.h>
00040
00041 #include "eyedblib/filelib.h"
00042 #include "eyedblib/rpc_lib.h"
00043 #include "kern_p.h"
00044 #include <eyedbsm/smd.h>
00045 #include <map>
00046 #include "lib/compile_builtin.h"
00047
00048 static const char defDsp[] = "DEFAULT";
00049
00050
00051
00052
00053 namespace eyedbsm {
00054 unsigned long curref;
00055 const void *ObjectZero = 0, *ObjectNone = (void *)-1;
00056 Boolean backend_interrupt = False;
00057 Boolean backend = False;
00058 unsigned int import_xid;
00059 const int INVALID = -1;
00060
00061
00062
00063 #define SHM_DEFSIZE 0x4000000
00064
00065 #define DBS_DEFSIZE (size_t)DbHeader_SIZE
00066 #define OIDMAP_SIZE(NOBJS) \
00067 (((((unsigned long long)NOBJS * OIDLOCSIZE) / pgsize) + 1) * pgsize)
00068
00069 #define ALIGN4(x) \
00070 x = (u_long *)(((u_long)(x)&0x3) ? ((u_long)(x) + 0x4-((u_long)(x)&0x3)) : (u_long)x)
00071
00072
00073 #define ESM_DEF_NBOBJS 100000000
00074 #define MAXTRIES 0
00075
00076 const char ompext[] = ".omp";
00077 const char shmext[] = ".shm";
00078 const char dbsext[] = ".dbs";
00079 const char datext[] = ".dat";
00080 const char dmpext[] = ".dmp";
00081
00082 int dbsext_len = 4;
00083 int datext_len = 4;
00084
00085 static Status
00086 dbCleanupRealize(const char *shmfile, int sm_fdshm);
00087
00088 static Status
00089 dbcreate_error(Status status, const char *dbfile,
00090 const DbCreateDescription *dbc, int n, DBFD *dbfd)
00091 {
00092 char pwd[DEFAULT_PWD_SIZE];
00093 push_dir(dbfile, pwd, sizeof pwd);
00094
00095 unlink(dbfile);
00096 unlink(objmapfileGet(dbfile));
00097 unlink(shmfileGet(dbfile));
00098
00099 close(dbfd->dbsfd);
00100 close(dbfd->ompfd);
00101 close(dbfd->shmfd);
00102
00103 for (int j = 0; j < n; j++) {
00104 unlink(dbc->dat[j].file);
00105 unlink(dmpfileGet(dbc->dat[j].file));
00106 close(dbfd->fd_dat[j]);
00107 close(dbfd->fd_dmp[j]);
00108 }
00109
00110 pop_dir(pwd);
00111 return status;
00112 }
00113
00114 static int fileCreate(const char *file, mode_t file_mode, gid_t file_gid)
00115 {
00116 int fd;
00117
00118 umask(0);
00119
00120 if ((fd = creat(file, file_mode)) < 0)
00121 return -1;
00122
00123 if (file_gid != (gid_t)-1) {
00124 if (chown(file, (uid_t)-1, file_gid) < 0) {
00125 close(fd);
00126 unlink(file);
00127 return -2;
00128 }
00129 }
00130 return fd;
00131 }
00132
00133 static int
00134 dbsfileCreate(const char *dbfile, mode_t file_mode, gid_t file_gid)
00135 {
00136 int dbsfd;
00137
00138 if ((dbsfd = fileCreate(dbfile, file_mode, file_gid)) < 0)
00139 return dbsfd;
00140
00141 if (ftruncate(dbsfd, DBS_DEFSIZE) < 0)
00142 return -1;
00143 return dbsfd;
00144 }
00145
00146 static int
00147 shmfileCreate(const char *dbfile, mode_t file_mode, gid_t file_gid)
00148 {
00149 int shmfd;
00150
00151 if ((shmfd = fileCreate(shmfileGet(dbfile), file_mode, file_gid)) < 0)
00152 return shmfd;
00153
00154 if (ftruncate(shmfd, SHM_DEFSIZE) < 0)
00155 return -1;
00156 return shmfd;
00157 }
00158
00159 static Status
00160 check_dbCreate_1(const char *pr, int dbid, const char *dbfile,
00161 Oid::NX nbobjs, int ndat)
00162 {
00163 int dbfile_len = strlen(dbfile);
00164
00165 if (dbid <= 0 || dbid >= MAX_DBID)
00166 return statusMake(INVALID_DBID,
00167 "%sinvalid database identifier `%d'", pr, dbid);
00168
00169 if (dbfile_len <= dbsext_len ||
00170 strcmp(&dbfile[dbfile_len-dbsext_len], dbsext))
00171 return statusMake(INVALID_DBFILE,
00172 "%sinvalid database file extension for `%s' "
00173 "(must be %s)", pr, dbfile, dbsext);
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 if (ndat <= 0)
00184 return statusMake(INVALID_DATAFILE_CNT,
00185 "%sinvalid volume files number: `%d'",
00186 pr, ndat);
00187
00188 if (ndat >= MAX_DATAFILES)
00189 return statusMake(INVALID_DATAFILE_CNT,
00190 "%svolume files number too large: `%d'", pr, ndat);
00191
00192 return Success;
00193 }
00194
00195 static Status
00196 check_dbCreate_2(const char *pr, const char *dbfile, DBFD *dbfd, mode_t file_mode, gid_t file_gid)
00197 {
00198 if ((dbfd->dbsfd = open(dbfile, O_RDONLY)) >= 0)
00199 return statusMake(INVALID_DBFILE,
00200 "%sdatabase file already exists: '%s'",
00201 pr, dbfile);
00202
00203 if ((dbfd->ompfd = open(objmapfileGet(dbfile), O_RDONLY)) >= 0)
00204 return statusMake(INVALID_DBFILE,
00205 "%smap file already exists: '%s'",
00206 pr, objmapfileGet(dbfile));
00207
00208 if ((dbfd->shmfd = open(shmfileGet(dbfile), O_RDONLY)) >= 0)
00209 return statusMake(INVALID_SHMFILE,
00210 "%sshm file already exists: '%s'",
00211 pr, shmfileGet(dbfile));
00212
00213 if ((dbfd->dbsfd = dbsfileCreate(dbfile, file_mode, file_gid)) < 0)
00214 return statusMake(INVALID_DBFILE,
00215 "%scannot create database file: '%s' [%s]",
00216 pr, dbfile, strerror(errno));
00217
00218 return Success;
00219 }
00220
00221 static Status
00222 check_dbCreate_3(const char *pr, const char *dbfile, DBFD *dbfd, mode_t file_mode, gid_t file_gid)
00223 {
00224 if ((dbfd->ompfd = fileCreate(objmapfileGet(dbfile), file_mode, file_gid))
00225 < 0)
00226 return statusMake(INVALID_DBFILE,
00227 "%scannot create map file: '%s' [%s]",
00228 pr, objmapfileGet(dbfile), strerror(errno));
00229
00230 if ((dbfd->shmfd = shmfileCreate(dbfile, file_mode, file_gid)) < 0)
00231 return statusMake(INVALID_SHMFILE,
00232 "%scannot create shm file: '%s' [%s]",
00233 pr, shmfileGet(dbfile), strerror(errno));
00234
00235 return Success;
00236 }
00237
00238 Status
00239 checkDatafile(const char *pr, const char *dbfile, DbHeader *dbh,
00240 const DbCreateDescription *dbc,
00241 int i, DBFD *dbfd,
00242 mode_t file_mode, gid_t file_gid,
00243 Boolean can_be_null,
00244 Boolean *is_null, Boolean out_place)
00245 {
00246 if (!*dbc->dat[i].file) {
00247 if (can_be_null) {
00248 if (is_null)
00249 *is_null = True;
00250 return Success;
00251 }
00252 return statusMake(INVALID_DBFILE, "%sinvalid null database", pr);
00253 }
00254
00255 DatType dtype = (DatType)dbc->dat[i].dtype;
00256
00257 if (dtype != LogicalOidType &&
00258 dtype != PhysicalOidType)
00259 return statusMake(ERROR, "datafile creation: "
00260 "invalid datatype %d", dtype);
00261
00262 if (is_null)
00263 *is_null = False;
00264 const char *dmpfile = dmpfileGet(dbc->dat[i].file);
00265 short mtype;
00266 int datfile_len = strlen(dbc->dat[i].file);
00267 Status status;
00268 unsigned int sizeslot;
00269
00270 char pwd[DEFAULT_PWD_SIZE];
00271 status = push_dir(dbfile, pwd, sizeof pwd);
00272 if (status) return status;
00273
00274 if (datfile_len <= datext_len ||
00275 strcmp(&dbc->dat[i].file[datfile_len-datext_len], datext)) {
00276 pop_dir(pwd);
00277 return statusMake(INVALID_DBFILE,
00278 "%sinvalid database file extension for `%s' "
00279 "(must be %s)", pr, dbc->dat[i].file, datext);
00280 }
00281
00282 if ((status = checkVolMaxSize(dbc->dat[i].maxsize))) {
00283 pop_dir(pwd);
00284 return status;
00285 }
00286
00287 if ((dbfd->fd_dat[i] = open(dbc->dat[i].file, O_RDONLY)) >= 0) {
00288 pop_dir(pwd);
00289 close(dbfd->fd_dat[i]);
00290 return statusMake(INVALID_DATAFILE,
00291 "%svolume file already exists: '%s'",
00292 pr, dbc->dat[i].file);
00293 }
00294
00295 if (status = checkNewDatafile(dbh, dbc->dat[i].file, dbc->dat[i].name)) {
00296 pop_dir(pwd);
00297 return status;
00298 }
00299
00300 if ((dbfd->fd_dmp[i] = open(dmpfile, O_RDONLY)) >= 0) {
00301 pop_dir(pwd);
00302 close(dbfd->fd_dmp[i]);
00303 return statusMake(INVALID_DMPFILE,
00304 "%sdata map file already exists: '%s'",
00305 pr, dmpfile);
00306 }
00307
00308
00309 if ((dbfd->fd_dat[i] = fileCreate(dbc->dat[i].file, file_mode, file_gid)) <
00310 0) {
00311 pop_dir(pwd);
00312 return statusMake(INVALID_DATAFILE,
00313 "%scannot create volume file: '%s' [%s]",
00314 pr, dbc->dat[i].file, strerror(errno));
00315 }
00316
00317 if ((dbfd->fd_dmp[i] = fileCreate(dmpfile, file_mode, file_gid)) <
00318 0) {
00319 unlink(dbc->dat[i].file);
00320 pop_dir(pwd);
00321 return statusMake(INVALID_DMPFILE,
00322 "%scannot create data map file: '%s' [%s]",
00323 pr, dmpfile, strerror(errno));
00324 }
00325
00326 if (status = syscheck(pr, close(dbfd->fd_dat[i]),
00327 "closing volume file: '%s'",
00328 dbc->dat[i].file)) {
00329 unlink(dmpfile);
00330 unlink(dbc->dat[i].file);
00331 pop_dir(pwd);
00332 return status;
00333 }
00334
00335 strcpy(dbh->dat(i).file(), dbc->dat[i].file);
00336 strcpy(dbh->dat(i).name(), dbc->dat[i].name);
00337 dbh->dat(i).__dspid() = 0;
00338 if (out_place) {
00339 dbh->dat(i).__maxsize() = h2x_u32(dbc->dat[i].maxsize);
00340 setDataspace(dbh, i, DefaultDspid);
00341 setDatType(dbh, i, dtype);
00342 }
00343 else {
00344 dbh->dat(i).__maxsize() = dbc->dat[i].maxsize;
00345 setDataspace_inplace(dbh, i, DefaultDspid);
00346 setDatType_inplace(dbh, i, dtype);
00347 }
00348
00349 dbh->dat(i).__lastslot() = 0;
00350 dbh->dat(i).mp()->memzero();
00351
00352 mtype = dbc->dat[i].mtype;
00353
00354 if (mtype == LinkmapType) {
00355 unlink(dmpfile);
00356 unlink(dbc->dat[i].file);
00357 pop_dir(pwd);
00358 return statusMake(INVALID_MAPTYPE, "%slinkmap type is not supported", pr);
00359 }
00360
00361 if (mtype != BitmapType) {
00362 unlink(dmpfile);
00363 unlink(dbc->dat[i].file);
00364 pop_dir(pwd);
00365 return statusMake(INVALID_MAPTYPE, "%smap type is invalid: '%d'", pr, mtype);
00366 }
00367
00368 sizeslot = ((dbc->dat[i].mtype == BitmapType) ? dbc->dat[i].sizeslot :
00369 sizeof(eyedblib::int32));
00370
00371 DatafileDesc dat = dbh->dat(i);
00372 MapHeader *xmp = dat.mp();
00373
00374 xmp->pow2() = power2(sizeslot);
00375 if (xmp->pow2() < 0) {
00376 unlink(dmpfile);
00377 unlink(dbc->dat[i].file);
00378 pop_dir(pwd);
00379 return statusMake(INVALID_SIZESLOT,
00380 "%sslot size %d is not a power of two", pr, sizeslot);
00381 }
00382
00383 if (mtype == BitmapType &&
00384 (sizeslot < MIN_SIZE_SLOT ||
00385 sizeslot > MAX_SIZE_SLOT ||
00386 (pgsize % sizeslot) != 0)) {
00387 unlink(dmpfile);
00388 unlink(dbc->dat[i].file);
00389 pop_dir(pwd);
00390 return statusMake(INVALID_SIZESLOT,
00391 "dbCreate: slot size is invalid: `%d'", sizeslot);
00392 }
00393
00394 xmp->sizeslot() = sizeslot;
00395 xmp->mtype() = mtype;
00396 xmp->sizeslot() = dbc->dat[i].sizeslot;
00397 if (mtype == BitmapType)
00398 xmp->nslots() =
00399 KB2SLOT(dbc->dat[i].maxsize, xmp->pow2());
00400 else
00401 xmp->nslots() =
00402 ((unsigned long long)(dbc->dat[i].maxsize)*ONE_K)/32;
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 if (status = syscheck(pr, close(dbfd->fd_dmp[i]),
00415 "closing data map file: '%s'", dmpfile)) {
00416 unlink(dmpfile);
00417 unlink(dbc->dat[i].file);
00418 pop_dir(pwd);
00419 return status;
00420 }
00421
00422 pop_dir(pwd);
00423
00424 if (out_place) {
00425 h2x_mapHeader(dbh->dat(i).mp(), xmp);
00426 }
00427
00428 return Success;
00429 }
00430
00431 static char **datfilesBuild(unsigned int ndat)
00432 {
00433 char **datfiles = new char *[ndat];
00434 for (int n = 0; n < ndat; n++) {
00435 char buf[16];
00436 sprintf(buf, "%d", n);
00437 datfiles[n] = strdup(buf);
00438 }
00439
00440 return datfiles;
00441 }
00442
00443 static void datfilesFree(char **datfiles, unsigned int ndat)
00444 {
00445 for (int n = 0; n < ndat; n++)
00446 free(datfiles[n]);
00447
00448 delete [] datfiles;
00449 }
00450
00451 Status
00452 getFileMaskGroup(mode_t &file_mode, gid_t &file_gid, mode_t file_mask, const char *file_group)
00453 {
00454 file_mode = (file_mask | DEFAULT_CREATION_MODE);
00455 if (file_group && *file_group) {
00456 struct group *grp = getgrnam(file_group);
00457 if (!grp) {
00458 return statusMake(DATABASE_CREATION_ERROR, "invalid file group: %s", file_group);
00459 }
00460 file_gid = grp->gr_gid;
00461 }
00462 else
00463 file_gid = (gid_t)-1;
00464
00465 return Success;
00466 }
00467
00468 Status
00469 dbCreate(const char *dbfile, unsigned int version,
00470 const DbCreateDescription *dbc, mode_t file_mask, const char *file_group)
00471 {
00472 DBFD dbfd;
00473 int dbid = dbc->dbid, sizeslot, i,
00474 ndat = dbc->ndat, szhead, rszhead;
00475
00476 Oid::NX nbobjs = dbc->nbobjs;
00477 int n;
00478 DbHeader dbh;
00479
00480 DbHandle *pdbh;
00481 DbShmHeader dbhshm;
00482 char *p;
00483 Status status;
00484 int dbfile_len = strlen(dbfile);
00485
00486 #undef PR
00487 #define PR "dbCreate: "
00488 mode_t file_mode;
00489 gid_t file_gid;
00490 status = getFileMaskGroup(file_mode, file_gid, file_mask, file_group);
00491 if (status)
00492 return status;
00493
00494 status = check_dbCreate_1(PR, dbid, dbfile, nbobjs, ndat);
00495 if (status)
00496 return status;
00497
00498 status = check_dbCreate_2(PR, dbfile, &dbfd, file_mode, file_gid);
00499 if (status)
00500 return status;
00501
00502 status = check_dbCreate_3(PR, dbfile, &dbfd, file_mode, file_gid);
00503 if (status)
00504 return dbcreate_error(status, dbfile, dbc, 0, &dbfd);
00505
00506 memset(&dbhshm, 0, sizeof(dbhshm));
00507 dbhshm.magic = MAGIC;
00508 dbhshm.version = h2x_u32(version);
00509 if ((n = write(dbfd.shmfd, (char *)&dbhshm, sizeof(dbhshm))) !=
00510 sizeof(dbhshm))
00511 return dbcreate_error(statusMake(DATABASE_CREATION_ERROR, PR "unexpected writing header in shmfile: '%s'", shmfileGet(dbfile)),
00512 dbfile, dbc, 0, &dbfd);
00513
00514 if (status = syscheck(PR, close(dbfd.shmfd), "closing shm file: '%s'", shmfileGet(dbfile)))
00515 return dbcreate_error(status, dbfile, dbc, 0, &dbfd);
00516
00517 dbh.memzero();
00518
00519 char pwd[DEFAULT_PWD_SIZE];
00520 status = push_dir(dbfile, pwd, sizeof pwd);
00521 if (status) return status;
00522
00523 Boolean ok = False;
00524 dbh.__magic() = MAGIC;
00525 for (i = 0; i < ndat; i++) {
00526 Boolean is_null;
00527 status = checkDatafile(PR, dbfile, &dbh, dbc, i, &dbfd,
00528 file_mode, file_gid, True, &is_null);
00529 if (!is_null) ok = True;
00530 if (status) {
00531 pop_dir(pwd);
00532 return dbcreate_error(status, dbfile, dbc, i, &dbfd);
00533 }
00534 }
00535
00536 if (!ok) {
00537 pop_dir(pwd);
00538 return statusMake(DATABASE_CREATION_ERROR, PR " at least one datafile must not be null");
00539 }
00540
00541 strcpy(dbh.shmfile(), shmfileGet(dbfile));
00542 dbh.__ndat() = dbc->ndat;
00543 dbh.__lastidxbusy() = 0;
00544 dbh.__curidxbusy() = 0;
00545 dbh.__dbid() = dbid;
00546 dbh.__guest_uid() = INVALID_UID;
00547 dbh.__nbobjs() = nbobjs;
00548
00549 dbh.state() = OPENING_STATE;
00550
00551 DbHeader xdbh;
00552 h2x_dbHeader(&xdbh, &dbh);
00553
00554 if ((n = write(dbfd.dbsfd, xdbh._addr(), DbHeader_SIZE)) != DbHeader_SIZE) {
00555 pop_dir(pwd);
00556 return dbcreate_error(statusMake(DATABASE_CREATION_ERROR, PR "unexpected error reported by write on database file: '%s'", dbfile), dbfile, dbc, ndat, &dbfd);
00557 }
00558
00559 if (status = syscheck(PR, close(dbfd.dbsfd), "closing database file: '%s'", dbfile)) {
00560 pop_dir(pwd);
00561 return dbcreate_error(status, dbfile, dbc, ndat, &dbfd);
00562 }
00563
00564 if (status = syscheck(PR, close(dbfd.ompfd), "closing map oid file: '%s'",
00565 objmapfileGet(dbfile))) {
00566 pop_dir(pwd);
00567 return dbcreate_error(status, dbfile, dbc, ndat, &dbfd);
00568 }
00569
00570 if (status = ESM_dbOpen(dbfile, VOLRW, 0, 0, 0, 1, 0, 0, &pdbh)) {
00571 pop_dir(pwd);
00572 return dbcreate_error(statusMake(DATABASE_CREATION_ERROR, PR "database open error reported: '%s'", statusGet(status)), dbfile, dbc, ndat, &dbfd);
00573 }
00574
00575 char **datfiles = datfilesBuild(ndat);
00576
00577
00578 if (status = ESM_dspCreate(pdbh, defDsp, (const char **)datfiles, ndat, True)) {
00579 datfilesFree(datfiles, ndat);
00580 pop_dir(pwd);
00581 return dbcreate_error(statusMake(DATABASE_CREATION_ERROR, PR "database open error reported: '%s'", statusGet(status)), dbfile, dbc, ndat, &dbfd);
00582 }
00583
00584
00585 datfilesFree(datfiles, ndat);
00586
00587 if (status = ESM_dspSetDefault(pdbh, defDsp, True)) {
00588 pop_dir(pwd);
00589 return dbcreate_error(statusMake(DATABASE_CREATION_ERROR, PR "database open error reported: '%s'", statusGet(status)), dbfile, dbc, ndat, &dbfd);
00590 }
00591
00592 if (status = protectionInit(pdbh)) {
00593 pop_dir(pwd);
00594 return dbcreate_error(statusMake(DATABASE_CREATION_ERROR, PR "database protection init error reported: '%s'", statusGet(status)), dbfile, dbc, ndat, &dbfd);
00595 }
00596
00597 pop_dir(pwd);
00598 DbHeader _xpdbh(pdbh->vd->dbs_addr);
00599 _xpdbh.state() = OPENED_STATE;
00600
00601 ESM_dbClose(pdbh);
00602
00603 return Success;
00604 }
00605
00606 Status
00607 dbDelete(const char *dbfile)
00608 {
00609 Status s;
00610 DbHandle *dbh;
00611 int i;
00612
00613 #undef PR
00614 #define PR "dbDelete: "
00615 if (s = ESM_dbOpen(dbfile, VOLRW, 0, 0, 0, 0, 0, 0, &dbh))
00616 return s;
00617
00618 char pwd[DEFAULT_PWD_SIZE];
00619 s = push_dir(dbfile, pwd, sizeof pwd);
00620 if (s) return s;
00621
00622 DbHeader _dbh(DBSADDR(dbh));;
00623 unsigned int ndat = x2h_u32(_dbh.__ndat());
00624 for (i = 0; i < ndat; i++) {
00625 if (*_dbh.dat(i).file()) {
00626 if (unlink(_dbh.dat(i).file()) < 0) {
00627 pop_dir(pwd);
00628 return fcouldnot(PR, "unlink", _dbh.dat(i).file());
00629 }
00630
00631 if (unlink(dmpfileGet(_dbh.dat(i).file())) < 0) {
00632 pop_dir(pwd);
00633 return fcouldnot(PR, "unlink", dmpfileGet(_dbh.dat(i).file()));
00634 }
00635 }
00636 }
00637
00638 ESM_dbClose(dbh);
00639
00640 if (unlink(dbfile) < 0) {
00641 pop_dir(pwd);
00642 return fcouldnot(PR, "unlink", dbfile);
00643 }
00644
00645 if (unlink(shmfileGet(dbfile)) < 0) {
00646 pop_dir(pwd);
00647 return fcouldnot(PR, "unlink", shmfileGet(dbfile));
00648 }
00649
00650 if (unlink(objmapfileGet(dbfile)) < 0) {
00651 pop_dir(pwd);
00652 return fcouldnot(PR, "unlink", objmapfileGet(dbfile));
00653 }
00654
00655 return pop_dir(pwd);
00656 }
00657
00658 Status
00659 dbInfo(const char *dbfile, DbInfoDescription *info)
00660 {
00661 DbHeader xdbh;
00662 int fd;
00663 Status se;
00664
00665 #undef PR
00666 #define PR "dbInfo: "
00667 if (se = checkFileAccess(DATABASE_OPEN_FAILED, "database file",
00668 dbfile, R_OK))
00669 return se;
00670
00671 if ((se = dopen(PR, dbfile, O_RDONLY, &fd, 0)) != Success)
00672 return se;
00673
00674 if (se = syscheckn(PR, read(fd, xdbh._addr(), DbHeader_SIZE), DbHeader_SIZE,
00675 "reading database file: '%s'", dbfile))
00676 return se;
00677
00678 DbHeader dbh;
00679 x2h_dbHeader(&dbh, &xdbh);
00680
00681 if (dbh.__magic() != MAGIC) {
00682 if (se = syscheck(PR, close(fd), "closing database file: '%s'",
00683 dbfile))
00684 return se;
00685 return statusMake(INVALID_DBFILE,
00686 PR "database file '%s' is not a valid eyedbsm database "
00687 "file", dbfile);
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 info->dbid = dbh.__dbid();
00701 info->ndat = dbh.__ndat();
00702 info->ndsp = dbh.__ndsp();
00703 info->nbobjs = dbh.__nbobjs();
00704
00705 if (se = fileSizesGet(dbfile,
00706 info->dbsfilesize, info->dbsfileblksize))
00707 return se;
00708
00709 if (se = fileSizesGet(objmapfileGet(dbfile),
00710 info->ompfilesize, info->ompfileblksize))
00711 return se;
00712
00713 if (se = fileSizesGet(shmfileGet(dbfile),
00714 info->shmfilesize, info->shmfileblksize))
00715 return se;
00716
00717 if (se = syscheck(PR, close(fd), "closing database file: '%s'", dbfile))
00718 return se;
00719
00720 for (int i = 0; i < dbh.__ndsp(); i++) {
00721 Dataspace *ds = &info->dsp[i];
00722 DataspaceDesc _dsd = dbh.dsp(i);
00723 DataspaceDesc *dsd = &_dsd;
00724
00725 strcpy(ds->name, dsd->name());
00726 ds->ndat = dsd->__ndat();
00727 memcpy(ds->datid, dsd->__datid_ref(), sizeof(short) * dsd->__ndat());
00728 }
00729
00730 for (int i = 0; i < dbh.__ndat(); i++) {
00731 Datafile *df = &info->dat[i];
00732 DatafileDesc _dfd = dbh.dat(i);
00733 DatafileDesc *dfd = &_dfd;
00734
00735 strcpy(df->file, dfd->file());
00736 strcpy(df->name, dfd->name());
00737 df->dspid = getDataspace_inplace(&dbh, i);
00738 df->dtype = getDatType_inplace(&dbh, i);
00739 df->maxsize = dfd->__maxsize();
00740 df->mtype = dfd->mp()->mtype();
00741 df->sizeslot = dfd->mp()->sizeslot();
00742
00743 if (!access(df->file, R_OK|W_OK))
00744 df->extflags = R_OK|W_OK;
00745 else if (!access(df->file, W_OK))
00746 df->extflags = W_OK;
00747 else if (!access(df->file, R_OK))
00748 df->extflags = R_OK;
00749 else
00750 df->extflags = 0;
00751 }
00752
00753 return Success;
00754 }
00755
00756
00757
00758
00759
00760 #define XSTR(F) ((F) ? "copy" : "move")
00761
00762
00763 char *
00764 makefile(const char *dir, const char *file)
00765 {
00766 static int buf_ind;
00767 #define NN 8
00768 static char *buf[NN];
00769 char *s;
00770
00771 if (buf_ind >= NN)
00772 buf_ind = 0;
00773
00774 free(buf[buf_ind]);
00775
00776 if (!dir || !*dir || *file == '/') {
00777 buf[buf_ind] = strdup(file);
00778 return buf[buf_ind++];
00779 }
00780
00781 s = (char *)m_malloc(strlen(dir)+strlen(file)+2);
00782 strcpy(s, dir);
00783 strcat(s, "/");
00784 strcat(s, file);
00785
00786 buf[buf_ind] = s;
00787 return buf[buf_ind++];
00788 }
00789
00790 Status
00791 copyfile(const char *from, const char *to,
00792 const char *fromdbdir, const char *todbdir,
00793 int sparsify)
00794 {
00795 int fd1, fd2;
00796 struct stat st;
00797 Status se;
00798 char *xfrom = makefile(fromdbdir, from);
00799 char *xto = makefile(todbdir, to);
00800
00801 #if 1
00802 sparsify = 0;
00803 #endif
00804
00805 errno = 0;
00806
00807 #ifdef MVCP_TRACE
00808 printf("copying '%s' to '%s' [%s . %s]\n", xfrom, xto, fromdbdir, todbdir);
00809 #endif
00810
00811 if (!access(xto, F_OK))
00812 return syserror("target file '%s' already exists", xto);
00813
00814 if ((fd1 = open(xfrom, O_RDONLY)) < 0)
00815 return syserror("opening file '%s' for reading", xfrom);
00816
00817 if ((fd2 = creat(xto, DEFAULT_CREATION_MODE)) < 0) {
00818 close(fd1);
00819 return syserror("creating file '%s'", xto);
00820 }
00821
00822
00823 if (fstat(fd1, &st) < 0)
00824 return syserror("stating file '%s'", xfrom);
00825 fchmod(fd2, st.st_mode);
00826
00827 if (!sparsify) {
00828 char buf[2048];
00829 int n;
00830 while ((n = read(fd1, buf, sizeof buf)) > 0)
00831 if (write(fd2, buf, n) != n) {
00832 close(fd1); close(fd2); unlink(xto);
00833 return syserror("writing to file '%s'", xto);
00834 }
00835
00836 if (n < 0) {
00837 close(fd1); close(fd2); unlink(xto);
00838 return syserror("reading from file '%s'", xfrom);
00839 }
00840 }
00841 else {
00842 char buf[512];
00843 static char const zero[sizeof buf] = { 0 };
00844 int n;
00845 off_t zeros = 0;
00846
00847 while ((n = read(fd1, buf, sizeof buf)) > 0) {
00848 if (memcmp(buf, zero, n) == 0)
00849 zeros += n;
00850 else {
00851 if (zeros) {
00852 if (lseek(fd2, zeros, SEEK_CUR) < 0) {
00853 close(fd1); close(fd2); unlink(xto);
00854 return syserror("seeking file '%s'", xto);
00855 }
00856 zeros = 0;
00857 }
00858 if (write(fd2, buf, n) != n) {
00859 close(fd1); close(fd2); unlink(xto);
00860 return syserror("writing to file '%s'", xto);
00861 }
00862 }
00863 }
00864
00865 if (n < 0) {
00866 close(fd1); close(fd2); unlink(xto);
00867 return syserror("reading from file '%s'", xfrom);
00868 }
00869
00870 if (zeros) {
00871 if (lseek(fd2, zeros - 1, SEEK_CUR) < 0) {
00872 close(fd1); close(fd2); unlink(xto);
00873 return syserror("seeking file '%s'", xto);
00874 }
00875
00876 if (write(fd2, zero, 1) != 1) {
00877 close(fd1); close(fd2); unlink(xto);
00878 return syserror("writing to file '%s'", xto);
00879 }
00880 }
00881 }
00882
00883 close(fd1);
00884 close(fd2);
00885 return Success;
00886 }
00887
00888 Status
00889 renamefile(char const * from, char const * to,
00890 const char *fromdbdir, const char *todbdir, int sparsify)
00891 {
00892 char *xfrom = makefile(fromdbdir, from);
00893 char *xto = makefile(todbdir, to);
00894
00895 #ifdef MVCP_TRACE
00896 printf("renaming '%s' to '%s' [%s . %s]\n", from, to, fromdbdir, todbdir);
00897 #endif
00898
00899 if (rename(xfrom, xto) < 0) {
00900 Status se;
00901 if (errno != EXDEV)
00902 return syserror("renaming file '%s' to '%s'", xfrom, xto);
00903
00904 #ifdef MVCP_TRACE
00905 printf("cannot rename file across 2 file systems\n");
00906 #endif
00907
00908 se = copyfile(from, to, fromdbdir, todbdir, sparsify);
00909 if (se)
00910 return statusMake(se->err, "renaming file '%s' to '%s': %s", xfrom, xto, se->err_msg);
00911
00912 if (unlink(xfrom) < 0)
00913 return syserror("unlinking file '%s'", xfrom);
00914 }
00915
00916 return Success;
00917 }
00918
00919 static Status
00920 mvcp_immediate(const char *xstr, const char *from,
00921 const char *to, const char *fromdbdir, const char *todbdir,
00922 Status (*mvcp)(const char *, const char *,
00923 const char *, const char *, int))
00924 {
00925 Status s;
00926 if (strcmp(from, to) && (s = mvcp(from, to, fromdbdir, todbdir, 1)))
00927 return statusMake(INVALID_SHMFILES_COPY,
00928 "%s operation failed between "
00929 "'%s' and '%s': %s",
00930 xstr, from, to, s->err_msg);
00931 return Success;
00932 }
00933
00934 static Status
00935 mvcp_datafiles(DbCreateDescription *dbc,
00936 DbHandle *dbh,
00937 DbHeader *db_header, int fd,
00938 const char *fromdbdir, const char *todbdir,
00939 const char *dbfile,
00940 int flag,
00941 Status (*mvcp)(const char *, const char *,
00942 const char *, const char *, int))
00943 {
00944 int i;
00945 Status s;
00946 for (i = 0; i < dbc->ndat; i++) {
00947 DbHeader _dbh(DBSADDR(dbh));
00948 char *from = makefile(fromdbdir, _dbh.dat(i).file());
00949 char *to = makefile(todbdir, dbc->dat[i].file);
00950
00951 if (strcmp(from, to)) {
00952 if (s = mvcp(_dbh.dat(i).file(),
00953 dbc->dat[i].file, fromdbdir, todbdir, 0))
00954 return statusMake(INVALID_DATAFILES_COPY,
00955 "%s operation failed between "
00956 "'%s' and '%s': %s",
00957 XSTR(flag), from, to, s->err_msg);
00958
00959 if (s = mvcp(dmpfileGet(_dbh.dat(i).file()),
00960 dmpfileGet(dbc->dat[i].file), fromdbdir, todbdir, 0))
00961 return statusMake(INVALID_DATAFILES_COPY,
00962 "%s operation failed between "
00963 "'%s' and '%s': %s",
00964 XSTR(flag),
00965 dmpfileGet(from),
00966 dmpfileGet(to),
00967 s->err_msg);
00968 }
00969
00970 strcpy(db_header->dat(i).file(), dbc->dat[i].file);
00971
00972 if (lseek(fd, 0, 0) < 0)
00973 return syserror("rewing database file '%s'", dbfile);
00974
00975 if (write(fd, db_header->_addr(), DbHeader_SIZE) != DbHeader_SIZE)
00976 return syserror("writing database file '%s'", dbfile);
00977 }
00978
00979 return Success;
00980 }
00981
00982 static Status
00983 mvcp_check(const char *fname, DbCreateDescription *dbc,
00984 DbHandle *dbh,
00985 const char *fromdbdir, const char *todbdir,
00986 const char *dbfile, const char *ndbfile,
00987 int flag)
00988 {
00989 int i;
00990 Status s;
00991
00992 DbHeader _dbh(DBSADDR(dbh));
00993 unsigned int ndat = x2h_u32(_dbh.__ndat());
00994 if (dbc->ndat != ndat)
00995 return statusMake(INVALID_DATAFILE_CNT,
00996 "%s: different volume files number: `%d' vs. `%d'",
00997 fname, dbc->ndat, ndat);
00998
00999 for (i = 0; i < dbc->ndat; i++) {
01000 unsigned int maxsize = x2h_u32(_dbh.dat(i).__maxsize());
01001 if (!dbc->dat[i].maxsize)
01002 dbc->dat[i].maxsize = maxsize;
01003 else if (dbc->dat[i].maxsize != maxsize)
01004 return statusMake(INVALID_MAXSIZE,
01005 "%s: different maximum size: `%d' vs. `%d' "
01006 "on volume file #%d",
01007 fname, dbc->dat[i].maxsize,
01008 maxsize, i);
01009 }
01010
01011 if (!strcmp(dbfile, ndbfile)) {
01012 if (flag)
01013 return statusMake(DBFILES_IDENTICAL,
01014 "%s: identical database files: '%s'",
01015 fname, dbfile);
01016 }
01017
01018 if (flag) {
01019 if (!access(ndbfile, F_OK))
01020 return statusMake(DBFILE_ALREADY_EXISTS,
01021 "%s: target database file already exists: '%s'",
01022 fname, ndbfile);
01023 if (!access(shmfileGet(ndbfile), F_OK))
01024 return statusMake(SHMFILE_ALREADY_EXISTS,
01025 "%s: target shm file already exists: '%s'",
01026 fname, shmfileGet(ndbfile));
01027 if (!access(objmapfileGet(ndbfile), F_OK))
01028 return statusMake(OBJMAPFILE_ALREADY_EXISTS,
01029 "%s: target oid map file already exists: '%s'",
01030 fname, objmapfileGet(ndbfile));
01031 }
01032
01033
01034 for (i = 0; i < dbc->ndat; i++) {
01035 char *to = makefile(todbdir, dbc->dat[i].file);
01036 char *from = makefile(fromdbdir, _dbh.dat(i).file());
01037
01038 if (flag && !strcmp(from, to))
01039 return statusMake(DATAFILES_IDENTICAL,
01040 "%s: identical data files: '%s'",
01041 fname, to);
01042 if (strcmp(from, to) && !access(to, F_OK))
01043 return statusMake(DATAFILE_ALREADY_EXISTS,
01044 "%s: target data file already exists: '%s'",
01045 fname, to);
01046 }
01047 return Success;
01048 }
01049
01050 static Status
01051 mvcp_realize(const char *fname, const char *dbfile,
01052 const DbMoveDescription *xdmv, int flag)
01053 {
01054 DbMoveDescription dmv = *xdmv;
01055 DbHandle *dbh;
01056 DbHeader db_header;
01057 Status s;
01058 DbCreateDescription *dbc = &dmv.dcr;
01059 int i, fd;
01060 Status (*mvcp)(const char *, const char *,
01061 const char *, const char *, int);
01062 const char *fromdbdir = get_dir(dbfile);
01063 const char *todbdir = get_dir(dmv.dbfile);
01064
01065 if (s = ESM_dbOpen(dbfile, VOLREAD, 0, 0, 0, 0, 0, 0, &dbh) )
01066 return s;
01067
01068 if (s = mvcp_check(fname, dbc, dbh, fromdbdir, todbdir,
01069 dbfile, dmv.dbfile, flag))
01070 return s;
01071
01072 mvcp = (flag ? copyfile : renamefile);
01073
01074 if (strcmp(dbfile, dmv.dbfile)) {
01075 if (s = mvcp(dbfile, dmv.dbfile, fromdbdir, todbdir, 1))
01076 return statusMake(INVALID_DBFILES_COPY,
01077 "%s operation failed between "
01078 "'%s' and '%s': %s",
01079 XSTR(flag), dbfile, dmv.dbfile,
01080 s->err_msg);
01081 }
01082
01083 if ((fd = open(dmv.dbfile, O_RDWR)) >= 0) {
01084 if (read(fd, db_header._addr(), DbHeader_SIZE) != DbHeader_SIZE)
01085 return syserror("reading database file '%s'", dmv.dbfile);
01086 }
01087 else
01088 return statusMake(INVALID_DBFILE_ACCESS,
01089 "cannot open database file for writing: '%s'",
01090 dmv.dbfile);
01091
01092 if (s = mvcp_immediate(XSTR(flag),
01093 shmfileGet(dbfile), shmfileGet(dmv.dbfile),
01094 fromdbdir, todbdir, mvcp))
01095 return s;
01096
01097 if (s = mvcp_immediate(XSTR(flag),
01098 objmapfileGet(dbfile), objmapfileGet(dmv.dbfile),
01099 fromdbdir, todbdir, mvcp))
01100 return s;
01101
01102 if (s = mvcp_datafiles(dbc, dbh, &db_header, fd, fromdbdir, todbdir,
01103 dmv.dbfile, flag, mvcp))
01104 return s;
01105
01106 close(fd);
01107
01108 ESM_dbClose(dbh);
01109
01110 if (s = ESM_dbOpen(dmv.dbfile, VOLREAD, 0, 0, 0, 0, 0, 0, &dbh))
01111 return s;
01112
01113 ESM_dbClose(dbh);
01114 return Success;
01115 }
01116
01117 Status
01118 dbMove(const char *dbfile, const DbMoveDescription *dmv)
01119 {
01120 return mvcp_realize("dbMove", dbfile, dmv, 0);
01121 }
01122
01123 Status
01124 dbCopy(const char *dbfile, const DbCopyDescription *dcp)
01125 {
01126 return mvcp_realize("dbCopy", dbfile, dcp, 1);
01127 }
01128
01129 Status
01130 dbRelocate(const char *dbfile, const DbRelocateDescription *rel)
01131 {
01132 DbHeader xdbh;
01133 int fd, i;
01134 Status se;
01135
01136 #undef PR
01137 #define PR "dbRelocate: "
01138 if ( (fd = open(dbfile, O_RDWR)) < 0)
01139 return statusMake(INVALID_DBFILE_ACCESS, PR "cannot open database file for writing: '%s'", dbfile);
01140
01141 if (se = syscheckn(PR, read(fd, xdbh._addr(), DbHeader_SIZE), DbHeader_SIZE, ""))
01142 return se;
01143
01144 DbHeader dbh;
01145 x2h_dbHeader(&dbh, &xdbh);
01146 if (dbh.__magic() != MAGIC)
01147 return statusMake(INVALID_DBFILE, PR "database file '%s' is not a valid eyedbsm database file", dbfile);
01148
01149
01150
01151
01152
01153
01154
01155
01156 if (rel->ndat != dbh.__ndat()) {
01157 close(fd);
01158 return statusMake_s(INVALID_DATAFILE_CNT);
01159 }
01160
01161 for (i = 0; i < dbh.__ndat(); i++)
01162 strcpy(dbh.dat(i).file(), rel->file[i]);
01163
01164 if (se = syscheck(PR, lseek(fd, 0, 0), ""))
01165 return se;
01166
01167 h2x_dbHeader(&xdbh, &dbh);
01168 if (se = syscheckn(PR, write(fd, xdbh._addr(), DbHeader_SIZE), DbHeader_SIZE, ""))
01169 return se;
01170
01171 if (se = syscheck(PR, close(fd), ""))
01172 return se;
01173
01174 return Success;
01175 }
01176
01177
01178
01179
01180
01181
01182 static Status
01183 shmMap(const char *dbfile, size_t size, int shmfd,
01184 void **pshm_addr, m_Map **pm_shm)
01185 {
01186 #undef PR
01187 #define PR "shmMap"
01188 int x;
01189 #ifndef MAP_NORESERVE
01190 #define MAP_NORESERVE 0
01191 #endif
01192 for (x = 0; ; x++) {
01193 if (*pm_shm = m_mmap(0, size, (PROT_READ|PROT_WRITE),
01194 MAP_NORESERVE|MAP_SHARED, shmfd,
01195 0, (char **)pshm_addr, shmfileGet(dbfile), 0, 0)) {
01196 if (x)
01197 IDB_LOG(IDB_LOG_MMAP, ("m_mmap successfull in shmMap after %d attemps\n",
01198 x));
01199 break;
01200 }
01201
01202 if (x == MAXTRIES)
01203 return statusMake(MAP_ERROR, PR "shmfile '%s' cannot be mapped by eyedbsm server", shmfileGet(dbfile));
01204 IDB_LOG(IDB_LOG_MMAP, ("m_mmap failed in shmMap, tries again\n"));
01205 sleep(1);
01206 }
01207
01208 m_lock(*pm_shm);
01209
01210 return Success;
01211 }
01212
01213 static Status
01214 dbsUnmap(const char *dbfile, DbDescription *vd)
01215 {
01216 m_unlock(vd->m_dbs);
01217
01218 if (m_munmap(vd->m_dbs, (char *)vd->dbs_addr, DBS_DEFSIZE))
01219 return statusMake(MAP_ERROR, PR "database system file '%s' "
01220 "cannot be unmapped by eyedbsm server", dbfile);
01221
01222 return Success;
01223 }
01224
01225 static Status
01226 shmUnmap(const char *dbfile, DbDescription *vd, unsigned int size)
01227 {
01228 m_unlock(vd->m_shm);
01229
01230 if (m_munmap(vd->m_shm, (char *)vd->shm_addr, size))
01231 return statusMake(MAP_ERROR, PR "shmfile '%s' cannot be unmapped by eyedbsm server", shmfileGet(dbfile));
01232
01233 return Success;
01234 }
01235
01236 static Status
01237 shmMutexRelease(DbDescription *vd, DbShmHeader *shmh, unsigned int xid)
01238 {
01239 Status se;
01240
01241
01242 if (xid && (se = DbMutexesRelease(vd, shmh, xid)))
01243 return se;
01244
01245 return Success;
01246 }
01247
01248 #define NO_BLOCK
01249 static void
01250 ESM_DbInitialize(DbDescription *vd, void *shm_addr, unsigned int shmsize)
01251 {
01252 DbMutexesInit(vd, (DbShmHeader *)shm_addr);
01253 ESM_transInit(vd, (char *)shm_addr, shmsize);
01254 }
01255
01256 static Status
01257 ESM_dbOpenPrologue(DbDescription *vd, DbShmHeader *shmh,
01258 unsigned int shmsize, const char *dbfile, int flags,
01259 unsigned int *pxid)
01260 {
01261 XMHandle *xmh;
01262 char hostname[256+1];
01263
01264 #undef PR
01265 #define PR "dbOpenPrologue: "
01266
01267 if (shmh->magic != MAGIC)
01268 return statusMake(INVALID_SHMFILE, PR "shm file is not a valid eyedbsm shm file: '%s'", shmfileGet(dbfile));
01269
01270 gethostname(hostname, sizeof(hostname)-1);
01271
01272 Mutex *mp = VD2MTX(vd, TRS);
01273
01274 DbMutexesLightInit(vd, shmh);
01275
01276
01277 xmh = XMOpen(((char *)shmh) + SHM_HEADSIZE, vd);
01278
01279 if (!xmh) {
01280
01281 return statusMake(INVALID_SHMFILE, PR "shm file is not a valid eyedbsm shm file: '%s'", shmfileGet(dbfile));
01282 }
01283
01284 Boolean mustUnlock = True;
01285 if (x2h_u32((unsigned int)shmh->hostid) != (unsigned int)gethostid() ||
01286 strncmp(shmh->arch, eyedblib::CompileBuiltin::getArch(), sizeof( shmh->arch))) {
01287
01288 return statusMake(DATABASE_OPEN_FAILED,
01289 "cannot open database %s on "
01290 "computer %s [architecture %s]: "
01291 "database hold by computer %s [architecture %s]",
01292 dbfile, hostname, eyedblib::CompileBuiltin::getArch(), shmh->hostname,
01293 shmh->arch);
01294 }
01295
01296 if (backend) {
01297 *pxid = rpc_getpid();
01298
01299 shmh->stat.total_db_access_cnt = h2x_u32(x2h_u32(shmh->stat.total_db_access_cnt)+1);
01300 shmh->stat.current_db_access_cnt = h2x_u32(x2h_u32(shmh->stat.current_db_access_cnt)+1);
01301 }
01302 else {
01303 *pxid = import_xid;
01304 }
01305
01306
01307
01308
01309
01310
01311 IDB_LOG(IDB_LOG_DATABASE, ("dbOpenPrologue(%s) -> xid = %d [backend %d]\n", dbfile, *pxid,
01312 backend));
01313
01314 return Success;
01315 }
01316
01317 static void
01318 ESM_initHost(DbShmHeader *sm_shmh)
01319 {
01320 char hostname[256+1];
01321 gethostname(hostname, sizeof(hostname)-1);
01322 sm_shmh->hostid = x2h_u32(gethostid());
01323 strncpy(sm_shmh->hostname, hostname, sizeof(sm_shmh->hostname)-1);
01324 sm_shmh->hostname[sizeof(sm_shmh->hostname)-1] = 0;
01325 strncpy(sm_shmh->arch, eyedblib::CompileBuiltin::getArch(), sizeof( sm_shmh->arch));
01326 }
01327
01328 #define ESM_MMAP_WIDE_SEGMENT 2000
01329
01330 static OpenHints *
01331 get_default_hints()
01332 {
01333 static OpenHints hints = {SegmentMap, ESM_MMAP_WIDE_SEGMENT};
01334 return &hints;
01335 }
01336
01337 static bool TRACE_CLEANUP = (getenv("EYEDB_TRACE_CLEANUP") != 0);
01338 static bool SLEEP_CLEANUP = (getenv("EYEDB_SLEEP_CLEANUP") != 0);
01339
01340 static std::map<std::string, unsigned int> db_map;
01341
01342 static Status db_clean_shm(const char *dbfile, int *lkfd, int shmfd)
01343 {
01344 #undef PR
01345 #define PR "dbOpenPrologue: "
01346 errno = 0;
01347
01348 if (db_map.find(dbfile) != db_map.end()) {
01349 if (TRACE_CLEANUP) {
01350 fprintf(stderr, "eyedbsm: found database %s %d\n", dbfile, db_map[dbfile]);
01351 }
01352 db_map[dbfile]++;
01353 return Success;
01354 }
01355
01356 const char *lockfile = fileGet(dbfile, ".lck");
01357 if ((*lkfd = open(lockfile, O_RDWR)) < 0) {
01358 struct stat st;
01359 mode_t file_mode = DEFAULT_CREATION_MODE;
01360 if (stat(shmfileGet(dbfile), &st) >= 0) {
01361 file_mode = st.st_mode;
01362 }
01363
01364 int fd = fileCreate(lockfile, file_mode, (gid_t)-1);
01365 if (TRACE_CLEANUP) {
01366 fprintf(stderr, "eyedbsm: creating lockfile %s\n", lockfile);
01367 }
01368
01369 if (fd < 0) {
01370 return statusMake(INVALID_DBFILE,
01371 "%scannot create lock file: '%s' [%s]",
01372 PR, lockfile, strerror(errno));
01373 }
01374 close(fd);
01375
01376 if ((*lkfd = open(lockfile, O_RDWR)) < 0) {
01377 return statusMake(INVALID_DBFILE,
01378 "%scannot open lock file: '%s' [%s]",
01379 PR, lockfile, strerror(errno));
01380 }
01381 }
01382
01383 if (filelockX(*lkfd)) {
01384 if (TRACE_CLEANUP) {
01385 fprintf(stderr, "eyedbsm: cleaning up database %s %d %s\n", dbfile, errno, strerror(errno));
01386 }
01387
01388 dbCleanupRealize(shmfileGet(dbfile), shmfd);
01389
01390 if (SLEEP_CLEANUP) {
01391 int sl = atoi(getenv("EYEDB_SLEEP_CLEANUP"));
01392 if (TRACE_CLEANUP) {
01393 fprintf(stderr, "eyedbsm: waiting for %d seconds\n", sl);
01394 }
01395 sleep(sl);
01396 }
01397
01398 if (!filelockS(*lkfd)) {
01399 return statusMake(ERROR, PR "cannot open database '%s': cannot lock dbfile in share mode", dbfile);
01400 }
01401
01402 db_map[dbfile] = 1;
01403 return Success;
01404 }
01405
01406 if (TRACE_CLEANUP) {
01407 fprintf(stderr, "eyedbsm: does not clean up database %s %d %s\n", dbfile, errno, strerror(errno));
01408 }
01409
01410 for (int try_n = 0; !filelockS(*lkfd); try_n++) {
01411 #define MAX_TRY_LOCK_CNT 100
01412 if (try_n == MAX_TRY_LOCK_CNT) {
01413 return statusMake(ERROR, PR "cannot open database '%s': cannot lock dbfile in share mode", dbfile);
01414 }
01415 if (TRACE_CLEANUP) {
01416 fprintf(stderr, "eyedbsm: waiting before continuing...\n");
01417 }
01418 usleep(10000);
01419 }
01420
01421 if (TRACE_CLEANUP) {
01422 fprintf(stderr, "eyedbsm: continuing for database '%s'\n", dbfile);
01423 }
01424
01425 db_map[dbfile] = 1;
01426 return Success;
01427 }
01428
01429 Status
01430 ESM_dbOpen(const char *dbfile, int flags,
01431 const OpenHints *hints, int *id,
01432 void **pdblock, int create_mode, unsigned int xid,
01433 unsigned int *pversion, DbHandle **pdbh)
01434 {
01435 int hdfd, shmfd, ompfd, va, fop, i;
01436 int const opf = (flags & VOLREAD) ? O_RDONLY : O_RDWR;
01437 int const accflags = (flags & VOLREAD ? R_OK : R_OK|W_OK);
01438 size_t size;
01439 DbDescription *vd;
01440 DbHeader *dbh = NULL;
01441 Status se;
01442 Boolean suser = True;
01443 void *shm_addr;
01444 int x;
01445 size_t shmsize;
01446 unsigned int version;
01447
01448
01449
01450
01451
01452
01453
01454
01455 if (!hints)
01456 hints = get_default_hints();
01457
01458 if (hints->maph != WholeMap && hints->maph != SegmentMap)
01459 return statusMake(DATABASE_OPEN_FAILED, "invalid open hints %d",
01460 hints->maph);
01461 #undef PR
01462 #define PR "dbOpen: "
01463
01464 #ifdef TRACE
01465 utshm("ESM_dbOpen(%s)\n", dbfile);
01466 #endif
01467
01468 if (flags != VOLREAD &&
01469 flags != VOLRW)
01470 return statusMake(INVALID_FLAG, PR "flag is invalid: `%d'", flags);
01471
01472 if (se = checkFileAccess(DATABASE_OPEN_FAILED, "shm file", shmfileGet(dbfile), accflags))
01473 return se;
01474
01475 vd = (DbDescription *)m_calloc(sizeof(DbDescription), 1);
01476
01477 #ifndef HAVE_EYEDBSMD
01478 smdcli_conn_t *conn = 0;
01479 #else
01480 smdcli_conn_t *conn = smdcli_open(smd_get_port());
01481 if (!conn) {
01482 free(vd);
01483 return statusMake(ERROR, "cannot connect to eyedbsmd on port "
01484 "%s", smd_get_port());
01485 }
01486 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
01487 if (smdcli_init_getsems(conn, dbfile, vd->semkeys)) {
01488 free(vd);
01489 free(conn);
01490 return statusMake(ERROR, "protocol error with eyedbsmd on port "
01491 "%s", smd_get_port());
01492 }
01493 #else
01494 if (smdcli_init(conn, dbfile)) {
01495 free(vd);
01496 free(conn);
01497 return statusMake(ERROR, "protocol error with eyedbsmd on port "
01498 "%s", smd_get_port());
01499 }
01500 #endif
01501 #endif
01502
01503 if ((shmfd = shmfileOpen(dbfile)) < 0) {
01504 free(vd);
01505 return statusMake(INVALID_SHMFILE_ACCESS, PR "shm file '%s'",
01506 shmfileGet(dbfile));
01507 }
01508
01509 vd->shmfd = shmfd;
01510 vd->conn = conn;
01511
01512 if ((ompfd = objmapfileOpen(dbfile, opf)) < 0) {
01513 free(vd);
01514 return statusMake(INVALID_OBJMAP_ACCESS, PR "objmap file '%s'",
01515 objmapfileGet(dbfile));
01516 }
01517
01518 shmsize = fdSizeGet(shmfd);
01519
01520 if ((se = shmMap(dbfile, shmsize, shmfd, (void **)&vd->shm_addr,
01521 &vd->m_shm)) != Success) {
01522 free(vd);
01523 return se;
01524 }
01525
01526 shm_addr = vd->shm_addr;
01527
01528 if (se = checkFileAccess(DATABASE_OPEN_FAILED, "database file", dbfile, accflags)) {
01529 free(vd);
01530 return se;
01531 }
01532
01533 if ((se = dopen(PR, dbfile, opf, &hdfd, &suser)) != Success) {
01534 free(vd);
01535 return se;
01536 }
01537
01538 DbHeader xdbh;
01539 if (se = syscheckn(PR, read(hdfd, xdbh._addr(), DbHeader_SIZE), DbHeader_SIZE, "")) {
01540 free(vd);
01541 free(dbh);
01542 return se;
01543 }
01544
01545 #ifndef HAVE_EYEDBSMD
01546 if (se = db_clean_shm(dbfile, &vd->lkfd, shmfd)) {
01547 free(vd);
01548 free(dbh);
01549 return se;
01550 }
01551 #endif
01552
01553 dbh = new DbHeader();
01554 x2h_dbHeader(dbh, &xdbh);
01555
01556 if (dbh->__magic() != MAGIC) {
01557 free(vd);
01558 delete dbh;
01559 return statusMake(INVALID_DBFILE, PR "database file '%s' is not a valid eyedbsm database file", dbfile);
01560 }
01561
01562 version = x2h_u32(((DbShmHeader *)shm_addr)->version);
01563
01564 if (pversion && *pversion && version > *pversion) {
01565 char str_version[32];
01566 char str_pversion[32];
01567 strcpy(str_version, string_version(version));
01568 strcpy(str_pversion, string_version(*pversion));
01569 free(vd);
01570 delete dbh;
01571 return statusMake(ERROR, "version of database '%s' (%s) is upper "
01572 "than the EyeDB version (%s): cannot be opened",
01573 dbfile,
01574 str_version, str_pversion);
01575 }
01576
01577
01578 fop = ((flags & VOLREAD) ? PROT_READ : PROT_READ|PROT_WRITE);
01579 vd->dbid = dbh->__dbid();
01580 vd->flags = flags;
01581 vd->rsuser = vd->suser = suser;
01582 vd->hints = *hints;
01583
01584 #ifdef ESM_DBG
01585 printf("FLAGS %d\n", flags);
01586 #endif
01587
01588 if (!(vd->m_dbs = m_mmap(0, DBS_DEFSIZE, fop, MAP_SHARED, hdfd, 0,
01589 (char **)&vd->dbs_addr, dbfile, 0, 0))) {
01590 shmUnmap(dbfile, vd, shmsize);
01591 free(vd);
01592 delete dbh;
01593 return statusMake(MAP_ERROR, "unexpected and unrecoverable mmap error in database opening process: '%s'", dbfile);
01594 }
01595
01596 m_lock(vd->m_dbs);
01597
01598 char pwd[DEFAULT_PWD_SIZE];
01599 se = push_dir(dbfile, pwd, sizeof pwd);
01600 if (se) return se;
01601
01602
01603 for (i = 0; i < dbh->__ndat(); i++) {
01604 if (!*dbh->dat(i).file()) {
01605 vd->m_dmp[i] = 0;
01606 vd->dmp_addr[i] = 0;
01607 continue;
01608 }
01609 const char *dmpfile = dmpfileGet(dbh->dat(i).file());
01610 int fd = open(dmpfile, opf);
01611 if (fd < 0) {
01612 pop_dir(pwd);
01613 return statusMake(DATABASE_OPEN_FAILED,
01614 PR "cannot open data map file '%s' for writing",
01615 dmpfile);
01616 }
01617
01618 size = DMP_SIZE(dbh->dat(i).mp()->mtype(), dbh->dat(i).mp()->nslots());
01619
01620 if (!(vd->m_dmp[i] = m_mmap(0, size, fop, MAP_SHARED, fd, 0,
01621 (char **)&vd->dmp_addr[i],
01622 dmpfileGet(dbh->dat(i).file()), 0, 0))) {
01623 shmUnmap(dbfile, vd, shmsize);
01624 dbsUnmap(dbfile, vd);
01625
01626 free(vd);
01627 delete dbh;
01628 pop_dir(pwd);
01629 perror("mmap");
01630 return statusMake(MAP_ERROR,
01631 "unexpected and unrecoverable mmap error in "
01632 "database opening process (dbfile='%s') for data map file: ", dbfile);
01633 }
01634
01635 m_lock(vd->m_dmp[i]);
01636 if (se = syscheck(PR, close(fd), "")) {
01637 delete dbh;
01638 free(vd);
01639 pop_dir(pwd);
01640 return se;
01641 }
01642 }
01643
01644
01645
01646
01647 size = OIDMAP_SIZE(dbh->__nbobjs());
01648
01649 if (!(vd->m_omp = m_mmap(0, size, fop, MAP_SHARED, ompfd, 0,
01650 (char **)&vd->omp_addr,
01651 objmapfileGet(dbfile), 0, 0))) {
01652 dbsUnmap(dbfile, vd);
01653 shmUnmap(dbfile, vd, shmsize);
01654
01655 free(vd);
01656 delete dbh;
01657 pop_dir(pwd);
01658 return statusMake(MAP_ERROR, "unexpected and unrecoverable mmap error in "
01659 "database opening process (dbfile: '%s') for object map file %s", dbfile,
01660 objmapfileGet(dbfile));
01661 }
01662
01663 m_lock(vd->m_omp);
01664
01665 if (se = syscheck(PR, close(hdfd), "")) {
01666 delete dbh;
01667 free(vd);
01668 pop_dir(pwd);
01669 return se;
01670 }
01671
01672 if (se = syscheck(PR, close(ompfd), "")) {
01673 delete dbh;
01674 free(vd);
01675 pop_dir(pwd);
01676 return se;
01677 }
01678
01679
01680 for (i = 0; i < dbh->__ndat(); i++) {
01681 vd->dmd[i].file = strdup(dbh->dat(i).file());
01682 if (!*dbh->dat(i).file()) {
01683 vd->dmd[i].fd = -1;
01684 continue;
01685 }
01686
01687 Status status;
01688 if (se = checkFileAccess(DATABASE_OPEN_FAILED, "volume file", dbh->dat(i).file(), accflags)) {
01689 delete dbh;
01690 free(vd);
01691 pop_dir(pwd);
01692 return se;
01693 }
01694
01695 if ((status = dopen(PR, dbh->dat(i).file(), opf, &vd->dmd[i].fd,
01696 &vd->suser)) != Success) {
01697 int j;
01698 for (j = 0; j < i; j++)
01699 if (vd->dmd[j].fd >= 0 &&
01700 (se = syscheck(PR, close(vd->dmd[j].fd), ""))) {
01701 delete dbh;
01702 free(vd);
01703 pop_dir(pwd);
01704 return se;
01705 }
01706
01707 delete dbh;
01708 free(vd);
01709 pop_dir(pwd);
01710 return status;
01711 }
01712
01713
01714
01715
01716
01717
01718 if (hints->maph == WholeMap) {
01719 if (!(vd->dmd[i].m_dat = m_mmap(0, (size_t)dbh->dat(i).__maxsize()*ONE_K,
01720 fop, MAP_SHARED, vd->dmd[i].fd, 0,
01721 (char **)&vd->dmd[i].addr,
01722 dbh->dat(i).file(), 0, 0))) {
01723 shmUnmap(dbfile, vd, shmsize);
01724 dbsUnmap(dbfile, vd);
01725 free(vd);
01726 delete dbh;
01727 pop_dir(pwd);
01728 return statusMake(MAP_ERROR,
01729 "unexpected and unrecoverable mmap error in "
01730 "database opening process (dbfile='%s') for data map file: ", dbfile,
01731 dbh->dat(i).file());
01732 }
01733
01734 m_lock(vd->dmd[i].m_dat);
01735 }
01736 else {
01737 vd->dmd[i].m_dat = 0;
01738 vd->dmd[i].addr = 0;
01739
01740 unsigned int mapwide = (hints->mapwide ? hints->mapwide : ESM_MMAP_WIDE_SEGMENT);
01741 vd->mapwide = mapwide * pgsize;
01742 vd->mapwide2 = vd->mapwide >> 1;
01743
01744 }
01745
01746 if (se = syscheck(PR, fcntl(vd->dmd[i].fd, F_SETFD, 1), "")) {
01747 delete dbh;
01748 free(vd);
01749 pop_dir(pwd);
01750 return se;
01751 }
01752 }
01753
01754 if (create_mode) {
01755 ESM_initHost((DbShmHeader *)shm_addr);
01756 ESM_DbInitialize(vd, shm_addr, shmsize);
01757 }
01758
01759 se = ESM_dbOpenPrologue(vd, (DbShmHeader *)shm_addr, shmsize, dbfile, flags,
01760 &xid);
01761
01762 if (se) {
01763 delete dbh;
01764 free(vd);
01765 pop_dir(pwd);
01766 return se;
01767 }
01768
01769 ALIGN4(vd->omp_addr);
01770
01771 *pdbh = (DbHandle *)m_calloc(sizeof(DbHandle), 1);
01772 (*pdbh)->vd = vd;
01773
01774 assert(!pdblock);
01775
01776 if (pdblock)
01777 *pdblock = &((DbShmHeader *)shm_addr)->dblock_W;
01778
01779 if (pversion)
01780 *pversion = x2h_u32(((DbShmHeader *)shm_addr)->version);
01781
01782 (*pdbh)->vd->xid = xid;
01783
01784 (*pdbh)->vd->trs_mh = XMOpen(((char *)shm_addr) + SHM_HEADSIZE, vd);
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800 delete dbh;
01801
01802 (*pdbh)->dbfile = strdup(dbfile);
01803
01804 if (flags == VOLRW) {
01805 se = ESM_transactionsGarbage(*pdbh, True);
01806 if (se) {
01807 pop_dir(pwd);
01808 return se;
01809 }
01810 }
01811
01812
01813
01814 if (DbHeader((*pdbh)->vd->dbs_addr).state() == OPENING_STATE) {
01815 pop_dir(pwd);
01816 return Success;
01817 }
01818
01819 if (se = dbProtectionRunTimeUpdate(*pdbh)) {
01820 pop_dir(pwd);
01821 return se;
01822 }
01823
01824 pop_dir(pwd);
01825 return protectionRunTimeUpdate(*pdbh);
01826 }
01827
01828 int ESM_getOpenFlags(DbHandle const *dbh)
01829 {
01830 return dbh->vd->flags;
01831 }
01832
01833
01834
01835
01836
01837
01838 static Status
01839 ESM_dbCloseEpilogue(DbDescription *vd, DbShmHeader *shmh, unsigned int xid,
01840 int flags, const char *dbfile)
01841 {
01842 Status se;
01843 XMHandle *xmh;
01844
01845 xmh = XMOpen(((char *)shmh) + SHM_HEADSIZE, vd);
01846
01847 if (!xmh)
01848 return statusMake(INVALID_SHMFILE, PR "shm file is not a valid eyedbsm shm file: '%s'", shmfileGet(dbfile));
01849
01850 IDB_LOG(IDB_LOG_DATABASE, ("dbCloseEpilogue(%s) #1\n", dbfile));
01851
01852
01853 shmh->stat.current_db_access_cnt--;
01854
01855
01856 if (se = ESM_transactionsRelease(vd, shmh, dbfile, xid, xmh, 0))
01857 return se;
01858
01859 if (se = shmMutexRelease(vd, shmh, xid))
01860 return se;
01861
01862 IDB_LOG(IDB_LOG_DATABASE, ("dbCloseEpilogue(%s) #2\n", dbfile));
01863
01864 return Success;
01865 }
01866
01867 Status
01868 ESM_dbClose(const DbHandle *dbh)
01869 {
01870 Status se;
01871 int i;
01872
01873 #undef PR
01874 #define PR "dbClose: "
01875
01876 if (!check_dbh(dbh))
01877 return statusMake(INVALID_DB_HANDLE, PR IDBH);
01878
01879 DbHeader _dbh(DBSADDR(dbh));
01880 unsigned int ndat = x2h_u32(_dbh.__ndat());
01881 for (i = 0; i < ndat; i++) {
01882 MmapDesc *mmd, *mmend = &dbh->vd->dmd[i].mmd[MAX_MMAP_SEGMENTS];
01883
01884 if (dbh->vd->m_dmp[i]) {
01885 int mtype = x2h_u16(_dbh.dat(i).mp()->mtype());
01886 int nslots = x2h_u32(_dbh.dat(i).mp()->nslots());
01887 unsigned int size = DMP_SIZE(mtype, nslots);
01888 if (m_munmap(dbh->vd->m_dmp[i], dbh->vd->dmp_addr[i], size))
01889 return statusMake(MAP_ERROR, PR "cannot unmap dmp file");
01890 }
01891
01892 if (dbh->vd->dmd[i].fd >= 0 &&
01893 (se = syscheck(PR, close(dbh->vd->dmd[i].fd), "")))
01894 return se;
01895
01896 for (mmd = dbh->vd->dmd[i].mmd; mmd < mmend; mmd++) {
01897 if (mmd->ismapped)
01898 SEGMENT_UNMAP(mmd);
01899 }
01900 }
01901
01902 unsigned int nbobjs = x2h_u32(_dbh.__nbobjs());
01903 m_munmap(dbh->vd->m_omp, (char *)dbh->vd->omp_addr, OIDMAP_SIZE(nbobjs));
01904
01905
01906
01907
01908
01909 dbsUnmap(dbh->dbfile, dbh->vd);
01910
01911 if (backend)
01912 ESM_dbCloseEpilogue(dbh->vd, (DbShmHeader *)dbh->vd->shm_addr, dbh->vd->xid,
01913 dbh->vd->flags, dbh->dbfile);
01914
01915 if (se = shmUnmap(dbh->dbfile, dbh->vd, fdSizeGet(dbh->vd->shmfd))) {
01916 return se;
01917 }
01918
01919 if (se = syscheck(PR, close(dbh->vd->shmfd), "")) {
01920 return se;
01921 }
01922
01923 #ifndef HAVE_EYEDBSMD
01924 if (!--db_map[dbh->dbfile]) {
01925 if (TRACE_CLEANUP) {
01926 fprintf(stderr, "eyedbsm: closing lockfile map\n");
01927 }
01928
01929 if (se = syscheck(PR, close(dbh->vd->lkfd), "")) {
01930 return se;
01931 }
01932
01933 db_map.erase(dbh->dbfile);
01934 }
01935 #endif
01936
01937 if (dbh->vd->conn) {
01938 smdcli_close(dbh->vd->conn);
01939 }
01940
01941 XMClose(dbh->vd->trs_mh);
01942
01943 free(dbh->vd);
01944 free(dbh->dbfile);
01945 memset((char *)dbh, 0, sizeof(*dbh));
01946 free((char *)dbh);
01947
01948 return Success;
01949 }
01950
01951 int
01952 ESM_dataBaseIdGet(DbHandle const *dbh)
01953 {
01954 return dbh->vd->dbid;
01955 }
01956
01957 int
01958 dbidGet(const Oid *oid)
01959 {
01960 return OIDDBIDGET(oid);
01961 }
01962
01963 void
01964 dbidSet(Oid *oid, int dbid)
01965 {
01966 OIDDBIDMAKE(oid, dbid);
01967 }
01968
01969 Oid::NX
01970 getTotalObjectCount(DbHandle const *dbh)
01971 {
01972 DbHeader _dbh(DBSADDR(dbh));
01973 Oid::NX curobj_cnt = 0;
01974
01975 unsigned int ndat = x2h_u32(_dbh.__ndat());
01976 for (int datid = 0; datid < ndat; datid++) {
01977 if (isDatValid(dbh, datid)) {
01978 MapHeader mp = DAT2MP(dbh, datid);
01979 curobj_cnt += x2h_u32(mp.mstat_u_bmstat_obj_count());
01980 }
01981 }
01982
01983 return curobj_cnt;
01984 }
01985
01986 #define BLKIDXALLOC_INC 10000
01987
01988 Status
01989 nxFileSizeExtends(DbHandle const *dbh, Oid::NX cur_nx)
01990 {
01991 Oid::NX lastidxblkalloc = cur_nx + BLKIDXALLOC_INC;
01992 Oid::NX lastidxbusy = x2h_u32(LASTIDXBUSY(dbh));
01993
01994 char pwd[DEFAULT_PWD_SIZE];
01995 Status status = push_dir(dbh->dbfile, pwd, sizeof pwd);
01996 if (status) return status;
01997
01998 if (lastidxblkalloc < lastidxbusy)
01999 lastidxblkalloc = lastidxbusy + 1;
02000
02001 const char *file = objmapfileGet(dbh->dbfile);
02002 size_t size = OIDMAP_SIZE(lastidxblkalloc);
02003 size_t cursize = fileSizeGet(file);
02004
02005 if (cursize == ~0) {
02006 pop_dir(pwd);
02007 return statusMake(ERROR, "cannot stat file '%s'", file);
02008 }
02009
02010 if (cursize < size) {
02011 if (truncate(file, size) < 0) {
02012 pop_dir(pwd);
02013 return statusMake(ERROR, "nxFileSizeExtends: "
02014 "unexpected error reported by truncate "
02015 "on map file '%s': %s", file, strerror(errno));
02016 }
02017 }
02018
02019 LASTIDXBLKALLOC(dbh) = h2x_u32(lastidxblkalloc);
02020 return pop_dir(pwd);
02021 }
02022
02023 #define BLKNSALLOC_INC (40000/BITS_PER_BYTE)
02024
02025 Status
02026 nsFileSizeExtends(DbHandle const *dbh, short datid, NS curb)
02027 {
02028 NS lastnsblkalloc = curb + BLKNSALLOC_INC;
02029 DbHeader _dbh(DBSADDR(dbh));
02030 const char *file = dmpfileGet(_dbh.dat(datid).file());
02031 size_t size = lastnsblkalloc;
02032
02033 char pwd[DEFAULT_PWD_SIZE];
02034 Status status = push_dir(dbh->dbfile, pwd, sizeof pwd);
02035 if (status) return status;
02036
02037 size_t cursize = fileSizeGet(file);
02038
02039 if (cursize == ~0) {
02040 pop_dir(pwd);
02041 return statusMake(ERROR, "cannot stat file '%s'", file);
02042 }
02043
02044 if (cursize < size) {
02045 if (truncate(file, size) < 0) {
02046 pop_dir(pwd);
02047 return statusMake(ERROR, "nsFileSizeExtends: "
02048 "unexpected error reported by truncate "
02049 "on map file '%s': %s", file, strerror(errno));
02050 }
02051 }
02052
02053 LASTNSBLKALLOC(dbh, datid) = h2x_u32(lastnsblkalloc);
02054 return pop_dir(pwd);
02055 }
02056
02057 Status
02058 objectNumberSet(DbHandle const *dbh, Oid::NX maxobjs)
02059 {
02060 DbHeader _dbh(DBSADDR(dbh));
02061 DbShmHeader *shmh = dbh->vd->shm_addr;
02062
02063 Oid::NX curobj_cnt = getTotalObjectCount(dbh);
02064 if (maxobjs < curobj_cnt)
02065 return statusMake(ERROR,
02066 "objectNumberSet: cannot decrease object number "
02067 "to %d: current object number is %d", maxobjs,
02068 curobj_cnt);
02069
02070 #ifndef NO_FILE_LOCK
02071 #error "NO_FILE_LOCK not defined"
02072 if (!filelockX(dbh->vd->shmfd))
02073 return statusMake(ERROR,
02074 "objectNumberSet: cannot change object number "
02075 "when clients are connected.");
02076 #endif
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091 _dbh.__nbobjs() = h2x_u32(maxobjs);
02092
02093 return Success;
02094 }
02095
02096 Boolean
02097 isDatValid(DbHandle const *dbh, short datid)
02098 {
02099 DbHeader _dbh(DBSADDR(dbh));
02100 return (datid >= 0 && datid < x2h_u32(_dbh.__ndat()) &&
02101 dbh->vd->dmd[datid].fd >= 0) ?
02102 True : False;
02103 }
02104
02105 unsigned int
02106 getDbVersion(void *dbh)
02107 {
02108 return x2h_u32(((DbHandle *)dbh)->vd->shm_addr->version);
02109 }
02110
02111 Boolean
02112 isWholeMapped(void *dbh)
02113 {
02114 return ((DbHandle *)dbh)->vd->hints.maph == WholeMap ? True : False;
02115 }
02116
02117 static Status
02118 dbCleanupRealize(const char *shmfile, int sm_fdshm)
02119 {
02120 caddr_t shm_addr;
02121 Status status;
02122 DbHandle *sm_dbh;
02123 DbHandle *dbh;
02124 DbShmHeader *sm_shmh;
02125 DbHeader *sm_h;
02126 XMHandle *sm_xmh;
02127 size_t sm_shmsize;
02128
02129 sm_shmsize = fdSizeGet(sm_fdshm);
02130
02131 shm_addr = (caddr_t)mmap(0, sm_shmsize, PROT_READ|PROT_WRITE,
02132 MAP_SHARED, sm_fdshm, 0);
02133
02134 if (shm_addr == MAP_FAILED)
02135 return statusMake(ERROR,
02136 "cannot map file '%s' for writing\n", shmfile);
02137
02138 sm_shmh = (DbShmHeader *)shm_addr;
02139 sm_xmh = XMOpen(shm_addr + SHM_HEADSIZE, 0);
02140
02141 unsigned int version = x2h_u32(sm_shmh->version);
02142
02143 DbStat stat = sm_shmh->stat;
02144 cleanup = True;
02145 memset(sm_shmh, 0, sizeof(DbShmHeader));
02146 sm_shmh->magic = MAGIC;
02147 sm_shmh->version = h2x_u32(version ? version : 20508);
02148
02149 sm_shmh->stat = stat;
02150 sm_shmh->stat.current_db_access_cnt = 0;
02151 Mutex mp;
02152 mutexInit(0, &mp, &sm_shmh->main_mp, "SHMMAIN");
02153 ESM_transInit(0, (char *)sm_shmh, sm_shmsize);
02154 DbMutexesInit(0, sm_shmh);
02155
02156 if (sm_xmh)
02157 XMInit(sm_xmh);
02158
02159 ESM_initHost(sm_shmh);
02160
02161 munmap(shm_addr, sm_shmsize);
02162
02163 cleanup = False;
02164
02165 return Success;
02166 }
02167
02168 Status
02169 dbCleanup(const char *dbfile)
02170 {
02171 extern Boolean cleanup;
02172 const char *shmfile = shmfileGet(dbfile);
02173 int fd;
02174
02175 if ((fd = open(dbfile, O_RDWR)) < 0)
02176 return statusMake(ERROR, "cannot open dbfile %s for writing",
02177 dbfile);
02178
02179 close(fd);
02180
02181 fd = open(shmfile, O_RDWR);
02182
02183 if (fd < 0)
02184 return statusMake(ERROR, "cannot open shmfile %s for writing",
02185 shmfile);
02186
02187 #ifndef NO_FILE_LOCK
02188 #error "NO_FILE_LOCK not defined"
02189 if (ut_file_lock(fd, ut_LOCKX, ut_NOBLOCK) < 0 &&
02190 !getenv("EYEDBFORCECLEANUP")) {
02191 close(fd);
02192 return statusMake(CANNOT_LOCK_SHMFILE,
02193 "cannot cleanup shmem file %s: currently used by"
02194 " other clients", shmfile);
02195 }
02196 #endif
02197
02198 Status s = dbCleanupRealize(shmfile, fd);
02199 close(fd);
02200 return s;
02201 }
02202 }