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 #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
00041
00042
00043
00044 RPCStatus
00045 IDB_execCheck(DbHandle *, const char *intname, const eyedbsm::Oid *oid,
00046 const char *extref)
00047 {
00048
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
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
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
00211 return RPCSuccess;
00212 }
00213
00214 RPCStatus
00215 IDB_execGetExtRefPath(const char *user, const char *passwd, void *path,
00216 unsigned int pathlen)
00217 {
00218
00219 return RPCSuccess;
00220 }
00221
00222
00223
00224
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 }