ExecutableCache.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 
00025 #define _IDB_KERN_
00026 #include <assert.h>
00027 #include <dlfcn.h>
00028 #include "eyedb_p.h"
00029 #include "kernel_p.h"
00030 #include "DBM_Database.h"
00031 
00032 #include "serv_lib.h"
00033 #include "kernel.h"
00034 #include "ExecutableCache.h"
00035 
00036 namespace eyedb {
00037 
00038   // ---------------------------------------------------------------------------
00039   //
00040   // Backend Methods
00041   //
00042   // ---------------------------------------------------------------------------
00043 
00044   RPCStatus
00045   IDB_execCheck(DbHandle *, const char *intname, const eyedbsm::Oid *oid,
00046                 const char *extref)
00047   {
00048     //  printf("EXEC CHECK BACKEND %s %s\n", intname, extref);
00049     return RPCSuccess;
00050   }
00051 
00052 
00053   extern RPCStatus
00054   IDB_checkDBAuth(ConnHandle *ch, const char *dbmdb,
00055                   const char *dbname, const char *&userauth,
00056                   const char *&passwdauth, DBAccessMode dbmode,
00057                   Bool, int *, DBM_Database **pdbm, const char *msg);
00058 
00059   static RPCStatus
00060   checkAuth(Database *db, const char *userauth, const char *passwdauth)
00061   {
00062     return IDB_checkDBAuth(db->getConnection()->getConnHandle(),
00063                            db->getDBMDB(),
00064                            db->getName(),
00065                            userauth,
00066                            passwdauth,
00067                            ExecDBAccessMode,
00068                            False,
00069                            NULL,
00070                            0,
00071                            "execute method in backend");
00072   }
00073 
00074   //#define USE_GBXCONTEXT
00075 
00076   RPCStatus
00077   IDB_execExecute(DbHandle *dbh,
00078                   const char *userauth, const char *passwdauth,
00079                   const char *intname,
00080                   const char *name,
00081                   int exec_type,
00082                   const eyedbsm::Oid *cloid,
00083                   const char *extref,
00084                   const void *xsign, const void *sign_data,
00085                   const eyedbsm::Oid *execoid,
00086                   const eyedbsm::Oid *xobjoid,
00087                   void *xo,
00088                   const void *xargarray, void *argarray_data,
00089                   void *xargret, void *argarrayret_data)
00090   {
00091     Database *db = (Database *)dbh->db;
00092     RPCStatus rpc_status;
00093 #ifdef USE_GBXCONTEXT
00094     gbxContext _;
00095 #endif
00096     int isStaticExec = (exec_type & STATIC_EXEC);
00097     exec_type &= ~STATIC_EXEC;
00098 
00099     if (!dbh->exec_auth) {
00100       rpc_status = checkAuth(db, userauth, passwdauth);
00101       if (!rpc_status)
00102         dbh->exec_auth = 1;
00103     }
00104     else
00105       rpc_status = RPCSuccess;
00106 
00107     if (rpc_status)
00108       {
00109         if (argarrayret_data)
00110           {
00111             Argument arg;
00112             rpc_Data *data = (rpc_Data *)argarrayret_data;
00113             data->size = 0;
00114             data->data = NULL;
00115             code_argument(argarrayret_data, (const void *)&arg);
00116           }
00117         return rpc_status;
00118       }
00119 
00120     ArgArray *argarray = 0;
00121     Signature *sign = 0;
00122     ExecutableItem *item;
00123     Status status = Success;
00124     Argument arg;
00125     Argument *parg = (argarrayret_data ? &arg : (Argument *)xargret);
00126     Oid objoid(xobjoid);
00127     Object *o = (Object *)xo;
00128 
00129     if (argarray_data)
00130       decode_arg_array(db, argarray_data, (void **)&argarray, True);
00131     else
00132       argarray = (ArgArray *)xargarray;
00133 
00134     if (sign_data)
00135       {
00136         sign = new Signature();
00137         decode_signature(sign_data, (void *)sign);
00138       }
00139     else
00140       sign = (Signature *)xsign;
00141 
00142     if (!(item = db->exec_cache->get(intname)))
00143       {
00144         item = new ExecutableItem(db, intname, name, exec_type, isStaticExec,
00145                                   cloid,
00146                                   extref, sign, execoid);
00147         if (status = item->check())
00148           {
00149             delete item;
00150             goto out;
00151           }
00152         db->exec_cache->insert(item);
00153       }
00154  
00155     if (objoid.isValid() && !o)
00156       {
00157         status = db->loadObject(&objoid, &o);
00158         if (status)
00159           goto out;
00160       }
00161 
00162     status = item->execute(o, argarray, parg);
00163 
00164 #define NO_EXEC_CHECK
00165 
00166 #ifndef NO_EXEC_CHECK
00167     if (!status) {
00168       const char *which = "method";
00169       status = eyedb_CHECKArgument(db, *sign->getRettype(), *parg,
00170                                    which, name, "return");
00171       if (!status)
00172         status = eyedb_CHECKArguments(db, sign, *argarray, which,
00173                                       name, OUT_ARG_TYPE);
00174     }
00175 #endif
00176 
00177   out:
00178 
00179     if (argarrayret_data)
00180       {
00181         code_arg_array(argarrayret_data, argarray);
00182         code_argument(argarrayret_data, (const void *)&arg);
00183       }
00184     else
00185       {
00186         //*(Argument *)xargret = arg;
00187 #ifdef USE_GBXCONTEXT
00188         ((Argument *)xargret)->keep();
00189         ((Argument *)xargret)->getType()->keep();
00190 #endif
00191       }
00192   
00193 #ifdef USE_GBXCONTEXT
00194     if (!status && (db->isLocal() || db->getUserData() == IDB_LOCAL_CALL))
00195       _.keepObjs();
00196 #endif
00197     
00198 #ifndef USE_GBXCONTEXT
00199     if (argarray_data && argarray)
00200       argarray->release();
00201     if (sign_data && sign)
00202       sign->release();
00203 #endif
00204     return rpcStatusMake(status);
00205   }
00206 
00207   RPCStatus
00208   IDB_execSetExtRefPath(const char *user, const char *passwd, const char *path)
00209   {
00210     // not yet implemented
00211     return RPCSuccess;
00212   }
00213 
00214   RPCStatus
00215   IDB_execGetExtRefPath(const char *user, const char *passwd, void *path,
00216                         unsigned int pathlen)
00217   { 
00218     // not yet implemented
00219     return RPCSuccess;
00220   }
00221 
00222   // ---------------------------------------------------------------------------
00223   //
00224   // Executable Cache Management
00225   //
00226   // ---------------------------------------------------------------------------
00227 
00228   ExecutableItem::ExecutableItem(Database *_db, 
00229                                  const char *_intname,
00230                                  const char *name,
00231                                  int _exec_type,
00232                                  int isStaticExec,
00233                                  const Oid &cloid,
00234                                  const char *_extref,
00235                                  Signature *sign,
00236                                  const Oid& oid)
00237   {
00238     db = _db;
00239     exec_type = _exec_type;
00240     dl = NULL;
00241     csym = NULL;
00242     intname = strdup(_intname);
00243     extref = strdup(_extref);
00244 
00245     if (exec_type == METHOD_C_TYPE)
00246       {
00247         const Class *cl = db->getSchema()->getClass(cloid); 
00248         assert(cl);
00249         exec = new BEMethod_C(db, (Class *)cl, name, sign,
00250                               (isStaticExec?True:False), False,
00251                               extref);
00252       }
00253     else
00254       {
00255         utlog("EXEC_TYPE %d not yet implemented, ABORTING PROCESSUS!\n");
00256         abort();
00257       }
00258 
00259     ObjectPeer::setOid(exec, oid);
00260   }
00261 
00262   Status ExecutableItem::check()
00263   {
00264     return Executable::checkRealize(extref, intname, &dl, &csym);
00265   }
00266 
00267   Status
00268   MethodLaunch(Status (*method)(Database *, Method *, Object *,
00269                                 ArgArray &, Argument &),
00270                Database *db,
00271                Method *mth,
00272                Object *o,
00273                ArgArray &argarray,
00274                Argument &retarg)
00275   {
00276     return method(db, mth, o, argarray, retarg);
00277   }
00278 
00279   Status ExecutableItem::execute(Object *o, ArgArray *argarray,
00280                                  Argument *retarg)
00281   {
00282     if (exec_type == METHOD_C_TYPE)
00283       return MethodLaunch((Status (*)(Database *, Method *,
00284                                       Object *, ArgArray &,
00285                                       Argument &))csym,
00286                           db,
00287                           (Method *)exec,
00288                           o, *argarray,
00289                           *retarg);
00290 
00291     abort();
00292   }
00293 
00294   ExecutableItem::~ExecutableItem()
00295   {
00296     free(intname);
00297     free(extref);
00298     exec->release();
00299   }
00300 
00301   inline unsigned int ExecutableCache::get_key(const char *tok)
00302   {
00303     int len = strlen(tok);
00304     int k = 0;
00305 
00306     for (int i = 0; i < len; i++)
00307       k += *tok++;
00308 
00309     return k & mask;
00310   }
00311 
00312 #define CACHESIZE 128
00313 
00314   ExecutableCache::ExecutableCache()
00315   {
00316     nkeys = CACHESIZE;
00317     mask = nkeys-1;
00318     lists = (LinkedList **)malloc(sizeof(LinkedList *) * nkeys);
00319     memset(lists, 0, sizeof(LinkedList *)*nkeys);
00320   }
00321 
00322   void ExecutableCache::insert(ExecutableItem *item)
00323   {
00324     int k = get_key(item->intname);
00325   
00326     if (!lists[k])
00327       lists[k] = new LinkedList();
00328 
00329     lists[k]->insertObjectLast(item);
00330   }
00331 
00332   void ExecutableCache::remove(const char *intname)
00333   {
00334     remove(get(intname));
00335   }
00336 
00337   void ExecutableCache::remove(ExecutableItem *item)
00338   {
00339     if (!item)
00340       return;
00341 
00342     LinkedList *list;
00343 
00344     if (list = lists[get_key(item->intname)])
00345       list->deleteObject(item);
00346   }
00347 
00348   ExecutableItem *ExecutableCache::get(const char *intname)
00349   {
00350     LinkedList *list;
00351 
00352     if (list = lists[get_key(intname)])
00353       {
00354         ExecutableItem *item;
00355         LinkedListCursor *c = list->startScan();
00356 
00357         while (list->getNextObject(c, (void *&)item))
00358           if (!strcmp(item->intname, intname))
00359             {
00360               list->endScan(c);
00361               return item;
00362             }
00363 
00364         list->endScan(c);
00365       }
00366 
00367     return NULL;
00368   }
00369 
00370   ExecutableCache::~ExecutableCache()
00371   {
00372     for (int i = 0; i < nkeys; i++)
00373       {
00374         LinkedList *list = lists[i];
00375 
00376         if (!list)
00377           continue;
00378 
00379         ExecutableItem *item;
00380         LinkedListCursor *c = list->startScan();
00381 
00382         while (list->getNextObject(c, (void *&)item))
00383           delete item;
00384 
00385         list->endScan(c);
00386         delete list;
00387       }
00388 
00389     free(lists);
00390   }
00391 
00392 }

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