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 #include <assert.h>
00026 #include <dlfcn.h>
00027 #include <fcntl.h>
00028 #include <unistd.h>
00029 #include "eyedb_p.h"
00030
00031 namespace eyedb {
00032
00033 static eyedbsm::Oid nulloid;
00034
00035 Status
00036 eyedb_CHECKObjRefType(Database *db, Argument &arg, const char *which)
00037 {
00038 if (!arg.u.o->isModify())
00039 {
00040 arg.set(arg.u.o->getOid(), db);
00041 return Success;
00042 }
00043
00044 if (!arg.u.o->getClass()->isFlatStructure())
00045 return Exception::make(IDB_ERROR,
00046 "argument %s : object '%s' of class '%s' "
00047 "is not consistent with database "
00048 ": cannot be transmitted",
00049 which, arg.u.o->getOid().getString(),
00050 arg.u.o->getClass()->getName());
00051 return Success;
00052 }
00053
00054 Status
00055 eyedb_CHECKObjType(Database *db, Argument &arg, const char *which)
00056 {
00057 const ArgType *t = arg.type;
00058
00059 if (t->getType() == ARRAY_TYPE)
00060 return eyedb_CHECKObjArrayType(db, arg, which);
00061
00062 if (t->getType() != OBJ_TYPE)
00063 return Success;
00064
00065 if (!arg.u.o)
00066 return Success;
00067
00068 if (arg.u.o->getOid().isValid())
00069 return eyedb_CHECKObjRefType(db, arg, which);
00070
00071 if (!arg.u.o->getClass()->isFlatStructure() &&
00072 !(db->getOpenFlag() & _DBOpenLocal) &&
00073 !db->isBackEnd())
00074 return Exception::make(IDB_ERROR,
00075 "argument %s : non persistent object of "
00076 "class '%s' is not a flat structure : "
00077 "cannot be transmitted",
00078 which, arg.u.o->getClass()->getName());
00079 return Success;
00080 }
00081
00082 Status
00083 eyedb_CHECKObjArrayType(Database *db, Argument &arg, const char *which)
00084 {
00085 int cnt = arg.u.array->getCount();
00086
00087 for (int i = 0; i < cnt; i++)
00088 {
00089 Status s = eyedb_CHECKObjType(db, *((*arg.u.array)[i]), which);
00090 if (s) return s;
00091 }
00092
00093 return Success;
00094 }
00095
00096 Status
00097 eyedb_CHECKArgument(Database *db, ArgType t1, Argument &arg,
00098 const char *typname, const char *name, const char *which,
00099 int inout)
00100 {
00101 int type = t1.getType();
00102
00103 if (!inout || (type & inout)) {
00104 ArgType t2 = *arg.type;
00105
00106 t1.setType((ArgType_Type)(type & ~(INOUT_ARG_TYPE)), False);
00107
00108 if (!t1.getType())
00109 return Success;
00110
00111 Status s = eyedb_CHECKObjType(db, arg, which);
00112 if (s) return s;
00113
00114 if (t1 != t2) {
00115 if (t1.getType() == OBJ_TYPE && t2.getType() == OBJ_TYPE) {
00116 if (!arg.u.o)
00117 return Success;
00118 const Class *m1, *m2;
00119 m1 = db->getSchema()->getClass(t1.getClname().c_str());
00120 m2 = db->getSchema()->getClass(t2.getClname().c_str());
00121
00122
00123
00124
00125 Bool is;
00126 if (m1 && m2 && !m1->isSuperClassOf(m2, &is) && is)
00127 return Success;
00128 }
00129
00130 return Exception::make(IDB_EXECUTABLE_ERROR,
00131 "%s %s, %s argument %s mismatch, "
00132 "expected %s, got %s",
00133 typname, name,
00134 (inout ? ((inout & IN_ARG_TYPE) ?
00135 "input" : "output") : "return"),
00136 which,
00137 Argument::getArgTypeStr(&t1),
00138 Argument::getArgTypeStr(&t2));
00139 }
00140 }
00141
00142 return Success;
00143 }
00144
00145 Status
00146 eyedb_CHECKArguments(Database *db, const Signature *sign,
00147 ArgArray &array, const char *typname,
00148 const char *name, int inout)
00149 {
00150 int cnt = sign->getNargs();
00151 if (cnt != array.getCount())
00152 return Exception::make(IDB_EXECUTABLE_ERROR,
00153 "%s %s, %d arguments expected, got %d",
00154 typname, name, cnt,
00155 array.getCount());
00156
00157 for (int i = 0; i < cnt; i++) {
00158 char which[12];
00159 sprintf(which, "#%d", i+1);
00160
00161 Status s = eyedb_CHECKArgument(db, *sign->getTypes(i), *array[i],
00162 typname, name, which, inout);
00163 if (s) return s;
00164 }
00165
00166 return Success;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175 const char *
00176 Executable::getSOTag()
00177 {
00178 static std::string s = std::string("-") + getVersion();
00179 return s.c_str();
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 const char *
00195 Executable::makeExtRef(const char *extref)
00196 {
00197 static std::string s;
00198
00199 int len = strlen(extref);
00200 if (len > 3 && !strcmp(&extref[len-3], ".so"))
00201 return extref;
00202
00203
00204 s = std::string(extref) + getSOTag() + ".so";
00205
00206 return s.c_str();
00207 }
00208
00209 static const char *
00210 get_next_path(const char *sopath, int &idx)
00211 {
00212 static char path[512];
00213
00214 const char *s = strchr(sopath+idx, ':');
00215 if (!s)
00216 {
00217 s = sopath+idx;
00218 idx += strlen(sopath+idx);
00219 return s;
00220 }
00221
00222 int len = s-sopath-idx;
00223 strncpy(path, sopath+idx, len);
00224 path[len] = 0;
00225 idx += strlen(path)+1;
00226 return path;
00227 }
00228
00229 void *
00230 Executable::_dlopen(const char *extref)
00231 {
00232 const char *s = makeExtRef(extref);
00233 const char *sopath = ServerConfig::getSValue("sopath");
00234
00235 if (!sopath)
00236 return (void *)0;
00237
00238 const char *x;
00239 int idx = 0;
00240 while (*(x = get_next_path(sopath, idx)))
00241 {
00242 void *dl = dlopen((std::string(x) + "/" + s).c_str(), RTLD_LAZY);
00243 if (dl)
00244 return dl;
00245 }
00246
00247 return (void *)0;
00248 }
00249
00250 const char *
00251 Executable::getSOFile(const char *extref)
00252 {
00253 static std::string file;
00254
00255 const char *s = makeExtRef(extref);
00256 const char *sopath = ServerConfig::getSValue("sopath");
00257
00258 if (!sopath)
00259 return (const char *)0;
00260
00261 const char *x;
00262 int idx = 0;
00263 while (*(x = get_next_path(sopath, idx)))
00264 {
00265 file = std::string(x) + "/" + s;
00266 int fd = open(file.c_str(), O_RDONLY);
00267 if (fd >= 0)
00268 {
00269 close(fd);
00270 return file.c_str();
00271 }
00272 }
00273
00274 return (const char *)0;
00275 }
00276
00277 Status
00278 Executable::checkRealize(const char *extref, const char *intname,
00279 void **pdl, void **pcsym)
00280 {
00281 if (!extref)
00282 return Exception::make(IDB_EXECUTABLE_ERROR,
00283 "invalid null external reference for"
00284 "function '%s'", intname);
00285 if (*pdl)
00286 dlclose(*pdl);
00287
00288 *pdl = Executable::_dlopen(extref);
00289
00290 if (!*pdl)
00291 {
00292 std::string s = std::string("method `") + intname + "' check failed : " +
00293 dlerror();
00294 return Exception::make(IDB_EXECUTABLE_ERROR, s);
00295 }
00296
00297 *pcsym = dlsym(*pdl, intname);
00298
00299 if (!*pcsym)
00300 {
00301 dlclose(*pdl);
00302 *pdl = 0;
00303 return Exception::make(IDB_EXECUTABLE_ERROR,
00304 "symbol '%s' not found in external reference '%s'",
00305 intname, extref);
00306 }
00307
00308 return Success;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 const char *
00324 Executable::makeInternalName(const char *exname, const Signature *sign,
00325 Bool isClassMethod,
00326 const char *clname)
00327 {
00328 static char intname[512];
00329
00330 strcpy(intname, "method_");
00331
00332 if (isClassMethod)
00333 strcat(intname, "static");
00334
00335 if (sign)
00336 strcat(intname, Argument::getArgTypeStr(sign->getRettype(), False));
00337
00338 int n = (sign ? sign->getNargs() : 0);
00339
00340 strcat(intname, "_");
00341 strcat(intname, exname);
00342
00343 if (clname)
00344 {
00345 strcat(intname, "_");
00346 strcat(intname, clname);
00347 }
00348
00349 for (int i = 0; i < n; i++)
00350 {
00351 strcat(intname, "_");
00352 strcat(intname, Argument::getArgTypeStr(sign->getTypes(i), False));
00353 }
00354
00355 return intname;
00356 }
00357
00358 int Executable::isStaticExec() const
00359 {
00360 return (getLoc() & STATIC_EXEC) ? 1 : 0;
00361 }
00362
00363 void Executable::initExec(const char *exname,
00364 ExecutableLang lang,
00365 Bool isSystem,
00366 ExecutableLocalisation loc,
00367 Signature *sign,
00368 Class *_class)
00369 {
00370 setExname(exname);
00371 setLang((ExecutableLang)(lang | (isSystem ? SYSTEM_EXEC : 0)),
00372 False);
00373 setLoc(loc, False);
00374 if (sign)
00375 *getSign() = *sign;
00376 const char *name = makeInternalName
00377 (exname, (sign ? getSign() : 0),
00378 ((loc & STATIC_EXEC) ? True : False),
00379
00380
00381 (_class ? _class->getAliasName() : 0));
00382 setIntname(name);
00383 }
00384
00385 void Executable::userInitialize()
00386 {
00387 dl = (void *)0;
00388 }
00389
00390 void Executable::userCopy(const Object &)
00391 {
00392 userInitialize();
00393 }
00394
00395 Status Executable::checkRealize(const char *extref, const char *mcname,
00396 void **pcsym)
00397 {
00398 const char *intname = makeInternalName
00399 (getExname().c_str(), getSign(),
00400 ((getLoc()&STATIC_EXEC) ? True : False), mcname);
00401
00402 return checkRealize(extref, intname, &dl, pcsym);
00403 }
00404
00405 Status Executable::execCheck()
00406 {
00407 return Success;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416 Status Method::execCheck()
00417 {
00418 return Success;
00419 }
00420
00421 Status Method::realize(const RecMode *rcm)
00422 {
00423 if (!db)
00424 return Exception::make(IDB_ERROR, "no database associated with object");
00425
00426 if (!oid.isValid()) {
00427 OQL q(db, "select method.ex.intname = \"%s\"", getEx()->getIntname().c_str());
00428
00429 ObjectArray obj_arr(true);
00430 Status s = q.execute(obj_arr);
00431
00432 if (obj_arr.getCount()) {
00433
00434 return Exception::make(IDB_UNIQUE_CONSTRAINT_ERROR,
00435 "method '%s::%s' already exists in"
00436 " database '%s'",
00437 getClassOwner()->getName(),
00438 getEx()->getIntname().c_str(),
00439 db->getName());
00440 }
00441 }
00442
00443 return ClassComponent::realize(rcm);
00444 }
00445
00446 Status Method::remove(const RecMode *rcm)
00447 {
00448 return ClassComponent::remove(rcm);
00449 }
00450
00451 Status Method::check(Class *cl) const
00452 {
00453 return Success;
00454 }
00455
00456 int Method::getInd() const
00457 {
00458 return Class::Method_C;
00459 }
00460
00461 const char *
00462 Method::getPrototype(Bool scope) const
00463 {
00464 return getEx()->_getPrototype(getClassOwner(), scope);
00465 }
00466
00467 Bool Method::isInherit() const
00468 {
00469 return True;
00470 }
00471
00472 const char *
00473 Executable::_getPrototype(const Class *_class,
00474 Bool scope) const
00475 {
00476 static std::string proto;
00477
00478 Bool istrs;
00479 if (db && !db->isInTransaction())
00480 {
00481 db->transactionBegin();
00482 istrs = True;
00483 }
00484 else
00485 istrs = False;
00486
00487
00488 proto = "";
00489
00490 const Signature *sign = getSign();
00491
00492 ArgType rettype = *sign->getRettype();
00493 rettype.setType((ArgType_Type)(rettype.getType() & ~INOUT_ARG_TYPE),
00494 False);
00495
00496 proto += Argument::getArgTypeStr(&rettype);
00497
00498 char tok[256];
00499 if (_class && scope)
00500 sprintf(tok, " %s::%s(", _class->getName(), getExname().c_str());
00501 else
00502 sprintf(tok, " %s(", getExname().c_str());
00503
00504
00505 proto += tok;
00506
00507 int n = sign->getNargs();
00508 for (int i = 0; i < n; i++)
00509 {
00510 sprintf(tok, "%s%s", (i ? ", " : ""),
00511 Argument::getArgTypeStr(sign->getTypes(i)));
00512
00513 proto += tok;
00514 }
00515
00516
00517 proto += ")";
00518
00519 if (istrs)
00520 db->transactionCommit();
00521
00522 return proto.c_str();
00523 }
00524
00525 extern void print_oqlexec(FILE *fd, const char *body);
00526
00527 Status
00528 Method::m_trace(FILE *fd, int indent, unsigned int flags,
00529 const RecMode* rcm) const
00530 {
00531 Status s = Success;
00532 Bool istrs;
00533 if (db && !db->isInTransaction())
00534 {
00535 db->transactionBegin();
00536 istrs = True;
00537 }
00538 else
00539 istrs = False;
00540
00541 const Executable *ex = getEx();
00542 const Signature *sign = ex->getSign();
00543 const Class *_class = getClassOwner();
00544
00545 ArgType t = *sign->getRettype();
00546 t.setType((ArgType_Type)(t.getType() & ~OUT_ARG_TYPE), False);
00547 fprintf(fd, "%s_method <%s> %s ",
00548 (ex->isStaticExec() ? "class" : "instance"),
00549 (asFEMethod_C() ? "client" : "server"),
00550 Argument::getArgTypeStr(&t));
00551
00552 if (flags & NoScope)
00553 fprintf(fd, "%s(", ex->getExname().c_str());
00554 else
00555 fprintf(fd, "%s::%s(", (_class ? _class->getName() : "??"),
00556 ex->getExname().c_str());
00557
00558 int is_clang = (ex->getLang() & C_LANG);
00559 int n = sign->getNargs();
00560 for (int i = 0; i < n; i++)
00561 {
00562 fprintf(fd, "%s%s",
00563 (i ? ", " : ""), Argument::getArgTypeStr(sign->getTypes(i)));
00564 if (!is_clang && (flags & ExecBodyTrace))
00565 fprintf(fd, " x%d", i);
00566 }
00567
00568 fprintf(fd, ")");
00569
00570 if (flags & ExecBodyTrace)
00571 {
00572 if (is_clang)
00573 fprintf(fd, " C++(\"%s\")", ex->getExtrefBody().c_str());
00574 else
00575 {
00576 ((Method *)this)->asBEMethod_OQL()->runtimeInit();
00577 if (asBEMethod_OQL()->body)
00578 print_oqlexec(fd, asBEMethod_OQL()->body);
00579 }
00580 }
00581
00582 if (rcm->getType() == RecMode_FullRecurs)
00583 {
00584 fprintf(fd, " ");
00585 s = ObjectPeer::trace_realize(this, fd, indent + INDENT_INC, flags, rcm);
00586 }
00587
00588 if ((flags & CompOidTrace) == CompOidTrace)
00589 fprintf(fd, " %s", oid.getString());
00590
00591 if (istrs)
00592 db->transactionCommit();
00593
00594 return s;
00595 }
00596
00597 Status Method::applyTo(Database *_db, Object *o,
00598 ArgArray &array, Argument &retarg,
00599 Bool checkArgs)
00600 {
00601 return Success;
00602 }
00603
00604 Status Method::get(Database *db, Class *_class,
00605 const char *exname,
00606 const Signature *sign, Bool isClassMethod,
00607 Method* &mth)
00608 {
00609 const char *intname = Executable::makeInternalName
00610
00611
00612 (exname, sign, isClassMethod, _class->getAliasName());
00613
00614 mth = 0;
00615
00616 const LinkedList *mth_list = _class->getCompList(Class::Method_C);
00617 if (!mth_list || !mth_list->getCount())
00618 return Success;
00619
00620
00621 Method **pmth = (Method **)malloc(sizeof(Method *) *
00622 mth_list->getCount());
00623 int mth_cnt = 0;
00624 LinkedListCursor *c = new LinkedListCursor(mth_list);
00625 Method *tmth;
00626
00627 while (mth_list->getNextObject(c, (void *&)tmth))
00628 {
00629 Executable *ex = tmth->getEx();
00630 if (!strcmp(ex->getExname().c_str(), exname) && *ex->getSign() == *sign)
00631 pmth[mth_cnt++] = tmth;
00632 }
00633
00634 mth_list->endScan(c);
00635
00636 if (mth_cnt == 1)
00637 mth = pmth[0];
00638 else if (mth_cnt > 1)
00639 {
00640 Class *cl = _class;
00641 int carryon = 1;
00642 while (cl && carryon)
00643 {
00644 for (int i = 0; i < mth_cnt; i++)
00645 if (pmth[i]->getClassOwner()->compare(cl))
00646 {
00647 mth = pmth[i];
00648 carryon = 0;
00649 break;
00650 }
00651 cl = cl->getParent();
00652 }
00653 }
00654
00655 free(pmth);
00656
00657 return Success;
00658 }
00659
00660
00661
00662
00663
00664 #define check_symbol(C) \
00665 (((C) >= 'a' && (C) <= 'z') || ((C) >= 'A' && (C) <= 'Z') || (C) == '_' ||\
00666 (C) >= '0' && (C) <= '9')
00667
00668 static const char *
00669 getSpaceRid(const char *s, unsigned int len)
00670 {
00671 static char *mem;
00672 static int mem_len;
00673
00674 if (strlen(s) > mem_len)
00675 {
00676 mem_len = strlen(s);
00677 mem = (char *)malloc(mem_len + 1);
00678 }
00679
00680 char *p = mem;
00681 char c;
00682 unsigned int l = 0;
00683
00684 if (!len)
00685 len = ~0;
00686
00687 while ((c = *s) && l < len)
00688 {
00689 if (check_symbol(c) || c == '*' || c == '[' || c == ']')
00690 *p++ = *s;
00691 s++;
00692 l++;
00693 }
00694
00695 *p = 0;
00696 return mem;
00697 }
00698
00699 static char *
00700 getReturnType(const char *s, const char *& p)
00701 {
00702 p = s;
00703 char c;
00704 int state = 0;
00705
00706 while (c = *p)
00707 {
00708 if (c != ' ' && c != '\t')
00709 break;
00710 p++;
00711 }
00712
00713 while (c = *p)
00714 {
00715 if (state && check_symbol(c))
00716 {
00717 int len = p-s;
00718 return strdup(getSpaceRid(s, p-s));
00719 }
00720
00721 if (c == ' ' || c == '\t' || c == '*' || c == ']')
00722 state = 1;
00723
00724 p++;
00725 }
00726
00727 return 0;
00728 }
00729
00730 static char *
00731 getExecName(const char *s, const char *& p)
00732 {
00733 const char *q = p;
00734 char *name = 0;
00735 char c;
00736
00737 while (c = *p)
00738 {
00739 if (c == '(')
00740 {
00741 name = strdup(getSpaceRid(q, p-q));
00742 break;
00743 }
00744
00745 if (!check_symbol(c))
00746 return 0;
00747 p++;
00748 }
00749
00750 if (!name)
00751 return 0;
00752
00753 return name;
00754 }
00755
00756 struct Arg {
00757 int inout;
00758 char *arg;
00759
00760 Arg() {
00761 inout = 0;
00762 arg = NULL;
00763 }
00764
00765 void set(int _inout, const char *_arg) {
00766 inout = _inout;
00767 arg = strdup(_arg);
00768 }
00769
00770 ~Arg() {
00771 free(arg);
00772 }
00773 };
00774
00775 static int
00776 getInOut(const char *t)
00777 {
00778 if (!strcasecmp(t, "in"))
00779 return IN_ARG_TYPE;
00780
00781 if (!strcasecmp(t, "out"))
00782 return OUT_ARG_TYPE;
00783
00784 if (!strcasecmp(t, "inout"))
00785 return INOUT_ARG_TYPE;
00786
00787 return 0;
00788 }
00789
00790 static int
00791 getArgTypes(const char *s, const char *& p, Arg args[], int &nargs,
00792 const char *&str)
00793 {
00794 static const char missinout[] =
00795 "missing IN, OUT or INOUT keyword(s) in signature";
00796
00797 int carryon = 1;
00798 char c;
00799 nargs = 0;
00800 p++;
00801 str = "";
00802
00803 for (nargs = 0; carryon; )
00804 {
00805 int state = 0;
00806 const char *q = p;
00807 int inout = 0;
00808 while (c = *p)
00809 {
00810 if (c == ',')
00811 {
00812 args[nargs].set(inout, getSpaceRid(q, p-q));
00813
00814 if (!inout)
00815 {
00816 str = missinout;
00817 return 0;
00818 }
00819
00820 if (*args[nargs].arg)
00821 nargs++;
00822 else
00823 return 0;
00824 p++;
00825 break;
00826 }
00827
00828 if (c == ')')
00829 {
00830 args[nargs].set(inout, getSpaceRid(q, p-q));
00831
00832 if (!inout && !*args[nargs].arg)
00833 return 1;
00834
00835 if (!inout)
00836 {
00837 str = missinout;
00838 return 0;
00839 }
00840
00841 if (*args[nargs].arg)
00842 nargs++;
00843 else
00844 return 0;
00845
00846 p++;
00847 carryon = 0;
00848 break;
00849 }
00850
00851 if (c == ' ' || c == '\t')
00852 {
00853 if (state == 1)
00854 {
00855 if (!(inout = getInOut(getSpaceRid(q, p-q))))
00856 {
00857 str = missinout;
00858 return 0;
00859 }
00860
00861 state = 2;
00862 q = p;
00863 }
00864 }
00865 else if (!state)
00866 state = 1;
00867
00868 p++;
00869 }
00870
00871 if (!c)
00872 break;
00873 }
00874
00875 while (c = *p)
00876 {
00877 if (c != ' ' && c != '\t')
00878 return 0;
00879 p++;
00880 }
00881 return 1;
00882 }
00883
00884 Status
00885 Method::getSignature(Database *db, Class *cls,
00886 const char *s, Signature *&sign, char *&name)
00887 {
00888 char *rettype;
00889 int nargs;
00890 Arg args[64];
00891 const char *ctx = 0;
00892 sign = NULL;
00893
00894 if (!(rettype = getReturnType(s, ctx)))
00895 return Exception::make
00896 (IDB_ERROR, "invalid signature syntax: invalid return type");
00897
00898 if (!(name = getExecName(s, ctx))) {
00899 free(rettype);
00900 return Exception::make
00901 (IDB_ERROR, "invalid signature syntax: invalid method name");
00902 }
00903
00904 const char *str;
00905 if (!getArgTypes(s, ctx, args, nargs, str)) {
00906 free(rettype);
00907 free(name);
00908 return Exception::make(IDB_ERROR, "invalid signature syntax: %s", str);
00909 }
00910
00911 sign = new Signature(db);
00912 Schema *m = db->getSchema();
00913 ArgType *type = ArgType::make(m, rettype);
00914
00915 free(rettype);
00916
00917 if (type) {
00918 ArgType *t = sign->getRettype();
00919 t->setDatabase(db);
00920 t->setType((ArgType_Type)(type->getType() | OUT_ARG_TYPE),
00921 False);
00922 if (type->getClname().c_str())
00923 t->setClname(type->getClname().c_str());
00924 type->release();
00925 }
00926 else
00927 return Exception::make(IDB_ERROR,
00928 "invalid signature syntax: invalid return type");
00929
00930 sign->setNargs(nargs);
00931 sign->getClass()->getAttribute("types")->setSize(sign, nargs);
00932
00933 for (int i = 0; i < nargs; i++) {
00934 if (type = ArgType::make(m, args[i].arg)) {
00935 ArgType *t = sign->getTypes(i);
00936 t->setDatabase(db);
00937 t->setType((ArgType_Type)(type->getType() | args[i].inout),
00938 False);
00939 if (type->getClname().c_str())
00940 t->setClname(type->getClname().c_str());
00941 type->release();
00942 }
00943 else
00944 return Exception::make(IDB_ERROR, "invalid signature syntax: invalid argument type '%s'", args[i].arg);
00945 }
00946
00947 return Success;
00948 }
00949
00950 Status Method::get(Database *db, Class *_class,
00951 const char *sign_str, Bool isClassMethod,
00952 Method *&mth)
00953 {
00954 Signature *sign = NULL;
00955 char *fname = NULL;
00956
00957 if (!_class)
00958 return Exception::make(IDB_EXECUTABLE_ERROR, "invalid null class");
00959
00960 Status s = getSignature(db, _class, sign_str, sign, fname);
00961 if (s) return s;
00962
00963 s = get(db, _class, fname, sign, isClassMethod, mth);
00964
00965 free(fname);
00966 sign->release();
00967
00968 return s;
00969 }
00970
00971
00972
00973
00974
00975
00976
00977 FEMethod_C::FEMethod_C(Database *_db, Class *_class,
00978 const char *name, Signature *sign,
00979 Bool isClassMethod,
00980 Bool isSystem, const char *extref)
00981 : FEMethod(_db, (const Dataspace *)0, 1)
00982 {
00983 initialize(_db);
00984 db = _db;
00985 Executable *ex = getEx();
00986 ex->initExec(name, C_LANG, isSystem,
00987 (ExecutableLocalisation)(FRONTEND | (isClassMethod ? STATIC_EXEC : 0)),
00988 sign, _class);
00989 setClassOwner(_class);
00990 ex->setExtrefBody(extref);
00991 setName(ex->getIntname());
00992 }
00993
00994 void FEMethod_C::userInitialize()
00995 {
00996 getEx()->Executable::userInitialize();
00997 csym = 0;
00998 }
00999
01000 void FEMethod_C::userCopy(const Object &)
01001 {
01002 userInitialize();
01003 }
01004
01005 Status FEMethod_C::applyTo(Database *_db, Object *o,
01006 ArgArray &array, Argument &retarg,
01007 Bool checkArgs)
01008 {
01009 Executable *ex = getEx();
01010 Status s;
01011
01012 if (checkArgs) {
01013 s = eyedb_CHECKArguments(db, ex->getSign(), array, "method",
01014 ex->getExname().c_str(), IN_ARG_TYPE);
01015 if (s) return s;
01016 }
01017
01018 if (!csym)
01019 {
01020 Bool isTrs = _db->isInTransaction();
01021 if (!isTrs)
01022 _db->transactionBegin();
01023 const char *mcname = getClassOwner()->getName();
01024 if (!isTrs)
01025 _db->transactionCommit();
01026 Status s = ex->checkRealize(ex->getExtrefBody().c_str(), mcname,
01027 (void **)&csym);
01028 if (s) return s;
01029 }
01030
01031 return csym(_db, this, o, array, retarg);
01032 }
01033
01034 Status FEMethod_C::execCheck()
01035 {
01036 Executable *ex = getEx();
01037 return ex->checkRealize(ex->getExtrefBody().c_str(), NULL, (void **)&csym);
01038 }
01039
01040
01041
01042
01043
01044
01045
01046 BEMethod_C::BEMethod_C(Database *_db, Class *_class,
01047 const char *name, Signature *sign,
01048 Bool isClassMethod, Bool isSystem,
01049 const char *extref)
01050 : BEMethod(_db, (const Dataspace *)0, 1)
01051 {
01052 initialize(_db);
01053
01054 Executable *ex = getEx();
01055 ex->initExec(name, C_LANG, isSystem,
01056 (ExecutableLocalisation)(BACKEND | (isClassMethod ? STATIC_EXEC : 0)),
01057 sign, _class);
01058 setClassOwner(_class);
01059 ex->setExtrefBody(extref);
01060 setName(ex->getIntname());
01061 }
01062
01063 Status BEMethod_C::execCheck()
01064 {
01065 if (!db)
01066 return Exception::make(IDB_EXECUTABLE_ERROR,
01067 "BEMethod_C: cannot set external "
01068 "reference, database is not set");
01069
01070 Executable *ex = getEx();
01071
01072 if (db->isBackEnd())
01073 return ex->checkRealize(ex->getExtrefBody().c_str(), NULL, (void **)&csym);
01074
01075 RPCStatus rpc_status;
01076
01077 rpc_status = eyedb::execCheck(db->getDbHandle(),
01078 ex->getIntname().c_str(), oid.getOid(),
01079 ex->getExtrefBody().c_str());
01080
01081 return StatusMake(rpc_status);
01082 }
01083
01084 Status BEMethod_C::applyTo(Database *_db, Object *o,
01085 ArgArray &array, Argument &retarg,
01086 Bool checkArgs)
01087 {
01088 const eyedbsm::Oid *objoid;
01089 Oid nulloid;
01090
01091 if (o && !o->getOid().isValid() &&
01092 (!o->asCollection() || !o->asCollection()->getOidC().isValid())) {
01093
01094
01095 if (!(db->getOpenFlag() & _DBOpenLocal) &&
01096 !db->isBackEnd())
01097 return Exception::make(IDB_EXECUTABLE_ERROR,
01098 "cannot apply a backend method on a "
01099 "non persistent object");
01100 }
01101
01102 if (o)
01103 objoid = (o->asCollection() ? o->asCollection()->getOidC().getOid() :
01104 o->getOid().getOid());
01105 else
01106 objoid = nulloid.getOid();
01107
01108 Executable *ex = getEx();
01109 Status s;
01110
01111 if (checkArgs) {
01112 s = eyedb_CHECKArguments(db, ex->getSign(), array, "method",
01113 ex->getExname().c_str(), IN_ARG_TYPE);
01114 if (s) return s;
01115 }
01116
01117 RPCStatus rpc_status;
01118 const eyedbsm::Oid *_oid = getOid().getOid();;
01119
01120 rpc_status = execExecute(_db->getDbHandle(),
01121 _db->getUser(),
01122 _db->getPassword(),
01123 ex->getIntname().c_str(),
01124 ex->getExname().c_str(),
01125 METHOD_C_TYPE |
01126 (getEx()->isStaticExec() ? STATIC_EXEC : 0),
01127 getClassOwner()->getOid().getOid(),
01128 ex->getExtrefBody().c_str(),
01129 ex->getSign(),
01130 _oid,
01131 objoid,
01132 o,
01133 (const void *)&array,
01134 (void **)&retarg);
01135
01136 if (rpc_status)
01137 return StatusMake(rpc_status);
01138
01139 return Success;
01140 }
01141
01142
01143
01144
01145
01146
01147
01148 BEMethod_OQL::BEMethod_OQL(Database *_db, Class *_class,
01149 const char *name, Signature *sign,
01150 Bool isClassMethod, Bool isSystem,
01151 const char *_body)
01152 {
01153 initialize(_db);
01154 db = _db;
01155 Executable *ex = getEx();
01156 ex->initExec(name, OQL_LANG, isSystem,
01157 (ExecutableLocalisation)(BACKEND|
01158 (isClassMethod ? STATIC_EXEC : 0)),
01159 sign, _class);
01160 setClassOwner(_class);
01161 ex->setExtrefBody(_body);
01162 setName(ex->getIntname());
01163 }
01164
01165 Status BEMethod_OQL::applyTo(Database *, Object *,
01166 ArgArray &, Argument &retarg,
01167 Bool checkArgs)
01168 {
01169 return Exception::make("cannot use the 'applyTo' method to an OQL method");
01170 }
01171
01172 Status BEMethod_OQL::execCheck()
01173 {
01174
01175 return Success;
01176 }
01177
01178 Status BEMethod_OQL::setBody(const char *_body)
01179 {
01180 getEx()->setExtrefBody(_body);
01181 return Success;
01182 }
01183
01184
01185
01186
01187
01188
01189
01190 std::string
01191 BEMethod_OQL::makeExtrefBody(const Class *cls, const char *oql,
01192 const char *name,
01193 char *typnames[],
01194 char *varnames[],
01195 unsigned int param_cnt,
01196 std::string &oqlConstruct)
01197 {
01198 std::string s = str_convert((long)param_cnt);
01199 int i;
01200
01201 for (i = 0; i < param_cnt; i++)
01202 s += std::string(":") + varnames[i];
01203
01204 s += ":";
01205
01206 std::string funcname = std::string("oql$") + cls->getAliasName() + "$" +
01207 name;
01208
01209 for (i = 0; i < param_cnt; i++)
01210 funcname += std::string("$") + typnames[i];
01211
01212 s += funcname;
01213 s += ":";
01214
01215 oqlConstruct = std::string("function ") + funcname + " (";
01216
01217 for (i = 0; i < param_cnt; i++)
01218 {
01219 if (i) oqlConstruct += ",";
01220 oqlConstruct += varnames[i];
01221 }
01222
01223 oqlConstruct += ")";
01224 oqlConstruct += oql;
01225
01226 return s + oql;
01227 }
01228
01229 Status
01230 BEMethod_OQL::runtimeInit()
01231 {
01232 if (isRTInitialized)
01233 return Success;
01234
01235 char *r;
01236 const char *s = getEx()->getExtrefBody().c_str();
01237
01238 tmpbuf = strdup(s);
01239 char *q = strchr(tmpbuf, ':');
01240
01241 if (!q)
01242 return Exception::make(IDB_EXECUTABLE_ERROR,
01243 "invalid internal format '%s'", s);
01244 *q = 0;
01245 param_cnt = atoi(tmpbuf);
01246
01247 varnames = new char *[param_cnt];
01248 std::string tmp = "(";
01249 for (int i = 0; i < param_cnt; i++)
01250 {
01251 r = strchr(q+1, ':');
01252 if (!r)
01253 return Exception::make(IDB_EXECUTABLE_ERROR,
01254 "invalid internal format '%s'", s);
01255 *r = 0;
01256 varnames[i] = q+1;
01257 if (i) tmp += ",";
01258 tmp += varnames[i];
01259 q = r;
01260 }
01261
01262 tmp += ")";
01263 r = strchr(q+1, ':');
01264 if (!r)
01265 return Exception::make(IDB_EXECUTABLE_ERROR,
01266 "invalid internal format '%s'", s);
01267 *r = 0;
01268 funcname = q+1;
01269
01270 r++;
01271 body = r;
01272 fullBody = strdup((std::string("function ") + funcname + tmp + body).c_str());
01273 isRTInitialized = True;
01274 return Success;
01275 }
01276
01277 void
01278 BEMethod_OQL::userInitialize()
01279 {
01280 isRTInitialized = False;
01281 varnames = 0;
01282 param_cnt = 0;
01283 body = 0;
01284 fullBody = 0;
01285 funcname = 0;
01286 tmpbuf = 0;
01287 entry = 0;
01288 }
01289
01290 void BEMethod_OQL::userCopy(const Object &)
01291 {
01292 userInitialize();
01293 }
01294
01295 void
01296 BEMethod_OQL::userGarbage()
01297 {
01298 delete[] varnames;
01299 free(tmpbuf);
01300 free(fullBody);
01301 }
01302
01303 }
01304