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 namespace eyedbsm {
00029
00030 Boolean
00031 isDspValid(DbHandle const *dbh, short dspid)
00032 {
00033 DbHeader _dbh(DBSADDR(dbh));
00034 return (dspid >= 0 && dspid < x2h_u32(_dbh.__ndsp()) &&
00035 *_dbh.dsp(dspid).name()) ?
00036 True : False;
00037 }
00038
00039 Status
00040 ESM_dspGet(DbHandle const *dbh, const char *dataspace, short *dspid)
00041 {
00042 if (is_number(dataspace))
00043 {
00044 *dspid = atoi(dataspace);
00045 if (!isDspValid(dbh, *dspid))
00046 return statusMake(INVALID_DATASPACE, "invalid dataspace #%d",
00047 *dspid);
00048 return Success;
00049 }
00050
00051 DbHeader _dbh(DBSADDR(dbh));
00052 for (int i = 0; i < MAX_DATASPACES; i++)
00053 if (!strcmp(_dbh.dsp(i).name(), dataspace)) {
00054 *dspid = i;
00055 return Success;
00056 }
00057
00058 return statusMake(INVALID_DATASPACE, "dataspace %s not found",
00059 dataspace);
00060 }
00061
00062 Status
00063 ESM_getDatafile(DbHandle const *dbh, short &dspid, short &datid)
00064 {
00065 Status s;
00066 if (dspid == DefaultDspid) {
00067 s = ESM_dspGetDefault(dbh, &dspid);
00068 if (s) return s;
00069 }
00070
00071 if (!isDspValid(dbh, dspid))
00072 return statusMake(INVALID_DATASPACE, "invalid dataspace #%d", dspid);
00073
00074 DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00075 datid = x2h_16(dsp.__datid(x2h_32(dsp.__cur())));
00076
00077
00078
00079
00080
00081
00082 return Success;
00083 }
00084
00085 Boolean
00086 ESM_getNextDatafile(DbHandle const *dbh, short dspid, short &datid)
00087 {
00088 DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00089 int cur = x2h_32(dsp.__cur());
00090
00091
00092
00093
00094 if (datid != x2h_16(dsp.__datid(cur))) {
00095 fprintf(stderr, "*WARNING*: ESM_getNextDataFile : "
00096 "datid != x2h_16(dsp->__datid[cur]): %d != %d\n", datid,
00097 x2h_16(dsp.__datid(cur)));
00098 }
00099
00100 int ndat = x2h_32(dsp.__ndat());
00101 if (cur == ndat - 1)
00102 return False;
00103
00104
00105
00106
00107 datid = x2h_16(dsp.__datid(++cur));
00108
00109 dsp.__cur() = h2x_32(cur);
00110 return True;
00111 }
00112
00113 Status
00114 ESM_dspSetDefault(DbHandle const *dbh, const char *dataspace,
00115 Boolean fromDbCreate)
00116 {
00117 if (!fromDbCreate) {
00118 CHECK_X(dbh, "setting a default dataspace");
00119 }
00120
00121 short dspid;
00122 Status s = ESM_dspGet(dbh, dataspace, &dspid);
00123 if (s) return s;
00124 DbHeader(DBSADDR(dbh)).__def_dspid() = h2x_16(dspid);
00125 return Success;
00126 }
00127
00128 Status
00129 ESM_dspGetDefault(DbHandle const *dbh, short *dspid)
00130 {
00131 *dspid = x2h_16(DbHeader(DBSADDR(dbh)).__def_dspid());
00132 return Success;
00133 }
00134
00135 static bool findDatafile(DbHandle const *dbh,
00136 const char **datfiles, unsigned int datfile_cnt,
00137 short datid)
00138 {
00139 bool found = false;
00140 for (int n = 0; n < datfile_cnt; n++) {
00141 short datid2, dspid;
00142 Status s = ESM_datCheck(dbh, datfiles[n], &datid2, &dspid);
00143 if (s) {
00144 return false;
00145 }
00146
00147 if (datid2 == datid) {
00148 return true;
00149 }
00150 }
00151
00152 return false;
00153 }
00154
00155 static Status
00156 ESM_dspCheckOrphans(DbHandle const *dbh, const char *op,
00157 short dspid, const char **datfiles,
00158 unsigned int datfile_cnt, short orphan_dspid)
00159 {
00160 DbHeader _dbh(DBSADDR(dbh));
00161
00162 std::vector<short> datid_v;
00163
00164 int ndat = x2h_u32(_dbh.__ndat());
00165 for (short datid = 0; datid < ndat; datid++) {
00166 if (!isDatValid(dbh, datid)) {
00167 continue;
00168 }
00169 short dspid2 = getDataspace(&_dbh, datid);
00170 if (dspid == dspid2) {
00171 bool found = findDatafile(dbh, datfiles, datfile_cnt, datid);
00172
00173 if (found) {
00174 continue;
00175 }
00176
00177 DatafileDesc _dfd = _dbh.dat(datid);
00178 DatafileDesc *dfd = &_dfd;
00179 MapHeader *xmp = dfd->mp();
00180 x2h_prologue(xmp, mp);
00181 if (mp->u_bmh_slot_lastbusy()) {
00182 if (orphan_dspid == DefaultDspid) {
00183 const char *datname = _dbh.dat(datid).name();
00184 char sdatid[8];
00185 sprintf(sdatid, "%d", datid);
00186 return statusMake(INVALID_DATASPACE, "busy datafile %s cannot be "
00187 "untied from dataspace %s",
00188 (*datname ? datname : sdatid),
00189 _dbh.dsp(dspid).name());
00190 }
00191 }
00192 datid_v.push_back(datid);
00193 }
00194 }
00195
00196 std::vector<short>::size_type size = datid_v.size();
00197 if (orphan_dspid != DefaultDspid && size != 0) {
00198 if (orphan_dspid == dspid) {
00199 return statusMake(INVALID_DATASPACE, "datafiles cannot be migrated to their own dataspace %s", _dbh.dsp(dspid).name());
00200 }
00201
00202 DataspaceDesc dsp = _dbh.dsp(orphan_dspid);
00203 unsigned int ndat = x2h_u32(dsp.__ndat());
00204 dsp.__ndat() = h2x_u32(ndat + size);
00205 for (int i = 0; i < size; i++) {
00206 dsp.__datid(ndat+i) = h2x_16(datid_v[i]);
00207 setDataspace(&_dbh, datid_v[i], orphan_dspid);
00208 }
00209 }
00210
00211 return Success;
00212 }
00213
00214
00215 static Status
00216 ESM_dspCreateRealize(DbHandle const *dbh, const char *op,
00217 short dspid, const char *dataspace,
00218 const char **datfiles, unsigned int datfile_cnt,
00219 bool create, short flags, short orphan_dspid)
00220 {
00221 if (datfile_cnt >= MAX_DAT_PER_DSP) {
00222 return statusMake(INVALID_DATAFILE_CNT_IN_DATASPACE,
00223 "%stoo many datafiles in dataspace: %u, maximum is %u",
00224 op, datfile_cnt, MAX_DAT_PER_DSP);
00225 }
00226
00227 DbHeader _dbh(DBSADDR(dbh));
00228 DatType dtype;
00229
00230 if (!create && !flags) {
00231 Status s = ESM_dspCheckOrphans(dbh, op, dspid, datfiles, datfile_cnt, orphan_dspid);
00232 if (s) {
00233 return s;
00234 }
00235 }
00236
00237
00238 short *datid = new short[datfile_cnt];
00239
00240 for (int i = 0; i < datfile_cnt; i++) {
00241 short xdspid;
00242 Status s = ESM_datCheck(dbh, datfiles[i], &datid[i], &xdspid);
00243 if (s) {
00244 delete [] datid;
00245 return s;
00246 }
00247
00248 if (xdspid != DefaultDspid && xdspid != dspid) {
00249 short did = datid[i];
00250 const char *datname = _dbh.dat(did).name();
00251 delete [] datid;
00252 return statusMake(INVALID_DATASPACE, "datafile %s is already "
00253 "tied to the dataspace %s",
00254 (*datname ? datname : datfiles[i]),
00255 _dbh.dsp(xdspid).name());
00256 }
00257
00258 if (!i)
00259 dtype = getDatType(&_dbh, datid[i]);
00260 else if (dtype != getDatType(&_dbh, datid[i])) {
00261 delete [] datid;
00262 return statusMake(INVALID_DATASPACE, "cannot gather different "
00263 "oid type based datafiles into a dataspace");
00264 }
00265 }
00266
00267 DataspaceDesc dsp = _dbh.dsp(dspid);
00268 strcpy(dsp.name(), dataspace);
00269 unsigned int ndat = (flags ? x2h_u32(dsp.__ndat()) : 0);
00270 if (!flags) {
00271 dsp.__cur() = 0;
00272 }
00273
00274 int dat_cnt = 0;
00275 for (int i = 0; i < datfile_cnt; i++) {
00276 short xdatid = h2x_16(datid[i]);
00277 bool found = false;
00278 for (int n = 0; n < ndat+dat_cnt; n++) {
00279 if (dsp.__datid(n) == xdatid) {
00280 found = true;
00281 break;
00282 }
00283 }
00284 if (!found) {
00285 dsp.__datid(ndat+dat_cnt) = xdatid;
00286 setDataspace(&_dbh, datid[i], dspid);
00287 dat_cnt++;
00288 }
00289 }
00290 dsp.__ndat() = h2x_u32(ndat + dat_cnt);
00291
00292 unsigned int ndsp = x2h_32(_dbh.__ndsp());
00293 if (dspid == ndsp) {
00294 ndsp++;
00295 _dbh.__ndsp() = h2x_32(ndsp);
00296 }
00297
00298 delete [] datid;
00299 return Success;
00300 }
00301
00302 Status
00303 ESM_dspSetCurDat(DbHandle const *dbh, const char *dataspace, const char *datfile)
00304 {
00305 CHECK_X(dbh, "setting current datafile to a dataspace");
00306
00307 short dspid;
00308 Status s = ESM_dspGet(dbh, dataspace, &dspid);
00309 if (s) return s;
00310
00311 short datid, xdspid;
00312 s = ESM_datCheck(dbh, datfile, &datid, &xdspid);
00313 if (s) return s;
00314
00315 DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00316
00317 unsigned int ndat = x2h_u32(dsp.__ndat());
00318 for (int i = 0; i < ndat; i++) {
00319 if (x2h_16(dsp.__datid(i)) == datid) {
00320 dsp.__cur() = h2x_32(i);
00321 return Success;
00322 }
00323 }
00324
00325 return statusMake(ERROR, "datafile %s is not tied to "
00326 "to dataspace #%d [%s]",
00327 datfile, dspid, dsp.name());
00328 }
00329
00330 Status
00331 ESM_dspGetCurDat(DbHandle const *dbh, const char *dataspace, short *datid)
00332 {
00333 short dspid;
00334 Status s = ESM_dspGet(dbh, dataspace, &dspid);
00335 if (s) return s;
00336
00337 DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00338
00339 *datid = x2h_16(dsp.__datid(x2h_32(dsp.__cur())));
00340 return Success;
00341 }
00342
00343 Status
00344 ESM_dspCheck(DbHandle const *dbh, const char *dataspace, short *dspid,
00345 short datid[], unsigned int *ndat)
00346 {
00347 Status s = ESM_dspGet(dbh, dataspace, dspid);
00348 if (s) return s;
00349
00350 if (ndat || datid) {
00351 DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(*dspid);
00352 if (ndat) *ndat = x2h_u32(dsp.__ndat());
00353 if (datid) {
00354 unsigned int _ndat = x2h_u32(dsp.__ndat());
00355 for (int i = 0; i < _ndat; i++)
00356 datid[i] = x2h_16(dsp.__datid(i));
00357 }
00358 }
00359
00360 return Success;
00361 }
00362
00363 Status
00364 ESM_dspCreate(DbHandle const *dbh, const char *dataspace,
00365 const char **datfiles, unsigned int datfile_cnt,
00366 Boolean fromDbCreate)
00367 {
00368 if (!fromDbCreate) {
00369 CHECK_X(dbh, "creating a dataspace");
00370 }
00371
00372 short dspid;
00373 Status s = ESM_dspGet(dbh, dataspace, &dspid);
00374 if (!s)
00375 return statusMake(INVALID_DATASPACE, "dataspace already exist %s",
00376 dataspace);
00377
00378 if (strlen(dataspace) >= L_NAME)
00379 return statusMake(INVALID_DATASPACE, "dataspace name %s is too "
00380 "large, maximum size is %d",
00381 dataspace, L_NAME);
00382
00383 for (dspid = 0; dspid < MAX_DATASPACES; dspid++)
00384 if (!isDspValid(dbh, dspid))
00385 break;
00386
00387 #undef PR
00388 #define PR "dspCreate: "
00389 if (dspid == MAX_DATASPACES)
00390 return statusMake(INVALID_DATAFILE_CNT,
00391 PR " dataspace number too large: `%d'",
00392 x2h_u32(DbHeader(DBSADDR(dbh)).__ndsp()));
00393
00394 return ESM_dspCreateRealize(dbh, PR, dspid, dataspace, datfiles, datfile_cnt, true, 0, DefaultDspid);
00395 }
00396
00397 Status
00398 ESM_dspUpdate(DbHandle const *dbh, const char *dataspace,
00399 const char **datfiles, unsigned int datfile_cnt,
00400 short flags, short orphan_dspid)
00401 {
00402 CHECK_X(dbh, "updating a dataspace");
00403
00404 short dspid;
00405 Status s = ESM_dspGet(dbh, dataspace, &dspid);
00406 if (s) return s;
00407
00408 #undef PR
00409 #define PR "dspUpdate: "
00410 return ESM_dspCreateRealize(dbh, PR, dspid, DbHeader(DBSADDR(dbh)).dsp(dspid).name(),
00411 datfiles, datfile_cnt, false, flags, orphan_dspid);
00412 }
00413
00414 Status
00415 ESM_dspDelete(DbHandle const *dbh, const char *dataspace)
00416 {
00417 CHECK_X(dbh, "deleting a dataspace");
00418
00419 short dspid;
00420 Status s = ESM_dspGet(dbh, dataspace, &dspid);
00421 if (s) return s;
00422
00423 short dspid_def;
00424 s = ESM_dspGetDefault(dbh, &dspid_def);
00425 if (s) return s;
00426
00427 DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00428
00429 if (dspid == dspid_def)
00430 return statusMake(ERROR, "cannot delete default dataspace #%d [%s]",
00431 dspid, dsp.name());
00432
00433 unsigned int ndat = x2h_u32(dsp.__ndat());
00434
00435
00436
00437
00438
00439
00440 DbHeader _dbh(DBSADDR(dbh));
00441 for (int i = 0; i < ndat; i++) {
00442 setDataspace(&_dbh, x2h_16(dsp.__datid(i)), DefaultDspid);
00443 }
00444
00445 dsp.__ndat() = 0;
00446 *dsp.name() = 0;
00447
00448 unsigned int ndsp = x2h_u32(_dbh.__ndsp());
00449 if (dspid == ndsp - 1) {
00450 ndsp--;
00451 DbHeader(DBSADDR(dbh)).__ndsp() = h2x_u32(ndsp);
00452 }
00453
00454 return Success;
00455 }
00456
00457 Status
00458 ESM_dspRename(DbHandle const *dbh, const char *dataspace,
00459 const char *dataspace_new)
00460 {
00461 CHECK_X(dbh, "renaming a dataspace");
00462
00463 short dspid;
00464 Status s = ESM_dspGet(dbh, dataspace, &dspid);
00465 if (s) return s;
00466
00467 if (strlen(dataspace_new) >= L_NAME)
00468 return statusMake(INVALID_DATASPACE, "dataspace name %s is too "
00469 "large, maximum size is %d",
00470 dataspace_new, L_NAME);
00471
00472 strcpy(DbHeader(DBSADDR(dbh)).dsp(dspid).name(), dataspace_new);
00473 return Success;
00474 }
00475 }