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 "eyedb_p.h"
00026 #include "eyedblib/butils.h"
00027
00028 using namespace std;
00029
00030 namespace eyedb {
00031
00032 Status _status_;
00033
00034 #define S_SIZE 2048
00035
00036 Exception::Mode Exception::mode = Exception::StatusMode;
00037 void (*Exception::handler)(Status, void *);
00038 void *Exception::handler_user_data;
00039 void (*Exception::print_method)(Status, FILE*);
00040
00041
00042
00043 static const char *getStringSeverity(SeverityStatus sev)
00044 {
00045 switch(sev)
00046 {
00047 case _Warning:
00048 return "warning";
00049
00050 case _Error:
00051 return "error";
00052
00053 case _FatalError:
00054 return "fatal error";
00055 }
00056 }
00057
00058 static void
00059 setString(char **st, const char *fmt, va_list ap)
00060 {
00061 va_list aq;
00062 va_copy(aq, ap);
00063
00064 char *s = eyedblib::getFBuffer(fmt, ap);
00065 vsprintf(s, fmt, aq);
00066 if (*st)
00067 free(*st);
00068 *st = (char *)malloc(strlen(s)+1);
00069 strcpy(*st, s);
00070 }
00071
00072
00073
00074
00075
00076 #define MAKE_DESC(ST, MSG) \
00077 statusDesc[ST].status_string = #ST; \
00078 statusDesc[ST].desc = MSG
00079
00080 struct Exception::_desc Exception::statusDesc[IDB_N_ERROR];
00081
00082 void Exception::init(void)
00083 {
00084 if (!statusDesc[IDB_SUCCESS].status_string)
00085 {
00086 MAKE_DESC(IDB_SUCCESS, "operation succesful");
00087 MAKE_DESC(IDB_ERROR, "eyedb error");
00088 MAKE_DESC(IDB_FATAL_ERROR, "eyedb fatal error");
00089 MAKE_DESC(IDB_NOT_YET_IMPLEMENTED, "feature not yet implemented");
00090 MAKE_DESC(IDB_INTERNAL_ERROR, "eyedb internal error");
00091 MAKE_DESC(IDB_EXIT_CALLED, "exit function has been called");
00092 MAKE_DESC(IDB_SERVER_NOT_RUNNING, "eyedb server is not running");
00093 MAKE_DESC(IDB_CONNECTION_LOG_FILE_ERROR, "cannot access connection log file");
00094 MAKE_DESC(IDB_INTERNAL_BUG, "eyedb internal bug");
00095 MAKE_DESC(IDB_CONNECTION_FAILURE, "connection failure");
00096 MAKE_DESC(IDB_SERVER_FAILURE, "server failure");
00097 MAKE_DESC(IDB_SM_ERROR, "storage manager error");
00098 MAKE_DESC(IDB_INVALID_DBOPEN_FLAG, "invalid database open flag");
00099 MAKE_DESC(IDB_INVALID_DB_ID, "invalid database identifier");
00100 MAKE_DESC(IDB_INVALID_CLIENT_ID, "invalid client identifier");
00101 MAKE_DESC(IDB_INVALID_SCHEMA, "invalid schema");
00102 MAKE_DESC(IDB_INVALID_OBJECT_HEADER, "invalid object_header");
00103 MAKE_DESC(IDB_INVALID_TRANSACTION, "invalid transaction");
00104 MAKE_DESC(IDB_INVALID_TRANSACTION_MODE, "invalid transaction mode");
00105 MAKE_DESC(IDB_INVALID_TRANSACTION_WRITE_MODE, "invalid transaction write mode");
00106 MAKE_DESC(IDB_INVALID_TRANSACTION_PARAMS, "invalid transaction parameters");
00107 MAKE_DESC(IDB_AUTHENTICATION_NOT_SET, "authentication parameters are not set (check your 'user' and 'passwd' configuration variables or use -eyedbuser and -eyedbpasswd command line options)");
00108 MAKE_DESC(IDB_ADD_USER_ERROR, "add user error");
00109 MAKE_DESC(IDB_DELETE_USER_ERROR, "delete user error");
00110 MAKE_DESC(IDB_SET_USER_PASSWD_ERROR, "set user password error");
00111 MAKE_DESC(IDB_SET_PASSWD_ERROR, "set password error");
00112 MAKE_DESC(IDB_SET_USER_DBACCESS_ERROR, "set user database access error");
00113 MAKE_DESC(IDB_SET_DEFAULT_DBACCESS_ERROR, "set default database access error");
00114 MAKE_DESC(IDB_SET_USER_SYSACCESS_ERROR, "set user system access error");
00115 MAKE_DESC(IDB_AUTHENTICATION_FAILED, "authentication failed");
00116 MAKE_DESC(IDB_TRANSACTION_COMMIT_UNEXPECTED, "commit unexpected");
00117 MAKE_DESC(IDB_TRANSACTION_ABORT_UNEXPECTED, "abort unexpected");
00118 MAKE_DESC(IDB_INSUFFICIENT_PRIVILEGES, "insufficient privileges");
00119 MAKE_DESC(IDB_NO_CURRENT_TRANSACTION, "no current transaction");
00120 MAKE_DESC(IDB_DATABASE_OPEN_ERROR, "database open error");
00121 MAKE_DESC(IDB_DATABASE_CLOSE_ERROR, "database close error");
00122 MAKE_DESC(IDB_DATABASE_CREATE_ERROR, "database create error");
00123 MAKE_DESC(IDB_DATABASE_REMOVE_ERROR, "database remove error");
00124 MAKE_DESC(IDB_DATABASE_COPY_ERROR, "database copy error");
00125 MAKE_DESC(IDB_DATABASE_MOVE_ERROR, "database move error");
00126 MAKE_DESC(IDB_DATABASE_REMOVE_ERROR, "database remove error");
00127 MAKE_DESC(IDB_DATABASE_RENAME_ERROR, "database rename error");
00128 MAKE_DESC(IDB_DATABASE_LOAD_OBJECT_ERROR, "database load object error");
00129 MAKE_DESC(IDB_DATABASE_GET_OBJECT_CLASS_ERROR, "database get object class error");
00130 MAKE_DESC(IDB_INCONSISTANT_OBJECT_HEADERS, "inconsistant object_headers");
00131 MAKE_DESC(IDB_IS_OBJECT_OF_CLASS_ERROR, "is object of class error");
00132 MAKE_DESC(IDB_SETDATABASE_ERROR, "set database error");
00133 MAKE_DESC(IDB_OBJECT_REMOVE_ERROR, "object remove");
00134 MAKE_DESC(IDB_CANNOT_CREATE_SCHEMA, "cannot create schema");
00135 MAKE_DESC(IDB_CANNOT_UPDATE_SCHEMA, "cannot update schema");
00136 MAKE_DESC(IDB_SCHEMA_ALREADY_CREATED, "schema already created");
00137 MAKE_DESC(IDB_OBJECT_ALREADY_CREATED, "object already created");
00138 MAKE_DESC(IDB_OBJECT_NOT_CREATED, "object not yet created");
00139 MAKE_DESC(IDB_OUT_OF_MEMORY, "eyedb out of memory");
00140 MAKE_DESC(IDB_BACKEND_INTERRUPTED, "backend interrupted");
00141 MAKE_DESC(IDB_ITERATOR_ATTRIBUTE_NO_IDX, "no index for attribute");
00142 MAKE_DESC(IDB_ITERATOR_ATTRIBUTE_INVALID_SIZE, "attribute invalid size");
00143 MAKE_DESC(IDB_ITERATOR_ATTRIBUTE_INVALID_INDICE, "attribute invalid indice");
00144 MAKE_DESC(IDB_ITERATOR_ERROR, "query error");
00145 MAKE_DESC(IDB_DBM_ERROR, "database manager error");
00146 MAKE_DESC(IDB_SCHEMA_ERROR, "schema error");
00147 MAKE_DESC(IDB_OQL_SYNTAX_ERROR, "oql syntax error");
00148 MAKE_DESC(IDB_OQL_ERROR, "oql error");
00149 MAKE_DESC(IDB_OQL_INTERRUPTED, "oql interrupted");
00150 MAKE_DESC(IDB_CLASS_READ, "reading class");
00151 MAKE_DESC(IDB_ATTRIBUTE_ERROR, "attribute error");
00152 MAKE_DESC(IDB_OUT_OF_RANGE_ATTRIBUTE_ERROR, "out of range attribute error");
00153 MAKE_DESC(IDB_ATTRIBUTE_INVERSE_ERROR, "attribute relationship error");
00154 MAKE_DESC(IDB_MAG_ORDER_ERROR, "magnitude order error");
00155 MAKE_DESC(IDB_NO_CLASS, "no class for object");
00156 MAKE_DESC(IDB_CLASS_NOT_CREATED, "class is not created");
00157 MAKE_DESC(IDB_CLASS_NOT_FOUND, "class not found");
00158 MAKE_DESC(IDB_INDEX_ERROR, "attribute index error");
00159 MAKE_DESC(IDB_ENUM_ERROR, "enum error");
00160 MAKE_DESC(IDB_COLLECTION_BACK_END_ERROR, "back end collection error");
00161 MAKE_DESC(IDB_COLLECTION_ITEM_SIZE_TOO_LARGE, "collection item size is too large");
00162 MAKE_DESC(IDB_COLLECTION_ITEM_SIZE_UNKNOWN, "collection unknown item size");
00163 MAKE_DESC(IDB_COLLECTION_ERROR, "collection error");
00164 MAKE_DESC(IDB_COLLECTION_LOCKED, "collection lock error");
00165 MAKE_DESC(IDB_COLLECTION_INSERT_ERROR, "collection insert error");
00166 MAKE_DESC(IDB_COLLECTION_DUPLICATE_INSERT_ERROR, "collection duplicate insert error");
00167 MAKE_DESC(IDB_COLLECTION_SUPPRESS_ERROR, "collection suppress error");
00168 MAKE_DESC(IDB_COLLECTION_IS_IN_ERROR, "collection is in error");
00169 MAKE_DESC(IDB_CLASS_COMPLETION_ERROR, "class completion error");
00170 MAKE_DESC(IDB_GENERATION_CODE_ERROR, "generation code error");
00171 MAKE_DESC(IDB_UNIQUE_CONSTRAINT_ERROR, "unique constraint error");
00172 MAKE_DESC(IDB_UNIQUE_COMP_CONSTRAINT_ERROR,
00173 "unique[] constraint error");
00174 MAKE_DESC(IDB_NOTNULL_CONSTRAINT_ERROR, "not null constraint error");
00175 MAKE_DESC(IDB_NOTNULL_COMP_CONSTRAINT_ERROR,
00176 "notnull[] constraint error");
00177 MAKE_DESC(IDB_CARDINALITY_CONSTRAINT_ERROR,
00178 "cardinality constraint error");
00179 MAKE_DESC(IDB_EXECUTABLE_ERROR, "executable error");
00180 MAKE_DESC(IDB_SESSION_LOG_CREATION_ERROR, "session log creation error");
00181 MAKE_DESC(IDB_SESSION_LOG_OPEN_ERROR, "session log opening error");
00182 MAKE_DESC(IDB_SESSION_LOG_NO_SPACE_LEFT, "no space left on session log");
00183 MAKE_DESC(IDB_UNSERIALIZABLE_TYPE_ERROR, "non serializable type used in serialization");
00184
00185
00186 int error = 0;
00187 for (int i = IDB_ERROR; i < IDB_N_ERROR; i++)
00188 if (!statusDesc[i].desc)
00189 {
00190 fprintf(stderr, "missing status description: #%d\n", i);
00191 error++;
00192 }
00193
00194 if (error) abort();
00195 }
00196 }
00197
00198 void Exception::_release(void)
00199 {
00200 }
00201
00202 void Exception::statusMake(Status p, int sta, SeverityStatus sev)
00203 {
00204 parent = (Exception *)p;
00205 status = sta;
00206 severity = sev;
00207 print_method = 0;
00208
00209 string = 0;
00210 user_data = 0;
00211 }
00212
00213 Exception::Exception(int sta, SeverityStatus sev)
00214 {
00215 statusMake(0, sta, sev);
00216 }
00217
00218 Exception::Exception(Status p, int sta, SeverityStatus sev)
00219 {
00220 statusMake(p, sta, sev);
00221 }
00222
00223 Exception::Exception(const Exception &e)
00224 {
00225 *this = e;
00226 }
00227
00228 Exception& Exception::operator=(const Exception &e)
00229 {
00230 parent = e.parent;
00231 status = e.status;
00232 string = e.string ? strdup(e.string) : 0;
00233 severity = e.severity;
00234 return *this;
00235 }
00236
00237 Status Exception::setSeverity(SeverityStatus sev)
00238 {
00239 severity = sev;
00240 return this;
00241 }
00242
00243 SeverityStatus Exception::getSeverity(void) const
00244 {
00245 return severity;
00246 }
00247
00248 void Exception::setStatus(int sta)
00249 {
00250 status = sta;
00251 }
00252
00253 int Exception::getStatus(void) const
00254 {
00255 return status;
00256 }
00257
00258 Status Exception::setString(const char *fmt, ...)
00259 {
00260 va_list ap;
00261 va_start(ap, fmt);
00262
00263 eyedb::setString(&string, fmt, ap);
00264
00265 va_end(ap);
00266 return this;
00267 }
00268
00269 Status Exception::setString(SeverityStatus sev, const char *fmt, ...)
00270 {
00271 va_list ap;
00272
00273 setSeverity(sev);
00274 va_start(ap, fmt);
00275
00276 eyedb::setString(&string, fmt, ap);
00277
00278 va_end(ap);
00279 return this;
00280 }
00281
00282 Status Exception::setString(int sta, SeverityStatus sev, const char *fmt, ...)
00283 {
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 setSeverity(sev);
00295 setStatus(sta);
00296 string = strdup(fmt);
00297 return this;
00298
00299 }
00300
00301 const char *Exception::getDesc(void) const
00302 {
00303 static std::string str;
00304
00305 str = "";
00306
00307 if (status >= IDB_ERROR && status < IDB_N_ERROR)
00308 {
00309 const char *desc = statusDesc[(int)status].desc;
00310 if (desc && *desc)
00311 str = desc;
00312 else
00313 str = statusDesc[(int)status].status_string;
00314 }
00315 else if (status >= eyedbsm::SUCCESS && status < IDB_ERROR)
00316 str = eyedbsm::statusGet_err((int)status);
00317 else
00318 str = "unknown error: probably connection failure";
00319
00320 if (string && *string)
00321 {
00322 if (str.size())
00323 str += ": ";
00324 str += string;
00325 }
00326
00327 return str.c_str();
00328 }
00329
00330 const char *Exception::getString(void) const
00331 {
00332 return (string ? string : "");
00333 }
00334
00335 void Exception::setPrintMethod(void (*pm)(Status, FILE*))
00336 {
00337 print_method = pm;
00338 }
00339
00340 void (*Exception::getPrintMethod(void))(Status, FILE*)
00341 {
00342 return print_method;
00343 }
00344
00345 Status Exception::setUserData(Any ud)
00346 {
00347 user_data = ud;
00348 return this;
00349 }
00350
00351 Any Exception::getUserData(void) const
00352 {
00353 return user_data;
00354 }
00355
00356 Status Exception::getParent() const
00357 {
00358 return parent;
00359 }
00360
00361 void Exception::print_realize(FILE *fd, bool newline) const
00362 {
00363 fprintf(fd, "%s%s", getDesc(), (newline ? "\n" : ""));
00364 fflush(fd);
00365 }
00366
00367 Status Exception::print(FILE *fd, bool newline) const
00368 {
00369 print_realize(fd, newline);
00370 return this;
00371 }
00372
00373 void Exception::setHandler(void (*_handler)(Status, void *), void *hud)
00374 {
00375 handler = _handler;
00376 handler_user_data = hud;
00377 }
00378
00379 void (*Exception::getHandler())(Status, void *)
00380 {
00381 return handler;
00382 }
00383
00384 void *Exception::getHandlerUserData()
00385 {
00386 return handler_user_data;
00387 }
00388
00389 static bool ECHO_ERR = getenv("EYEDB_ECHO_ERROR") ? true : false;
00390
00391 void
00392 stop_here()
00393 {
00394 }
00395
00396 void Exception::applyHandler() const
00397 {
00398 IDB_LOG(IDB_LOG_EXCEPTION, ("%s\n", getDesc()));
00399
00400 if (ECHO_ERR)
00401 fprintf(stderr, "%s\n", getDesc());
00402
00403 stop_here();
00404
00405 if (handler)
00406 (*handler)(this, handler_user_data);
00407
00408 if (mode == ExceptionMode) {
00409 throw *this;
00410 }
00411 }
00412
00413 Exception::Mode Exception::setMode(Exception::Mode _mode)
00414 {
00415 Mode omode = mode;
00416 mode = _mode;
00417 return omode;
00418 }
00419
00420 Exception::Mode Exception::getMode()
00421 {
00422 return mode;
00423 }
00424
00425 Exception::~Exception()
00426 {
00427 free(string);
00428 }
00429
00430 static inline Exception *getError()
00431 {
00432 static const int NERRS = 12;
00433 static Exception error[NERRS];
00434 static int err;
00435
00436 if (err >= NERRS)
00437 err = 0;
00438
00439 return &error[err++];
00440 }
00441
00442 Status Exception::make(int err, const char *fmt, ...)
00443 {
00444 va_list ap, aq;
00445 va_start(ap, fmt);
00446 va_copy(aq, ap);
00447
00448 if (err == IDB_SUCCESS)
00449 return Success;
00450
00451 char *s = eyedblib::getFBuffer(fmt, ap);
00452
00453 vsprintf(s, fmt, aq);
00454
00455 Exception *error = getError();
00456 error->setString(err, _Error, s);
00457
00458 error->applyHandler();
00459 va_end(ap);
00460 return error;
00461 }
00462
00463 Status Exception::make(int err, const std::string &s)
00464 {
00465 if (err == IDB_SUCCESS)
00466 return Success;
00467
00468 Exception *error = getError();
00469 error->setString(err, _Error, s.c_str());
00470
00471 error->applyHandler();
00472 return error;
00473 }
00474
00475 Status Exception::make(const char *fmt, ...)
00476 {
00477 va_list ap, aq;
00478 va_start(ap, fmt);
00479 va_copy(aq, ap);
00480
00481 char *s = eyedblib::getFBuffer(fmt, ap);
00482
00483 vsprintf(s, fmt, aq);
00484
00485 Exception *error = getError();
00486 error->setString(IDB_ERROR, _Error, s);
00487
00488 error->applyHandler();
00489 va_end(ap);
00490 return error;
00491 }
00492
00493 Status Exception::make(const std::string &s)
00494 {
00495 Exception *error = getError();
00496 error->setString(IDB_ERROR, _Error, s.c_str());
00497
00498 error->applyHandler();
00499 return error;
00500 }
00501
00502 Status Exception::make(int err)
00503 {
00504 if (err == IDB_SUCCESS)
00505 return Success;
00506
00507 Exception *error = getError();
00508 error->setString(err, _Error, "");
00509 error->applyHandler();
00510 return error;
00511 }
00512
00513 Status Exception::make(Status status)
00514 {
00515 if (status)
00516 status->applyHandler();
00517
00518 return status;
00519 }
00520
00521 Status StatusMake(Error err, RPCStatus rpc_status,
00522 const char *fmt, ...)
00523 {
00524 if (rpc_status && err != IDB_SUCCESS)
00525 {
00526 va_list ap, aq;
00527 va_start(ap, fmt);
00528 va_copy(aq, ap);
00529
00530 char *s = eyedblib::getFBuffer(fmt, ap);
00531
00532 vsprintf(s, fmt, aq);
00533
00534 char t[512];
00535
00536 sprintf(t, "%s: %s", s, rpc_status->err_msg);
00537
00538 Exception *error = getError();
00539 error->setString(err, _Error, t);
00540
00541 error->applyHandler();
00542 va_end(ap);
00543 return error;
00544 }
00545
00546 return Success;
00547 }
00548
00549 Status StatusMake(RPCStatus rpc_status)
00550 {
00551 if (rpc_status)
00552 return Exception::make(rpc_status->err, std::string(rpc_status->err_msg));
00553
00554 return Success;
00555 }
00556
00557 Status StatusMake(Error err, RPCStatus rpc_status)
00558 {
00559 if (rpc_status)
00560 {
00561 static char *str;
00562 Status status = Exception::make(rpc_status->err,
00563 std::string(rpc_status->err_msg));
00564
00565 delete str;
00566 str = strdup(status->getDesc());
00567
00568 return Exception::make(err, std::string(str));
00569 }
00570
00571 return Success;
00572 }
00573
00574 static void
00575 percent_manage(std::string &prefix)
00576 {
00577 if (!strchr(prefix.c_str(), '%'))
00578 return;
00579
00580 char *p = (char *)malloc(strlen(prefix.c_str())*2+1);
00581 char *q = p;
00582 const char *x = prefix.c_str();
00583 char c;
00584 while (c = *x++)
00585 {
00586 *q++ = c;
00587
00588 if (c == '%')
00589 *q++ = '%';
00590 }
00591 *q = 0;
00592 prefix = p;
00593 free(p);
00594 }
00595
00596 RPCStatus rpcStatusMake(Status status)
00597 {
00598 if (status)
00599 {
00600 std::string s = status->getString();
00601 percent_manage(s);
00602 return rpcStatusMake((Error)status->getStatus(), s.c_str());
00603 }
00604
00605 return RPCSuccess;
00606 }
00607
00608 ostream& operator<<(ostream& os, const Exception &e)
00609 {
00610 e.print(get_file(), false);
00611 return convert_to_stream(os);
00612 }
00613
00614 ostream& operator<<(ostream& os, Status s)
00615 {
00616 if (!s)
00617 return os;
00618 s->print(get_file(), false);
00619 return convert_to_stream(os);
00620 }
00621 }