kern_dsp.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 #include <eyedbconfig.h>
00025 
00026 #include "kern_p.h"
00027 
00028 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   if (!isDatValid(dbh, datid))
00079     return statusMake(INVALID_DATAFILE, "datafile #%d is not valid",
00080                          datpid);
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   // 07/01/05: see below
00092   // could be: if (datid != x2h_16(dsp->__datid[cur])) return False; ??
00093   //assert(datid == x2h_16(dsp->__datid[cur]));
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   // 07/01/05: corrected this bug (see tests/dataspace/bug_dsp.sh)
00105   //datid = x2h_16(dsp->__datid[cur]);
00106   //cur++;
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 Status
00136 ESM_dspCreateRealize(DbHandle const *dbh, const char *op,
00137                     short dspid, const char *dataspace,
00138                     const char **datfiles, unsigned int datfile_cnt)
00139 {
00140   if (datfile_cnt >= MAX_DAT_PER_DSP)
00141     return statusMake(INVALID_DATAFILE_CNT_IN_DATASPACE,
00142                          "%s too many datafiles in dataspace: `%d'", op,
00143                          datfile_cnt);
00144 
00145   short *datid = new short[datfile_cnt];
00146   DbHeader _dbh(DBSADDR(dbh));
00147   DatType dtype;
00148   for (int i = 0; i < datfile_cnt; i++) {
00149     short xdspid;
00150     Status s = ESM_datCheck(dbh, datfiles[i], &datid[i], &xdspid);
00151     if (s) {
00152       delete [] datid;
00153       return s;
00154     }
00155 
00156     if (xdspid != DefaultDspid && xdspid != dspid) {
00157       delete [] datid;
00158       return statusMake(INVALID_DATASPACE, "datafile %s is already "
00159                            "tied to the dataspace %s",
00160                            datfiles[i], _dbh.dsp(xdspid).name());
00161     }
00162 
00163     if (!i)
00164       dtype = getDatType(&_dbh, datid[i]);
00165     else if (dtype != getDatType(&_dbh, datid[i])) {
00166       delete [] datid;
00167       return statusMake(INVALID_DATASPACE, "cannot gather different "
00168                            "oid type based datafiles into a dataspace");
00169     }
00170   }
00171 
00172   DataspaceDesc dsp = _dbh.dsp(dspid);
00173   strcpy(dsp.name(), dataspace);
00174   dsp.__cur() = 0;
00175   dsp.__ndat() = h2x_u32(datfile_cnt);
00176   //memcpy(dsp->__datid, datid, sizeof(short) * datfile_cnt);
00177   for (int i = 0; i < datfile_cnt; i++) {
00178     dsp.__datid(i) = h2x_16(datid[i]);
00179     //DBSADDR(dbh)->dat[datid[i]].__dspid = h2x_16(dspid);
00180     setDataspace(&_dbh, datid[i], dspid);
00181   }
00182 
00183   unsigned int ndsp = x2h_32(_dbh.__ndsp());
00184   if (dspid == ndsp) {
00185     ndsp++;
00186     _dbh.__ndsp() = h2x_32(ndsp);
00187   }
00188 
00189   delete [] datid;
00190   return Success;
00191 }
00192 
00193 Status
00194 ESM_dspSetCurDat(DbHandle const *dbh, const char *dataspace, const char *datfile)
00195 {
00196   CHECK_X(dbh, "setting current datafile to a dataspace");
00197 
00198   short dspid;
00199   Status s = ESM_dspGet(dbh, dataspace, &dspid);
00200   if (s) return s;
00201 
00202   short datid, xdspid;
00203   s = ESM_datCheck(dbh, datfile, &datid, &xdspid);
00204   if (s) return s;
00205   
00206   DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00207 
00208   unsigned int ndat = x2h_u32(dsp.__ndat());
00209   for (int i = 0; i < ndat; i++) {
00210     if (x2h_16(dsp.__datid(i)) == datid) {
00211       dsp.__cur() = h2x_32(i);
00212       return Success;
00213     }
00214   }
00215 
00216   return statusMake(ERROR, "datafile %s is not tied to "
00217                        "to dataspace #%d [%s]",
00218                        datfile, dspid, dsp.name());
00219 }
00220 
00221 Status
00222 ESM_dspGetCurDat(DbHandle const *dbh, const char *dataspace, short *datid)
00223 {
00224   short dspid;
00225   Status s = ESM_dspGet(dbh, dataspace, &dspid);
00226   if (s) return s;
00227 
00228   DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00229 
00230   *datid = x2h_16(dsp.__datid(x2h_32(dsp.__cur())));
00231   return Success;
00232 }
00233 
00234 Status
00235 ESM_dspCheck(DbHandle const *dbh, const char *dataspace, short *dspid,
00236             short datid[], unsigned int *ndat)
00237 {
00238   Status s = ESM_dspGet(dbh, dataspace, dspid);
00239   if (s) return s;
00240 
00241   if (ndat || datid) {
00242     DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(*dspid);
00243     if (ndat) *ndat = x2h_u32(dsp.__ndat());
00244     if (datid) {
00245       unsigned int _ndat = x2h_u32(dsp.__ndat());
00246       for (int i = 0; i < _ndat; i++)
00247         datid[i] = x2h_16(dsp.__datid(i));
00248     }
00249   }
00250 
00251   return Success;
00252 }
00253 
00254 Status
00255 ESM_dspCreate(DbHandle const *dbh, const char *dataspace,
00256              const char **datfiles, unsigned int datfile_cnt,
00257              Boolean fromDbCreate)
00258 {
00259   if (!fromDbCreate) {
00260     CHECK_X(dbh, "creating a dataspace");
00261   }
00262 
00263   short dspid;
00264   Status s = ESM_dspGet(dbh, dataspace, &dspid);
00265   if (!s)
00266     return statusMake(INVALID_DATASPACE, "dataspace already exist %s",
00267                          dataspace);
00268 
00269   if (strlen(dataspace) >= L_NAME)
00270     return statusMake(INVALID_DATASPACE, "dataspace name %s is too "
00271                          "large, maximum size is %d",
00272                          dataspace, L_NAME);
00273 
00274   for (dspid = 0; dspid < MAX_DATASPACES; dspid++)
00275     if (!isDspValid(dbh, dspid))
00276       break;
00277 
00278 #undef PR
00279 #define PR "dspCreate: "
00280   if (dspid == MAX_DATASPACES)
00281     return statusMake(INVALID_DATAFILE_CNT,
00282                          PR " dataspace number too large: `%d'",
00283                          x2h_u32(DbHeader(DBSADDR(dbh)).__ndsp()));
00284 
00285   return ESM_dspCreateRealize(dbh, PR, dspid, dataspace, datfiles, datfile_cnt);
00286 }
00287 
00288 Status
00289 ESM_dspUpdate(DbHandle const *dbh, const char *dataspace,
00290              const char **datfiles, unsigned int datfile_cnt)
00291 {
00292   CHECK_X(dbh, "updating a dataspace");
00293 
00294   short dspid;
00295   Status s = ESM_dspGet(dbh, dataspace, &dspid);
00296   if (s) return s;
00297 
00298 #undef PR
00299 #define PR "dspUpdate: "
00300   return ESM_dspCreateRealize(dbh, PR, dspid, DbHeader(DBSADDR(dbh)).dsp(dspid).name(),
00301                              datfiles, datfile_cnt);
00302 }
00303 
00304 Status
00305 ESM_dspDelete(DbHandle const *dbh, const char *dataspace)
00306 {
00307   CHECK_X(dbh, "deleting a dataspace");
00308 
00309   short dspid;
00310   Status s = ESM_dspGet(dbh, dataspace, &dspid);
00311   if (s) return s;
00312 
00313   short dspid_def;
00314   s = ESM_dspGetDefault(dbh, &dspid_def);
00315   if (s) return s;
00316 
00317   DataspaceDesc dsp = DbHeader(DBSADDR(dbh)).dsp(dspid);
00318 
00319   if (dspid == dspid_def)
00320     return statusMake(ERROR, "cannot delete default dataspace #%d [%s]",
00321                          dspid, dsp.name());
00322 
00323   unsigned int ndat = x2h_u32(dsp.__ndat());
00324   /*
00325   for (int i = 0; i < ndat; i++)
00326     DBSADDR(dbh)->dat[x2h_16(dsp->__datid[i])].__dspid =
00327       h2x_32(DefaultDspid);
00328   */
00329 
00330   DbHeader _dbh(DBSADDR(dbh));
00331   for (int i = 0; i < ndat; i++) {
00332     setDataspace(&_dbh, x2h_16(dsp.__datid(i)), DefaultDspid);
00333   }
00334 
00335   dsp.__ndat() = 0;
00336   *dsp.name() = 0;
00337 
00338   unsigned int ndsp = x2h_u32(_dbh.__ndsp());
00339   if (dspid == ndsp - 1) {
00340     ndsp--;
00341     DbHeader(DBSADDR(dbh)).__ndsp() = h2x_u32(ndsp);
00342   }
00343 
00344   return Success;
00345 }
00346 
00347 Status
00348 ESM_dspRename(DbHandle const *dbh, const char *dataspace,
00349              const char *dataspace_new)
00350 {
00351   CHECK_X(dbh, "renaming a dataspace");
00352 
00353   short dspid;
00354   Status s = ESM_dspGet(dbh, dataspace, &dspid);
00355   if (s) return s;
00356 
00357   if (strlen(dataspace_new) >= L_NAME)
00358     return statusMake(INVALID_DATASPACE, "dataspace name %s is too "
00359                          "large, maximum size is %d",
00360                          dataspace_new, L_NAME);
00361 
00362   strcpy(DbHeader(DBSADDR(dbh)).dsp(dspid).name(), dataspace_new);
00363   return Success;
00364 }
00365 
00366 }

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