kern_omp.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 //#define NX_TRACE
00029 //#define DSP_INVALID_OID
00030 #define SKIP_NX_LOCK
00031 
00032 namespace eyedbsm {
00033 
00034 void
00035 oidCopySlot_(DbHandle const *dbh, Oid::NX nx, const OidLoc &oidloc,
00036              Oid *oid, unsigned int *psize)
00037 {
00038   MmapH hdl;
00039   ObjectHeader *objh;
00040 
00041   objh = (ObjectHeader *)
00042     slot2addr(dbh, oidloc.ns, oidloc.datid,
00043                  sizeof(ObjectHeader), (char **)&objh, &hdl, 0);
00044   oid->setNX(nx);
00045 
00046   oid->setUnique(x2h_u32(objh->unique));
00047 
00048   if (psize)
00049     *psize = x2h_u32(objh->size);
00050 
00051   /*
00052   printf("UNIQUE %u %u size=%d ns=%d datid=%d\n", oid->unique, objh->unique,
00053          objh->size, oidloc.ns, oidloc.datid);
00054   */
00055   hdl_release(&hdl);
00056   OIDDBIDMAKE(oid, dbh->vd->dbid);
00057 }
00058 
00059 void oidCopySlot(DbHandle const *dbh, Oid::NX nx, Oid *oid, unsigned int *psize)
00060 {
00061   oidCopySlot_(dbh, nx, oidLocGet_(dbh, nx), oid, psize);
00062 }
00063 
00064 NS
00065 oidLastSlotGet(DbHandle const *dbh, const OidLoc &oidloc)
00066 {
00067   MapHeader t_mp = DAT2MP(dbh, oidloc.datid);
00068   MapHeader *mp = &t_mp;
00069 
00070   MmapH hdl;
00071   ObjectHeader *objh;
00072 
00073   objh = (ObjectHeader *)
00074     slot2addr(dbh, oidloc.ns, oidloc.datid,
00075                  sizeof(ObjectHeader), (char **)&objh, &hdl, 0);
00076 
00077   NS lastslot = SZ2NS_XDR(x2h_u32(objh->size), mp) - 1 + oidloc.ns;
00078   hdl_release(&hdl);
00079   return lastslot;
00080 }
00081 
00082 Status
00083 nxAlloc(DbHandle const *const dbh, const OidLoc &oidloc_, Oid::NX *pnx)
00084 {
00085   Mutex *mt = NX_MTX(dbh);
00086   unsigned int xid = dbh->vd->xid;
00087   Oid::NX i;
00088   Oid::NX start, end;
00089   TransactionContext *trctx = DBH2TRCTX(dbh);
00090 
00091   if (NEED_LOCK(trctx))
00092     MUTEX_LOCK_VOID(mt, xid);
00093 
00094   start = x2h_u32(CURIDXBUSY(dbh));
00095   end = x2h_u32(DbHeader(DBSADDR(dbh)).__nbobjs());
00096 
00097   for (;;) {
00098     void *omp_addr = OIDLOC(dbh->vd->omp_addr, start);
00099     for (i = start; i < end; i++) {
00100       if (i >= x2h_u32(LASTIDXBLKALLOC(dbh))) {
00101         Status se;
00102         if (se = nxFileSizeExtends(dbh, i)) {
00103           if (NEED_LOCK(trctx))
00104             MUTEX_UNLOCK(mt, xid);
00105           return se;
00106         }
00107 
00108       }
00109 
00110       OidLoc oidloc;
00111       x2h_oidloc(&oidloc, omp_addr);
00112       if (!oidloc.ns) {
00113         oidloc.ns = oidloc_.ns+NS_OFFSET;
00114         oidloc.datid = oidloc_.datid;
00115 #ifdef NX_TRACE
00116         printf("nxAlloc(%d) -> %d %d\n", i, oidloc_.ns, oidloc_.datid);
00117 #endif
00118         assert(oidloc.datid >= 0);
00119         if (x2h_u32(LASTIDXBUSY(dbh)) < i+1) {
00120           LASTIDXBUSY(dbh) = h2x_u32(i+1);
00121         }
00122 
00123         CURIDXBUSY(dbh) = h2x_u32(i+1);
00124         h2x_oidloc(omp_addr, &oidloc);
00125 
00126         if (NEED_LOCK(trctx))
00127           MUTEX_UNLOCK(mt, xid);
00128 
00129         *pnx = i;
00130         return Success;
00131       }
00132       omp_addr = NEXT_OIDLOC(omp_addr);
00133     }
00134 
00135     if (!start) {
00136       CURIDXBUSY(dbh) = h2x_u32(i);
00137       if (NEED_LOCK(trctx))
00138         MUTEX_UNLOCK(mt, xid);
00139       *pnx = Oid::INVALID_NX;
00140       return Success;
00141     }
00142     
00143     // changed the 21/08/01 (and improved after) because of a catastrophic
00144     // performance in EMBL import when object number limit has been reached!
00145 
00146     CURIDXBUSY(dbh) = 0;
00147     start = 0;
00148     end = x2h_u32(LASTIDXBUSY(dbh));
00149   }
00150 
00151   return Success;
00152 }
00153 
00154 void
00155 nxFree(DbHandle const *const dbh, Oid::NX nx)
00156 {
00157   Mutex *mt = NX_MTX(dbh);
00158   unsigned int xid = dbh->vd->xid;
00159   OidLoc oidloc;
00160   TransactionContext *trctx = DBH2TRCTX(dbh);
00161 
00162 #ifndef SKIP_NX_LOCK
00163   //printf("nxFree:: locking NX\n");
00164   if (NEED_LOCK(trctx))
00165     MUTEX_LOCK_VOID(mt, xid);
00166 #endif
00167 
00168   oidloc.ns = 0;
00169   oidloc.datid = -1;
00170 
00171   h2x_oidloc(OIDLOC(dbh->vd->omp_addr, nx), &oidloc);
00172 
00173 #ifdef NX_TRACE
00174   printf("nxFree(%d)\n", nx);
00175 #endif
00176 
00177 #ifndef SKIP_NX_LOCK
00178   if (NEED_LOCK(trctx))
00179     MUTEX_UNLOCK(mt, xid);
00180 #endif
00181 }
00182 
00183 void
00184 nxSet(DbHandle const *const dbh, Oid::NX nx, NS ns, short datid)
00185 {
00186   Mutex *mt = NX_MTX(dbh);
00187   unsigned int xid = dbh->vd->xid;
00188   OidLoc oidloc;
00189   TransactionContext *trctx = DBH2TRCTX(dbh);
00190 
00191 #ifndef SKIP_NX_LOCK
00192   //printf("nxSet: locking NX\n");
00193   if (NEED_LOCK(trctx))
00194     MUTEX_LOCK_VOID(mt, xid);
00195 #endif
00196 
00197   oidloc.ns = ns+NS_OFFSET;
00198   oidloc.datid = datid;
00199 
00200   h2x_oidloc(OIDLOC(dbh->vd->omp_addr, nx), &oidloc);
00201 
00202 #ifdef NX_TRACE
00203   printf("nxSet(%d) -> %d %d\n", nx, ns, datid);
00204 #endif
00205 
00206 #ifndef SKIP_NX_LOCK
00207   if (NEED_LOCK(trctx))
00208     MUTEX_UNLOCK(mt, xid);
00209 #endif
00210 }
00211 
00212 Oid::NX
00213 nxNextBusyGet(DbHandle const *const dbh, Oid::NX nx)
00214 {
00215   Oid::NX lastidxbusy, i;
00216   Mutex *mt = NX_MTX(dbh);
00217   unsigned int xid = dbh->vd->xid;
00218   TransactionContext *trctx = DBH2TRCTX(dbh);
00219 
00220   if (NEED_LOCK(trctx))
00221     MUTEX_LOCK_VOID(mt, xid);
00222 
00223   lastidxbusy = x2h_u32(LASTIDXBUSY(dbh));
00224 
00225   void *omp_addr = OIDLOC(dbh->vd->omp_addr, nx);
00226   for (i = nx; i < lastidxbusy; i++)
00227     {
00228       OidLoc oidloc;
00229       x2h_oidloc(&oidloc, omp_addr);
00230 
00231       if (oidloc.ns)
00232         {
00233           if (NEED_LOCK(trctx))
00234             MUTEX_UNLOCK(mt, xid);
00235           return i;
00236         }
00237       omp_addr = NEXT_OIDLOC(omp_addr);
00238     }
00239 
00240   if (NEED_LOCK(trctx))
00241     MUTEX_UNLOCK(mt, xid);
00242   return Oid::INVALID_NX;
00243 }
00244 
00245 Status
00246 ESM_objectLocationGet(DbHandle const *dbh, const Oid *oid,
00247                      ObjectLocation *objloc)
00248 {
00249   OidLoc oidloc = oidLocGet(dbh, oid);
00250   if (oidloc.ns == INVALID_NS)
00251     return statusMake(INVALID_OID, "oid %s is invalid",
00252                          getOidString(oid));
00253   unsigned int size;
00254   // EV : 9/03/06 changed LockS to DefaultLock
00255   //Status s = ESM_objectSizeGet(dbh, &size, LockS, oid, OPDefault);
00256   Status s = ESM_objectSizeGet(dbh, &size, DefaultLock, oid, OPDefault);
00257   if (s) return s;
00258 
00259   DbHeader _dbh(DBSADDR(dbh));
00260   unsigned int sizeslot = x2h_u32(_dbh.dat(oidloc.datid).mp()->sizeslot());
00261   unsigned long long offset = oidloc.ns * sizeslot;
00262 
00263   objloc->is_valid = isValidObject(size) ? True : False;
00264 
00265   if (!objloc->is_valid)
00266     objloc->size = 0;
00267   else
00268     objloc->size = size;
00269   size += sizeof(ObjectHeader); // added the 26/07/01
00270   objloc->datid = oidloc.datid;
00271   objloc->dspid = getDataspace(&_dbh, oidloc.datid);
00272   objloc->slot_start_num = oidloc.ns;
00273   objloc->slot_end_num = oidloc.ns + (size-1)/sizeslot;
00274   unsigned int nsize = (objloc->slot_end_num - objloc->slot_start_num + 1) * sizeslot;
00275   objloc->dat_start_pagenum = offset>>pgsize_pow2;
00276   objloc->dat_end_pagenum = (offset+nsize-1)>>pgsize_pow2;
00277   if (isPhy(dbh, oid)) {
00278     objloc->omp_start_pagenum = ~0;
00279     objloc->omp_end_pagenum = ~0;
00280   } else {
00281     objloc->omp_start_pagenum = (oid->getNX() * OIDLOCSIZE)>>pgsize_pow2;
00282     objloc->omp_end_pagenum = (((oid->getNX() * OIDLOCSIZE)+OIDLOCSIZE)-1)>>pgsize_pow2;
00283   }
00284   objloc->dmp_start_pagenum = ((objloc->slot_start_num)/8)>>pgsize_pow2;
00285   objloc->dmp_end_pagenum = (((objloc->slot_end_num)/8))>>pgsize_pow2;
00286   return Success;
00287 }
00288 
00289 Status
00290 ESM_objectsLocationGet(DbHandle const *dbh, const Oid *oid,
00291                       ObjectLocation *objloc, unsigned int oid_cnt)
00292 {
00293   Status s;
00294   for (int i = 0; i < oid_cnt; i++)
00295     if (s = ESM_objectLocationGet(dbh, &oid[i], &objloc[i]))
00296       return s;
00297 
00298   return Success;
00299 }
00300 
00301 OidLoc
00302 oidLocGet(DbHandle const *const dbh, const Oid *oid)
00303 {
00304   if (isPhy(dbh, oid)) {
00305     OidLoc oidloc;
00306     getPhyInfo(oid, &oidloc.ns, &oidloc.datid);
00307     return oidloc;
00308   }
00309   return oidLocGet_(dbh, oid->getNX());
00310 }
00311 
00312 OidLoc
00313 oidLocGet_(DbHandle const *const dbh, Oid::NX nx)
00314 {
00315   Mutex *mt = NX_MTX(dbh);
00316   unsigned int xid = dbh->vd->xid;
00317   NS ns;
00318   TransactionContext *trctx = DBH2TRCTX(dbh);
00319 
00320   /* lock is really needed?? */
00321 #ifndef SKIP_NX_LOCK
00322   //printf("oidLocGet_:: locking NX\n");
00323   if (NEED_LOCK(trctx))
00324     MUTEX_LOCK_VOID(mt, xid);
00325 #endif
00326 
00327   OidLoc oidloc;
00328   memset(&oidloc, 0, sizeof(oidloc)); // added the 21/05/01 to make purify happy
00329 
00330   if (nx == Oid::INVALID_NX || nx > x2h_u32(LASTIDXBUSY(dbh)))
00331     {
00332 #ifndef SKIP_NX_LOCK
00333       if (NEED_LOCK(trctx))
00334         MUTEX_UNLOCK(mt, xid);
00335 #endif
00336       oidloc.ns = INVALID_NS;
00337       oidloc.datid = -1;
00338       return oidloc;
00339     }
00340 
00341   x2h_oidloc(&oidloc, OIDLOC(dbh->vd->omp_addr, nx));
00342 
00343   oidloc.ns -= NS_OFFSET;
00344 
00345 #ifndef SKIP_NX_LOCK
00346   if (NEED_LOCK(trctx))
00347     MUTEX_UNLOCK(mt, xid);
00348 #endif
00349 
00350 #if 0
00351   if (oidloc.datid < 0)
00352     {
00353       printf("very strange oidloc [%p] 0x%x, %d for nx=%d\n",
00354              dbh->vd->omp_addr, oidloc.ns, oidloc.datid, nx);
00355       for (int i = nx-1; i >= nx-40; i--) {
00356         x2h_oidloc(&oidloc, OIDLOC(dbh->vd->omp_addr, i));
00357         if (oidloc.datid < 0)
00358           printf("-> very strange oidloc [%p] 0x%x, %d for nx=%d\n",
00359                  dbh->vd->omp_addr, oidloc.ns, oidloc.datid, i);
00360         else
00361           printf("-> ok for nx=%d\n", i);
00362       }
00363     }
00364   else
00365     printf("oidloc [%p] 0x%x, %d for nx=%d\n",
00366            dbh->vd->omp_addr, oidloc.ns, oidloc.datid, nx);
00367 #endif
00368   return oidloc;
00369 }
00370 
00371 void
00372 ESM_oidsTrace(DbHandle const *const dbh, ESM_oidsTraceAction action, FILE *fd)
00373 {
00374   //DbHeader *h = dbh->vd->dbs_addr;
00375   void *omp_addr = dbh->vd->omp_addr;
00376   int cnt = 0;
00377   Oid oid, nextoid;
00378   Boolean found;
00379 
00380   ESM_firstOidGet_omp(dbh, &oid, &found);
00381 
00382   while (found)
00383     {
00384       if (action == ESM_allOids)
00385         fprintf(fd, "%s\n", getOidString(&oid));
00386       cnt++;
00387       ESM_nextOidGet_omp(dbh, &oid, &nextoid, &found);
00388       oid = nextoid;
00389     }
00390 
00391   fprintf(fd, "Total Oid Count   %d\n", cnt);
00392 }
00393 
00394 Status
00395 ESM_nextOidGetDat_omp(DbHandle const *dbh, short datid,
00396                      Oid *nextoid, Boolean *found)
00397 {
00398   for (;;) {
00399     OidLoc oidloc = oidLocGet(dbh, nextoid);
00400     if (oidloc.datid == datid) {
00401       *found = True;
00402       return Success;
00403     }
00404 
00405     Status s = ESM_nextOidGet_omp(dbh, nextoid, nextoid, found);
00406     if (s || !*found) return s;
00407   }
00408 }
00409 
00410 Status
00411 ESM_firstOidDatGet(DbHandle const *dbh, short datid, Oid *oid,
00412                   Boolean *found)
00413 {
00414   DbHeader _dbh(DBSADDR(dbh));
00415   if (getDatType(&_dbh, datid) == PhysicalOidType)
00416     return ESM_firstOidGet_map(dbh, datid, oid, found);
00417   
00418   Status s = ESM_firstOidGet_omp(dbh, oid, found);
00419   if (s || !*found) return s;
00420   return ESM_nextOidGetDat_omp(dbh, datid, oid, found);
00421 }
00422 
00423 Status
00424 ESM_nextOidDatGet(DbHandle const *dbh, short datid,
00425                  Oid const *const baseoid,
00426                  Oid *nextoid, Boolean *found)
00427 {
00428   DbHeader _dbh(DBSADDR(dbh));
00429   if (getDatType(&_dbh, datid) == PhysicalOidType)
00430     return ESM_nextOidGet_map(dbh, datid, baseoid, nextoid, found);
00431 
00432   Status s = ESM_nextOidGet_omp(dbh, baseoid, nextoid, found);
00433   if (s || !*found) return s;
00434   return ESM_nextOidGetDat_omp(dbh, datid, nextoid, found);
00435 }
00436 
00437 Status
00438 ESM_firstOidGet_omp(DbHandle const *dbh, Oid *oid, Boolean *found)
00439 {
00440   Oid::NX nx;
00441 
00442   *found = False;
00443 
00444   if (!check_dbh(dbh))
00445     return statusMake_s(INVALID_DB_HANDLE);
00446 
00447   if ((nx = nxNextBusyGet(dbh, 0)) == Oid::INVALID_NX)
00448     return Success;
00449 
00450   oidCopySlot(dbh, nx, oid, 0);
00451   *found = True;
00452   return Success;
00453 }
00454 
00455 Status
00456 ESM_nextOidGet_omp(DbHandle const *dbh, Oid const *const baseoid,
00457                    Oid *nextoid, Boolean *found)
00458 {
00459   Oid::NX nx;
00460 
00461   *found = False;
00462   if (!check_dbh(dbh))
00463     return statusMake_s(INVALID_DB_HANDLE);
00464 
00465   if (!check_oid(dbh, baseoid))
00466     return statusMake(INVALID_OID, "%s", getOidString(baseoid));
00467 
00468   if ((nx = nxNextBusyGet(dbh, baseoid->getNX()+1)) == Oid::INVALID_NX)
00469     return Success;
00470 
00471   oidCopySlot(dbh, nx, nextoid, 0);
00472   *found = True;
00473   return Success;
00474 }
00475 
00476 static int no_unique_check = getenv("NO_UNIQUE_CHECK") ? 1 : 0;
00477 
00478 ObjectHeader *
00479 oid2objh_(const Oid *oid, NS ns, short datid, const DbHandle *dbh,
00480              ObjectHeader **objh, MmapH *hdl, int *up,
00481              Boolean *oid2addr_failed)
00482 {
00483   ObjectHeader *hdr;
00484   ObjectHeader *xobjh = (ObjectHeader *)
00485     oid2addr_(ns, datid, dbh, sizeof(ObjectHeader), objh, hdl, up);
00486 
00487   *oid2addr_failed = (xobjh ? False : True);
00488 
00489   /*
00490   printf("UNIQUE_1 %x %x %x\n", xobjh->unique, x2h_u32(xobjh->unique),
00491          oid->unique);
00492   */
00493 
00494   hdr = (!xobjh || (x2h_u32(xobjh->unique) != oid->getUnique()) ? 0 : xobjh);
00495 
00496   if (!hdr) {
00497 #ifdef DSP_INVALID_OID
00498     display_invalid_oid(oid, xobjh);
00499 #endif
00500     if (no_unique_check)
00501       hdr = xobjh;
00502   }
00503 
00504   if (!hdr && xobjh)
00505     hdl_release(hdl);
00506   return hdr;
00507 }
00508 
00509 ObjectHeader *
00510 oid2objh(const Oid *oid, const DbHandle *dbh, ObjectHeader **objh,
00511             MmapH *hdl, Boolean *oid2addr_failed)
00512 {
00513   ObjectHeader *hdr;
00514   ObjectHeader *xobjh = (ObjectHeader *)
00515     oid2addr(oid, dbh, sizeof(ObjectHeader), objh, hdl);
00516 
00517   *oid2addr_failed = (xobjh ? False : True);
00518 
00519   hdr = (!xobjh || (x2h_u32(xobjh->unique) != oid->getUnique()) ? 0 : xobjh);
00520 
00521 #ifdef DSP_INVALID_OID
00522   if (!hdr)
00523     display_invalid_oid(oid, xobjh);
00524 #endif
00525 
00526   if (!hdr && xobjh)
00527     hdl_release(hdl);
00528   return hdr;
00529 }
00530 
00531 int
00532 check_oid(const DbHandle *dbh, const Oid *oid)
00533 {
00534   OidLoc oidloc = oidLocGet(dbh, oid);
00535   if (oidloc.ns == INVALID_NS || !isDatValid(dbh, oidloc.datid) ||
00536       OIDDBIDGET(oid) != dbh->vd->dbid)
00537     return 0;
00538   return 1;
00539 }
00540 
00541 extern int
00542 oidloc_cmp(const OidLoc &ol1, const OidLoc &ol2)
00543 {
00544   return ol1.ns == ol2.ns && ol1.datid == ol2.datid;
00545 }
00546 
00547 }

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