Exception.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 #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   // static functions
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   // Status
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         // checking
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       va_list ap;
00286 
00287       va_start(ap, fmt);
00288 
00289       ::setString(&string, fmt, ap);
00290 
00291       va_end(ap);
00292       return this;
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 }

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