Error.h

Go to the documentation of this file.
00001 
00022 #ifndef HYPERTABLE_ERROR_H
00023 #define HYPERTABLE_ERROR_H
00024 
00025 #include "Common/String.h"
00026 #include <ostream>
00027 #include <stdexcept>
00028 
00029 namespace Hypertable {
00030   namespace Error {
00031     enum Code {
00032       UNPOSSIBLE         = -3,
00033       EXTERNAL           = -2,
00034       FAILED_EXPECTATION = -1,
00035       OK                 = 0,
00036       PROTOCOL_ERROR     = 1,
00037       REQUEST_TRUNCATED  = 2,
00038       RESPONSE_TRUNCATED = 3,
00039       REQUEST_TIMEOUT    = 4,
00040       LOCAL_IO_ERROR     = 5,
00041       BAD_ROOT_LOCATION  = 6,
00042       BAD_SCHEMA         = 7,
00043       INVALID_METADATA   = 8,
00044       BAD_KEY            = 9,
00045       METADATA_NOT_FOUND = 10,
00046       HQL_PARSE_ERROR    = 11,
00047       FILE_NOT_FOUND     = 12,
00048       BLOCK_COMPRESSOR_UNSUPPORTED_TYPE  = 13,
00049       BLOCK_COMPRESSOR_INVALID_ARG       = 14,
00050       BLOCK_COMPRESSOR_TRUNCATED         = 15,
00051       BLOCK_COMPRESSOR_BAD_HEADER        = 16,
00052       BLOCK_COMPRESSOR_BAD_MAGIC         = 17,
00053       BLOCK_COMPRESSOR_CHECKSUM_MISMATCH = 18,
00054       BLOCK_COMPRESSOR_DEFLATE_ERROR     = 19,
00055       BLOCK_COMPRESSOR_INFLATE_ERROR     = 20,
00056       BLOCK_COMPRESSOR_INIT_ERROR        = 21,
00057       TABLE_NOT_FOUND                    = 22,
00058       MALFORMED_REQUEST                  = 23,
00059       TOO_MANY_COLUMNS                   = 24,
00060       BAD_DOMAIN_NAME                    = 25,
00061       COMMAND_PARSE_ERROR                = 26,
00062       CONNECT_ERROR_MASTER               = 27,
00063       CONNECT_ERROR_HYPERSPACE           = 28,
00064       BAD_MEMORY_ALLOCATION              = 29,
00065       BAD_SCAN_SPEC                      = 30,
00066       NOT_IMPLEMENTED                    = 31,
00067       VERSION_MISMATCH                   = 32,
00068       CANCELLED                          = 33,
00069       SCHEMA_PARSE_ERROR                 = 34,
00070       SYNTAX_ERROR                       = 35,
00071       DOUBLE_UNGET                       = 36,
00072       EMPTY_BLOOMFILTER                  = 37,
00073       BLOOMFILTER_CHECKSUM_MISMATCH      = 38,
00074       NAME_ALREADY_IN_USE                = 39,
00075       NAMESPACE_DOES_NOT_EXIST           = 40,
00076       BAD_NAMESPACE                      = 41,
00077       NAMESPACE_EXISTS                   = 42,
00078       NO_RESPONSE                        = 43,
00079       NOT_ALLOWED                        = 44,
00080       INDUCED_FAILURE                    = 45,
00081       SERVER_SHUTTING_DOWN               = 46,
00082 
00083       CONFIG_BAD_ARGUMENT               = 1001,
00084       CONFIG_BAD_CFG_FILE               = 1002,
00085       CONFIG_GET_ERROR                  = 1003,
00086       CONFIG_BAD_VALUE                  = 1004,
00087 
00088       COMM_NOT_CONNECTED             = 0x00010001,
00089       COMM_BROKEN_CONNECTION         = 0x00010002,
00090       COMM_CONNECT_ERROR             = 0x00010003,
00091       COMM_ALREADY_CONNECTED         = 0x00010004,
00092       //COMM_REQUEST_TIMEOUT           = 0x00010005,
00093       COMM_SEND_ERROR                = 0x00010006,
00094       COMM_RECEIVE_ERROR             = 0x00010007,
00095       COMM_POLL_ERROR                = 0x00010008,
00096       COMM_CONFLICTING_ADDRESS       = 0x00010009,
00097       COMM_SOCKET_ERROR              = 0x0001000A,
00098       COMM_BIND_ERROR                = 0x0001000B,
00099       COMM_LISTEN_ERROR              = 0x0001000C,
00100       COMM_HEADER_CHECKSUM_MISMATCH  = 0x0001000D,
00101       COMM_PAYLOAD_CHECKSUM_MISMATCH = 0x0001000E,
00102       COMM_BAD_HEADER                = 0x0001000F,
00103       COMM_INVALID_PROXY             = 0x00010010,
00104 
00105       DFSBROKER_BAD_FILE_HANDLE   = 0x00020001,
00106       DFSBROKER_IO_ERROR          = 0x00020002,
00107       DFSBROKER_FILE_NOT_FOUND    = 0x00020003,
00108       DFSBROKER_BAD_FILENAME      = 0x00020004,
00109       DFSBROKER_PERMISSION_DENIED = 0x00020005,
00110       DFSBROKER_INVALID_ARGUMENT  = 0x00020006,
00111       DFSBROKER_INVALID_CONFIG    = 0x00020007,
00112       DFSBROKER_EOF               = 0x00020008,
00113 
00114       HYPERSPACE_IO_ERROR                          = 0x00030001,
00115       HYPERSPACE_CREATE_FAILED                     = 0x00030002,
00116       HYPERSPACE_FILE_NOT_FOUND                    = 0x00030003,
00117       HYPERSPACE_ATTR_NOT_FOUND                    = 0x00030004,
00118       HYPERSPACE_DELETE_ERROR                      = 0x00030005,
00119       HYPERSPACE_BAD_PATHNAME                      = 0x00030006,
00120       HYPERSPACE_PERMISSION_DENIED                 = 0x00030007,
00121       HYPERSPACE_EXPIRED_SESSION                   = 0x00030008,
00122       HYPERSPACE_FILE_EXISTS                       = 0x00030009,
00123       HYPERSPACE_IS_DIRECTORY                      = 0x0003000A,
00124       HYPERSPACE_INVALID_HANDLE                    = 0x0003000B,
00125       HYPERSPACE_REQUEST_CANCELLED                 = 0x0003000C,
00126       HYPERSPACE_MODE_RESTRICTION                  = 0x0003000D,
00127       HYPERSPACE_ALREADY_LOCKED                    = 0x0003000E,
00128       HYPERSPACE_LOCK_CONFLICT                     = 0x0003000F,
00129       HYPERSPACE_NOT_LOCKED                        = 0x00030010,
00130       HYPERSPACE_BAD_ATTRIBUTE                     = 0x00030011,
00131       HYPERSPACE_BERKELEYDB_ERROR                  = 0x00030012,
00132       HYPERSPACE_DIR_NOT_EMPTY                     = 0x00030013,
00133       HYPERSPACE_BERKELEYDB_DEADLOCK               = 0x00030014,
00134       HYPERSPACE_BERKELEYDB_REP_HANDLE_DEAD        = 0x00030015,
00135       HYPERSPACE_FILE_OPEN                         = 0x00030016,
00136       HYPERSPACE_CLI_PARSE_ERROR                   = 0x00030017,
00137       HYPERSPACE_CREATE_SESSION_FAILED             = 0x00030018,
00138       HYPERSPACE_NOT_MASTER_LOCATION               = 0x00030019,
00139 
00140       HYPERSPACE_STATEDB_ERROR                     = 0x0003001A,
00141       HYPERSPACE_STATEDB_DEADLOCK                  = 0x0003001B,
00142       HYPERSPACE_STATEDB_BAD_KEY                   = 0x0003001C,
00143       HYPERSPACE_STATEDB_BAD_VALUE                 = 0x0003001D,
00144       HYPERSPACE_STATEDB_ALREADY_DELETED           = 0x0003001E,
00145       HYPERSPACE_STATEDB_EVENT_EXISTS              = 0x0003001F,
00146       HYPERSPACE_STATEDB_EVENT_NOT_EXISTS          = 0x00030020,
00147       HYPERSPACE_STATEDB_EVENT_ATTR_NOT_FOUND      = 0x00030021,
00148       HYPERSPACE_STATEDB_SESSION_EXISTS            = 0x00030022,
00149       HYPERSPACE_STATEDB_SESSION_NOT_EXISTS        = 0x00030023,
00150       HYPERSPACE_STATEDB_SESSION_ATTR_NOT_FOUND    = 0x00030024,
00151       HYPERSPACE_STATEDB_HANDLE_EXISTS             = 0x00030025,
00152       HYPERSPACE_STATEDB_HANDLE_NOT_EXISTS         = 0x00030026,
00153       HYPERSPACE_STATEDB_HANDLE_ATTR_NOT_FOUND     = 0x00030027,
00154       HYPERSPACE_STATEDB_NODE_EXISTS               = 0x00030028,
00155       HYPERSPACE_STATEDB_NODE_NOT_EXISTS           = 0x00030029,
00156       HYPERSPACE_STATEDB_NODE_ATTR_NOT_FOUND       = 0x0003002A,
00157 
00158       MASTER_TABLE_EXISTS                    = 0x00040001,
00159       MASTER_BAD_SCHEMA                      = 0x00040002,
00160       MASTER_NOT_RUNNING                     = 0x00040003,
00161       MASTER_NO_RANGESERVERS                 = 0x00040004,
00162       MASTER_FILE_NOT_LOCKED                 = 0x00040005,
00163       MASTER_RANGESERVER_ALREADY_REGISTERED  = 0x00040006,
00164       MASTER_BAD_COLUMN_FAMILY               = 0x00040007,
00165       MASTER_SCHEMA_GENERATION_MISMATCH      = 0x00040008,
00166       MASTER_LOCATION_ALREADY_ASSIGNED       = 0x00040009,
00167       MASTER_LOCATION_INVALID                = 0x0004000A,
00168       MASTER_OPERATION_IN_PROGRESS           = 0x0004000B,
00169 
00170       RANGESERVER_GENERATION_MISMATCH    = 0x00050001,
00171       RANGESERVER_RANGE_ALREADY_LOADED   = 0x00050002,
00172       RANGESERVER_RANGE_MISMATCH         = 0x00050003,
00173       RANGESERVER_NONEXISTENT_RANGE      = 0x00050004,
00174       RANGESERVER_OUT_OF_RANGE           = 0x00050005,
00175       RANGESERVER_RANGE_NOT_FOUND        = 0x00050006,
00176       RANGESERVER_INVALID_SCANNER_ID     = 0x00050007,
00177       RANGESERVER_SCHEMA_PARSE_ERROR     = 0x00050008,
00178       RANGESERVER_SCHEMA_INVALID_CFID    = 0x00050009,
00179       RANGESERVER_INVALID_COLUMNFAMILY   = 0x0005000A,
00180       RANGESERVER_TRUNCATED_COMMIT_LOG   = 0x0005000B,
00181       RANGESERVER_NO_METADATA_FOR_RANGE  = 0x0005000C,
00182       RANGESERVER_SHUTTING_DOWN          = 0x0005000D,
00183       RANGESERVER_CORRUPT_COMMIT_LOG     = 0x0005000E,
00184       RANGESERVER_UNAVAILABLE            = 0x0005000F,
00185       RANGESERVER_REVISION_ORDER_ERROR   = 0x00050010,
00186       RANGESERVER_ROW_OVERFLOW           = 0x00050011,
00187       RANGESERVER_TABLE_NOT_FOUND        = 0x00050012,
00188       RANGESERVER_BAD_SCAN_SPEC          = 0x00050013,
00189       RANGESERVER_CLOCK_SKEW             = 0x00050014,
00190       RANGESERVER_BAD_CELLSTORE_FILENAME = 0x00050015,
00191       RANGESERVER_CORRUPT_CELLSTORE      = 0x00050016,
00192       RANGESERVER_TABLE_DROPPED          = 0x00050017,
00193       RANGESERVER_UNEXPECTED_TABLE_ID    = 0x00050018,
00194       RANGESERVER_RANGE_BUSY             = 0x00050019,
00195       RANGESERVER_BAD_CELL_INTERVAL      = 0x0005001A,
00196       RANGESERVER_SHORT_CELLSTORE_READ   = 0x0005001B,
00197 
00198       HQL_BAD_LOAD_FILE_FORMAT  = 0x00060001,
00199 
00200       METALOG_VERSION_MISMATCH  = 0x00070001,
00201       METALOG_BAD_RS_HEADER     = 0x00070002,
00202       METALOG_BAD_HEADER        = 0x00070003,
00203       METALOG_ENTRY_TRUNCATED   = 0x00070004,
00204       METALOG_CHECKSUM_MISMATCH = 0x00070005,
00205       METALOG_ENTRY_BAD_TYPE    = 0x00070006,
00206       METALOG_ENTRY_BAD_ORDER   = 0x00070007,
00207 
00208       SERIALIZATION_INPUT_OVERRUN = 0x00080001,
00209       SERIALIZATION_BAD_VINT      = 0x00080002,
00210       SERIALIZATION_BAD_VSTR      = 0x00080003,
00211 
00212       THRIFTBROKER_BAD_SCANNER_ID         = 0x00090001,
00213       THRIFTBROKER_BAD_MUTATOR_ID         = 0x00090002,
00214       THRIFTBROKER_BAD_NAMESPACE_ID       = 0x00090003,
00215       THRIFTBROKER_BAD_FUTURE_ID          = 0x00090004
00216 
00217     };
00218 
00219     const char *get_text(int error);
00220 
00221   } // namespace Error
00222 
00223 
00224   class Exception;
00225 
00226   // Helpers to render a exception message a la IO manipulators
00227   struct ExceptionMessageRenderer {
00228     ExceptionMessageRenderer(const Exception &e) : ex(e) { }
00229 
00230     std::ostream &render(std::ostream &out) const;
00231 
00232     const Exception &ex;
00233   };
00234 
00235   struct ExceptionMessagesRenderer {
00236     ExceptionMessagesRenderer(const Exception &e, const char *sep = ": ")
00237       : ex(e), separator(sep) { }
00238 
00239     std::ostream &render(std::ostream &out) const;
00240 
00241     const Exception &ex;
00242     const char *separator;
00243   };
00244 
00249   class Exception : public std::runtime_error {
00250     const Exception &operator=(const Exception &); // not assignable
00251 
00252     int m_error;
00253     int m_line;
00254     const char *m_func;
00255     const char *m_file;
00256 
00257   public:
00258     typedef std::runtime_error Parent;
00259 
00260     Exception(int error, int l = 0, const char *fn = 0, const char *fl = 0)
00261       : Parent(""), m_error(error), m_line(l), m_func(fn), m_file(fl), prev(0)
00262       { }
00263     Exception(int error, const String &msg, int l = 0, const char *fn = 0,
00264               const char *fl = 0)
00265       : Parent(msg), m_error(error), m_line(l), m_func(fn), m_file(fl), prev(0)
00266       { }
00267     Exception(int error, const String &msg, const Exception &ex,
00268               int l = 0, const char *fn = 0, const char *fl = 0)
00269       : Parent(msg), m_error(error), m_line(l), m_func(fn), m_file(fl),
00270         prev(new Exception(ex)) { }
00271     // copy ctor is required for exceptions
00272     Exception(const Exception &ex) : Parent(ex), m_error(ex.m_error),
00273         m_line(ex.m_line), m_func(ex.m_func), m_file(ex.m_file) {
00274       prev = ex.prev ? new Exception(*ex.prev) : 0;
00275     }
00276     ~Exception() throw() { delete prev; prev = 0; }
00277 
00278     int code() const { return m_error; }
00279     int line() const { return m_line; }
00280     const char *func() const { return m_func; }
00281     const char *file() const { return m_file; }
00282 
00283     // render message
00284     virtual std::ostream &render_message(std::ostream &out) const {
00285       return out << what(); // override for custom exceptions
00286     }
00287 
00288     // render messages for the entire exception chain
00289     virtual std::ostream &
00290     render_messages(std::ostream &out, const char *sep) const;
00291 
00292     ExceptionMessageRenderer message() const {
00293       return ExceptionMessageRenderer(*this);
00294     }
00295 
00296     ExceptionMessagesRenderer messages(const char *sep = ": ") const {
00297       return ExceptionMessagesRenderer(*this, sep);
00298     }
00299 
00300     Exception *prev;    // exception chain/list
00301   };
00302 
00303 std::ostream &operator<<(std::ostream &out, const Exception &);
00304 
00305 inline std::ostream &
00306 ExceptionMessageRenderer::render(std::ostream &out) const {
00307   return ex.render_message(out);
00308 }
00309 
00310 inline std::ostream &
00311 ExceptionMessagesRenderer::render(std::ostream &out) const {
00312   return ex.render_messages(out, separator);
00313 }
00314 
00315 inline std::ostream &
00316 operator<<(std::ostream &out, const ExceptionMessageRenderer &r) {
00317   return r.render(out);
00318 }
00319 
00320 inline std::ostream &
00321 operator<<(std::ostream &out, const ExceptionMessagesRenderer &r) {
00322   return r.render(out);
00323 }
00324 
00328 #define HT_EXCEPTION(_code_, _msg_) \
00329   Exception(_code_, _msg_, __LINE__, HT_FUNC, __FILE__)
00330 
00331 #define HT_EXCEPTION2(_code_, _ex_, _msg_) \
00332   Exception(_code_, _msg_, _ex_, __LINE__, HT_FUNC, __FILE__)
00333 
00334 #define HT_THROW(_code_, _msg_) throw HT_EXCEPTION(_code_, _msg_)
00335 #define HT_THROW_(_code_) HT_THROW(_code_, "")
00336 #define HT_THROW2(_code_, _ex_, _msg_) throw HT_EXCEPTION2(_code_, _ex_, _msg_)
00337 #define HT_THROW2_(_code_, _ex_) HT_THROW2(_code_, _ex_, "")
00338 
00339 #define HT_THROWF(_code_, _fmt_, ...) \
00340   throw HT_EXCEPTION(_code_, format(_fmt_, __VA_ARGS__))
00341 
00342 #define HT_THROW2F(_code_, _ex_, _fmt_, ...) \
00343   throw HT_EXCEPTION2(_code_, _ex_, format(_fmt_, __VA_ARGS__))
00344 
00345 #define HT_RETHROWF(_fmt_, ...) \
00346   catch (Exception &e) { HT_THROW2F(e.code(), e, _fmt_, __VA_ARGS__); } \
00347   catch (std::bad_alloc &e) { \
00348     HT_THROWF(Error::BAD_MEMORY_ALLOCATION, _fmt_, __VA_ARGS__); \
00349   } \
00350   catch (std::exception &e) { \
00351     HT_THROWF(Error::EXTERNAL, "caught std::exception: %s " _fmt_,  e.what(), \
00352               __VA_ARGS__); \
00353   } \
00354   catch (...) { \
00355     HT_ERRORF("caught unknown exception " _fmt_, __VA_ARGS__); \
00356     throw; \
00357   }
00358 
00359 #define HT_RETHROW(_s_) HT_RETHROWF("%s", _s_)
00360 #define HT_RETHROW_ HT_RETHROW("")
00361 
00362 #define HT_TRY(_s_, _code_) do { \
00363   try { _code_; } \
00364   HT_RETHROW(_s_) \
00365 } while (0)
00366 
00367 
00368 // For catching exceptions in destructors
00369 #define HT_LOG_EXCEPTION(_s_) \
00370   catch (Exception &e) { HT_ERROR_OUT << e <<", "<< _s_ << HT_END; } \
00371   catch (std::bad_alloc &e) { \
00372     HT_ERROR_OUT <<"Out of memory, "<< _s_ << HT_END; } \
00373   catch (std::exception &e) { \
00374     HT_ERROR_OUT <<"Caught exception: "<< e.what() <<", "<< _s_ << HT_END; } \
00375   catch (...) { \
00376     HT_ERROR_OUT <<"Caught unknown exception, "<< _s_ << HT_END; }
00377 
00378 #define HT_TRY_OR_LOG(_s_, _code_) do { \
00379   try { _code_; } \
00380   HT_LOG_EXCEPTION(_s_) \
00381 } while (0)
00382 
00383 
00384 } // namespace Hypertable
00385 
00386 #endif // HYPERTABLE_ERROR_H