w_base.h

Go to the documentation of this file.
00001 /* -*- mode:C++; c-basic-offset:4 -*-
00002      Shore-MT -- Multi-threaded port of the SHORE storage manager
00003    
00004                        Copyright (c) 2007-2009
00005       Data Intensive Applications and Systems Labaratory (DIAS)
00006                Ecole Polytechnique Federale de Lausanne
00007    
00008                          All Rights Reserved.
00009    
00010    Permission to use, copy, modify and distribute this software and
00011    its documentation is hereby granted, provided that both the
00012    copyright notice and this permission notice appear in all copies of
00013    the software, derivative works or modified versions, and any
00014    portions thereof, and that both notices appear in supporting
00015    documentation.
00016    
00017    This code is distributed in the hope that it will be useful, but
00018    WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
00020    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
00021    RESULTING FROM THE USE OF THIS SOFTWARE.
00022 */
00023 
00024 /*<std-header orig-src='shore' incl-file-exclusion='W_BASE_H'>
00025 
00026  $Id: w_base.h,v 1.81 2010/07/07 20:50:12 nhall Exp $
00027 
00028 SHORE -- Scalable Heterogeneous Object REpository
00029 
00030 Copyright (c) 1994-99 Computer Sciences Department, University of
00031                       Wisconsin -- Madison
00032 All Rights Reserved.
00033 
00034 Permission to use, copy, modify and distribute this software and its
00035 documentation is hereby granted, provided that both the copyright
00036 notice and this permission notice appear in all copies of the
00037 software, derivative works or modified versions, and any portions
00038 thereof, and that both notices appear in supporting documentation.
00039 
00040 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00041 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00042 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00043 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00044 
00045 This software was developed with support by the Advanced Research
00046 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00047 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00048 Further funding for this work was provided by DARPA through
00049 Rome Research Laboratory Contract No. F30602-97-2-0247.
00050 
00051 */
00052 
00053 #ifndef W_BASE_H
00054 #define W_BASE_H
00055 
00056 #include "w_defines.h"
00057 
00058 /*  -- do not edit anything above this line --   </std-header>*/
00059 
00060 /**\file w_base.h
00061  *
00062  *\ingroup MACROS
00063  * Basic types.
00064  */
00065 
00066 /*******************************************************/
00067 /* get configuration definitions from config/shore.def */
00068 /*
00069  * WARNING: if ON and OFF are defined, we must turn them off asap
00070  * because ON and OFF are re-definedelsewhere as enums
00071  */
00072 #ifdef ON
00073 #undef ON
00074 #endif
00075 
00076 #ifdef OFF
00077 #undef OFF
00078 #endif
00079 /* end configuration definitions                       */
00080 /*******************************************************/
00081 
00082 
00083 #define W_UNIX
00084 
00085 #ifdef __GNUG__
00086 #pragma interface
00087 #endif
00088 
00089 #include <w_stream.h>
00090 
00091 #ifndef W_WORKAROUND_H
00092 #include "w_workaround.h"
00093 #endif
00094 
00095 #define NORET        /**/
00096 #define CAST(t,o) ((t)(o))
00097 #define    W_UNUSED(x)    /**/
00098 
00099 
00100 #if W_DEBUG_LEVEL>0
00101 #define W_IFDEBUG1(x)    x
00102 #define W_IFNDEBUG1(x)    /**/
00103 #else
00104 #define W_IFDEBUG1(x)    /**/
00105 #define W_IFNDEBUG1(x)    x
00106 #endif
00107 
00108 #if W_DEBUG_LEVEL>1
00109 #define W_IFDEBUG2(x)    x
00110 #define W_IFNDEBUG2(x)    /**/
00111 #else
00112 #define W_IFDEBUG2(x)    /**/
00113 #define W_IFNDEBUG2(x)    x
00114 #endif
00115 
00116 #if W_DEBUG_LEVEL>2
00117 #define W_IFDEBUG3(x)    x
00118 #define W_IFNDEBUG3(x)    /**/
00119 #else
00120 #define W_IFDEBUG3(x)    /**/
00121 #define W_IFNDEBUG3(x)    x
00122 #endif
00123 
00124 #if W_DEBUG_LEVEL>3
00125 #define W_IFDEBUG4(x)    x
00126 #define W_IFNDEBUG4(x)    /**/
00127 #else
00128 #define W_IFDEBUG4(x)    /**/
00129 #define W_IFNDEBUG4(x)    x
00130 #endif
00131 
00132 #define W_IFDEBUG9(x)    /**/
00133 #define W_IFNDEBUG9(x)    x
00134 
00135 //////////////////////////////////////////////////////////
00136 #undef  W_IFDEBUG
00137 #undef  W_IFNDEBUG
00138 #if W_DEBUG_LEVEL==1
00139 #define W_IFDEBUG(x)    W_IFDEBUG1(x)
00140 #define W_IFNDEBUG(x)    W_IFNDEBUG1(x)
00141 #endif
00142 
00143 #if W_DEBUG_LEVEL==2
00144 #define W_IFDEBUG(x)    W_IFDEBUG2(x)
00145 #define W_IFNDEBUG(x)    W_IFNDEBUG2(x)
00146 #endif
00147 
00148 #if W_DEBUG_LEVEL==3
00149 #define W_IFDEBUG(x)    W_IFDEBUG3(x)
00150 #define W_IFNDEBUG(x)    W_IFNDEBUG3(x)
00151 #endif
00152 
00153 #if W_DEBUG_LEVEL==4
00154 #define W_IFDEBUG(x)    W_IFDEBUG4(x)
00155 #define W_IFNDEBUG(x)    W_IFNDEBUG4(x)
00156 #endif
00157 
00158 #ifndef W_IFDEBUG
00159 #define W_IFDEBUG(x) /**/
00160 #endif
00161 #ifndef W_IFNDEBUG
00162 #define W_IFNDEBUG(x) x
00163 #endif
00164 
00165 //////////////////////////////////////////////////////////
00166 
00167 #ifdef W_TRACE
00168 #define    W_IFTRACE(x)    x
00169 #define    W_IFNTRACE(x)    /**/
00170 #else
00171 #define    W_IFTRACE(x)    /**/
00172 #define    W_IFNTRACE(x)    x
00173 #endif
00174 
00175 #if defined(W_DEBUG_SPACE)
00176 void     w_space(int line, const char *file);
00177 #define W_SPACE w_space(__LINE__,__FILE__)
00178 #else
00179 #define W_SPACE
00180 #endif
00181 
00182 /// Default assert/debug level is 0.
00183 #define w_assert0(x)    do {                        \
00184     if (!(x)) w_base_t::assert_failed(#x, __FILE__, __LINE__);    \
00185     W_SPACE;                            \
00186 } while(0)
00187 
00188 #ifndef W_DEBUG_LEVEL
00189 #define W_DEBUG_LEVEL 0
00190 #endif
00191 
00192 /// Level 1 should not add significant extra time.
00193 #if W_DEBUG_LEVEL>=1
00194 #define w_assert1(x)    w_assert0(x)
00195 #else
00196 #define w_assert1(x)    /**/
00197 #endif
00198 
00199 /// Level 2 adds some time.
00200 #if W_DEBUG_LEVEL>=2
00201 #define w_assert2(x)    w_assert1(x)
00202 #else
00203 #define w_assert2(x)    /**/
00204 #endif
00205 
00206 /// Level 3 definitely adds significant time.
00207 #if W_DEBUG_LEVEL>=3
00208 #define w_assert3(x)    w_assert1(x)
00209 #else
00210 #define w_assert3(x)    /**/
00211 #endif
00212 
00213 /// Level 4 can be a hog.
00214 #if W_DEBUG_LEVEL>=4
00215 #define w_assert4    w_assert1(x)
00216 #else
00217 #define w_assert4(x)    /**/
00218 #endif
00219 
00220 /// Level 5 is not yet used.
00221 #if W_DEBUG_LEVEL>=5
00222 #define w_assert5    w_assert1(x)
00223 #else
00224 #define w_assert5(x)    /**/
00225 #endif
00226 
00227 /*
00228  * The whole idea here is to gradually move assert3's, which have
00229  * not been established to be useful in an mt-environment, to anoter
00230  * assert level. 
00231  * First: make them 9. Then gradually move them to level 2->5, based
00232  * on the cost and frequency of usefulness.
00233  * Make them 2 if you want them for a 'normal' debug system.
00234 */
00235 /// changing an assert to an assert9 turns it off. 
00236 #define w_assert9(x)    /**/
00237 
00238 /**\brief  Cast to treat an enum as integer value.  
00239  *
00240  * This is used when
00241  * a operator<< doesn't exist for the enum.  The use of the macro
00242  * indicates that this enum would be printed if it had a printer,
00243  * rather than wanting the integer value of the enum
00244  */
00245 #define    W_ENUM(x)    ((int)(x))
00246 
00247 /**\brief  Cast to treat a pointer as a non-(char *) value.  
00248  *
00249  * This is used when
00250  * a operator<< is used on a pointer.   Without this cast, some values
00251  * would bind to 'char *' and attempt  to print a string, rather than
00252  * printing the desired pointer value.
00253  */
00254 #define    W_ADDR(x)    ((void *)(x))
00255 
00256 class w_rc_t;
00257 
00258 /**\brief The mother base class for most types.
00259  *
00260  * \attention These basic 1,2,4, and 8-byte types predate the
00261  * now-standard "u8", etc.
00262  * When these were developed, we used the count to
00263  * refer to bytes, not bits.  So for new users, 
00264  * this might take a bit of getting-used-to.
00265  */
00266 class w_base_t {
00267 public:
00268     /*
00269      *  shorthands
00270      */
00271     typedef unsigned char    u_char;
00272     typedef unsigned short    u_short;
00273 #ifdef FC_COMPAT_32BIT_ULONG
00274     /* keep u_long 32 bits on a 64 bit platform; see shore.def */
00275     typedef unsigned        u_long;
00276 #else
00277     typedef unsigned long    u_long;
00278 #endif
00279     // typedef w_rc_t        rc_t;
00280 
00281     /*
00282      *  basic types
00283      */
00284     typedef char         int1_t;
00285     typedef u_char       uint1_t;
00286     typedef short        int2_t;
00287     typedef u_short      uint2_t;
00288     typedef int          int4_t;
00289     typedef u_int        uint4_t;
00290 
00291 #if defined(ARCH_LP64)
00292     typedef    long              int8_t;
00293     typedef unsigned long        uint8_t;
00294 #elif defined(__GNUG__)
00295     typedef long long            int8_t;
00296     typedef unsigned long long   uint8_t;
00297 #else
00298 #error int8_t Not supported for this compiler.
00299 #endif
00300 
00301     /* 
00302      * For statistics that are always 64-bit numbers
00303      */
00304     typedef uint8_t         large_stat_t; 
00305 
00306     /* 
00307      * For statistics that are 64-bit numbers 
00308      * only when #defined LARGEFILE_AWARE
00309      */
00310 #if defined(LARGEFILE_AWARE) || defined(ARCH_LP64)
00311     typedef uint8_t         base_stat_t;
00312     typedef double          base_float_t;
00313 #else
00314     typedef uint4_t         base_stat_t;
00315     typedef float           base_float_t;
00316 #endif
00317 
00318     typedef float        f4_t;
00319     typedef double        f8_t;
00320 
00321     static const int1_t        int1_max, int1_min;
00322     static const int2_t        int2_max, int2_min;
00323     static const int4_t        int4_max, int4_min;
00324     static const int8_t        int8_max, int8_min;
00325 
00326     static const uint1_t    uint1_max, uint1_min;
00327     static const uint2_t    uint2_max, uint2_min;
00328     static const uint4_t    uint4_max, uint4_min;
00329     static const uint8_t    uint8_max, uint8_min;
00330 
00331     /*
00332      *  miscellaneous
00333      */
00334 
00335 /// helper for alignon
00336 #define alignonarg(a) (((ptrdiff_t)(a))-1)
00337 /// aligns a pointer p on a size a
00338 #define alignon(p,a) (((ptrdiff_t)((ptrdiff_t)(p) + alignonarg(a))) & ~alignonarg(a))
00339 
00340     /*
00341      * turned into a macro for the purpose of folding
00342      * static uint4_t        align(uint4_t sz);
00343      *
00344      * Align to 8-byte boundary.
00345      * We now support *only* 8-byte alignment of records
00346      */
00347 #    ifndef align
00348 #    define ALIGNON 0x8
00349 #    define ALIGNON1 (ALIGNON-1)
00350 #    define align(sz) ((size_t)((sz + ALIGNON1) & ~ALIGNON1))
00351 #    endif /* align */
00352     static bool        is_aligned(size_t sz);
00353     static bool        is_aligned(const void* s);
00354 
00355     static bool        is_big_endian();
00356     static bool        is_little_endian();
00357 
00358     /*!
00359      * strtoi8 and strtou8 act like strto[u]ll with the following
00360      *  two exceptions: the only bases supported are 0, 8, 10, 16;
00361      *  ::errno is not set
00362      */
00363     /**\brief Convert string to 8-byte integer  
00364      *
00365      * strtoi8 acts like strto[u]ll with the following
00366      *  two exceptions: the only bases supported are 0, 8, 10, 16;
00367      *  ::errno is not set
00368      */
00369     static int8_t    strtoi8(const char *, char ** end=0 , int base=0);
00370     /**\brief Convert string to 8-byte unsigned integer.  
00371      *
00372      * strtou8 acts like strto[u]ll with the following
00373      *  two exceptions: the only bases supported are 0, 8, 10, 16;
00374      *  ::errno is not set
00375      */
00376     static uint8_t    strtou8(const char *, char ** end=0, int base=0);
00377 
00378     // Input to an instream
00379     static istream&    _scan_uint8(istream& i, uint8_t &, 
00380                 bool chew_white,
00381                 bool is_signed,
00382                 bool& rangerr);
00383 
00384     static bool        is_finite(const f8_t x);
00385     static bool        is_infinite(const f8_t x);
00386     static bool        is_nan(const f8_t x);
00387     static bool        is_infinite_or_nan(const f8_t x);
00388 
00389     /*
00390      * Endian conversions that don't require any non-shore headers.
00391      * These may not be inlined, but that is the portability tradeoff.
00392      * w_ prefix due to typical macro problems with the names.
00393      * Why not use overloaded args?   Great idea, but unintentional
00394      * conversions could be a big problem with this stuff.
00395      * Used by w_opaque.
00396      */
00397     static uint2_t    w_ntohs(uint2_t);
00398     static uint2_t    w_htons(uint2_t);
00399     static uint4_t    w_ntohl(uint4_t);
00400     static uint4_t    w_htonl(uint4_t);
00401 
00402     ///  standard streams
00403     friend ostream&        operator<<(
00404         ostream&            o,
00405         const w_base_t&            obj);
00406 
00407     /// print a message and abort
00408     static void            assert_failed(
00409         const char*            desc,
00410         const char*            file,
00411         uint4_t             line);
00412 
00413     /// dump core
00414     static    void        abort();
00415 
00416     /**\brief Comparison Operators 
00417      * \enum CompareOp
00418      * */ 
00419     enum CompareOp {
00420     badOp=0x0, eqOp=0x1, gtOp=0x2, geOp=0x3, ltOp=0x4, leOp=0x5,
00421     /* for internal use only: */
00422     NegInf=0x100, eqNegInf, gtNegInf, geNegInf, ltNegInf, leNegInf,
00423     PosInf=0x400, eqPosInf, gtPosInf, gePosInf, ltPosInf, lePosInf
00424     };
00425 
00426     /**\enum lock_mode_t 
00427      * \brief Lock modes for the Storage Manager.
00428      * Note: Capital letters are used to match common usage in DB literature
00429      * Note: Values MUST NOT CHANGE since order is significant.
00430      * \ref SSMLOCK
00431      */
00432     enum lock_mode_t {
00433         NL = 0,         /* no lock                */
00434         IS,         /* intention share (read)        */
00435         IX,            /* intention exclusive (write)        */
00436         SH,            /* share (read)             */
00437         SIX,        /* share with intention exclusive    */
00438         UD,            /* update (allow no more readers)    */
00439         EX            /* exclusive (write)            */
00440     };
00441 
00442     /**\enum lock_duration_t
00443      * \brief Duration for locks
00444      * \ref SSMLOCK
00445      */
00446     enum lock_duration_t {
00447         t_instant     = 0,    /* released as soon as the lock is acquired */
00448         t_short     = 1,    /* held until end of some operation         */
00449         t_medium     = 2,    /* held until explicitly released           */
00450         t_long     = 3,    /* held until xct commits                   */
00451         t_very_long = 4,    /* held across xct boundaries               */
00452         t_num_durations = 5 /* not a duration -- used for typed comparisons */
00453     };
00454 
00455     /**\enum vote_t
00456      * \brief Votes for two-phase commit.
00457      * - vote_readonly : storage manager will return this from 
00458      *   ss_m::prepare_xct when transaction has not logged anything.
00459      *   See also ss_m::force_vote_readonly.
00460      * - vote_abort : Might be returned if error occurs.
00461      * - vote_commit : Usual result of prepare.
00462      * \ref SSM2PC
00463      */
00464     enum vote_t {
00465         vote_bad,    /* illegit value                */
00466         vote_readonly,  /* no ex locks acquired for this tx         */
00467         vote_abort,     /* cannot commit                            */
00468         vote_commit     /* can commit if so told                    */
00469     };
00470 };
00471 
00472 
00473 /* XXX compilers+environment that need this operator defined */
00474 
00475 /**\def w_reset_strstream(s)
00476  *\brief Allow a ostrstream to be reused.  
00477  */
00478 
00479 /* This works for the shore w_strstream.   But, wait, why
00480    is it different for visual c++?  It doesn't need to be?
00481    It is different so you can reset an ordinary strstream 
00482    with it also.    A better solution for w_strstreams and
00483    strstreams would be something overloaded instead of a macro. */
00484 
00485 #if defined (__SUNPRO_CC)
00486 #define w_reset_strstream(s) \
00487   do { \
00488     s.clear();                \
00489     s.seekp(0); \
00490   } while(0)
00491 #else
00492 #define    w_reset_strstream(s)        \
00493     do {                \
00494         s.clear();        \
00495         s.seekp(ios::beg);    \
00496     } while (0)
00497 #endif
00498 
00499 
00500 /*--------------------------------------------------------------*
00501  *  w_base_t::is_aligned()                    *
00502  *--------------------------------------------------------------*/
00503 inline bool
00504 w_base_t::is_aligned(size_t sz)
00505 {
00506     return (align(sz) == sz);
00507 }
00508 
00509 inline bool
00510 w_base_t::is_aligned(const void* s)
00511 {
00512     /* XXX works OK if there is a size mismatch because we are looking
00513        at the *low* bits */
00514     return is_aligned((ptrdiff_t)(s));
00515 }
00516 
00517 /*--------------------------------------------------------------*
00518  *  w_base_t::is_big_endian()                    *
00519  *--------------------------------------------------------------*/
00520 inline bool w_base_t::is_big_endian()
00521 {
00522 #ifdef WORDS_BIGENDIAN
00523     return true;
00524 #else
00525     return false;
00526 #endif
00527 }
00528 
00529 /*--------------------------------------------------------------*
00530  *  w_base_t::is_little_endian()                *
00531  *--------------------------------------------------------------*/
00532 inline bool
00533 w_base_t::is_little_endian()
00534 {
00535     return ! is_big_endian();
00536 }
00537 
00538 /**\brief Class that adds virtual destructor to w_base_t. 
00539  */
00540 class w_vbase_t : public w_base_t {
00541 public:
00542     NORET                w_vbase_t()    {};
00543     virtual NORET        ~w_vbase_t()    {};
00544 };
00545 
00546 /*
00547  * These types are auto-initialized filler space for alignment
00548  * in structures.  The auto init helps with purify.
00549  *
00550  * XXX Some of the users of these structures DEPEND on zero
00551  * fill (sm keys, etc). Eventually this will be seperated into
00552  * zero fill and plain fill (zeroed with ZERO_INIT).  Until then
00553  * these must always be initialized to 0.
00554  */
00555 /**\brief Auto-initialized 1-byte filler for alignment of structures*/
00556 struct fill1 {
00557     w_base_t::uint1_t u1;
00558     fill1() : u1(0) {}
00559 };
00560 
00561 /**\brief Auto-initialized 2-byte filler for alignment of structures*/
00562 struct fill2 {
00563     w_base_t::uint2_t u2;
00564     fill2() : u2(0) {}
00565 };
00566 
00567 /**\brief Auto-initialized 3-byte filler for alignment of structures*/
00568 struct fill3 {
00569     w_base_t::uint1_t    u1[3];
00570     fill3() { u1[0] = u1[1] = u1[2] = 0; }
00571 };
00572 
00573 /**\brief Auto-initialized 4-byte filler for alignment of structures*/
00574 struct fill4 {
00575     w_base_t::uint4_t u4;
00576     fill4() : u4(0) {}
00577 };
00578 
00579 
00580 #include <w_autodel.h>
00581 #include <w_error.h>
00582 #include <w_rc.h>
00583 
00584 template<bool B> struct CompileTimeAssertion;
00585 /** \brief Compile-time assertion trick. 
00586  * \details
00587  * See compile_time_assert.
00588  */
00589 template<> struct CompileTimeAssertion<true> { void reference() {} };
00590 
00591 /** \brief Compile-time assertion trick. 
00592  * \details
00593  * If the assertion fails 
00594  * you will get a compile error.
00595  * The problem is that you will also get an unused variable
00596  * complaint if warnings are turned on, so we make a bogus
00597  * reference to the named structure.
00598  *
00599  * This is used by macros 
00600  * - ASSERT_FITS_IN_LONGLONG 
00601  * - ASSERT_FITS_IN_POINTER 
00602  *   which are enabled only if built with some
00603  *   debug level 1 or above (e.g., configure --with-debug-level1)
00604  *   This enables us to continue to build a --disable-lp64 system even
00605  *   though it's known yet fully supported (not safe).
00606  *
00607  */
00608 template<typename T> struct compile_time_assert 
00609 {
00610     compile_time_assert() {
00611         CompileTimeAssertion<sizeof(long) == 8> assert_8byte_long;
00612         CompileTimeAssertion<sizeof(long) >= sizeof(T)> assert_long_holds_T;
00613     }
00614 };
00615 
00616 #if W_DEBUG_LEVEL > 4
00617 #define ASSERT_FITS_IN_LONGLONG(T) {                \
00618     CompileTimeAssertion<sizeof(long long) >= sizeof(T)> assert__##T##__fits_in_longlong; \
00619     assert__##T##__fits_in_longlong.reference(); \
00620     }                    
00621 #define ASSERT_FITS_IN_POINTER(T) {                \
00622     CompileTimeAssertion<sizeof(void*) >= sizeof(T)> assert__##T##__fits_in_pointer; \
00623     assert__##T##__fits_in_pointer.reference(); \
00624     }                    
00625 #else
00626 
00627 #define ASSERT_FITS_IN_POINTER(T) 
00628 #define ASSERT_FITS_IN_LONGLONG(T) 
00629 #endif
00630 /*<std-footer incl-file-exclusion='W_BASE_H'>  -- do not edit anything below this line -- */
00631 
00632 #endif          /*</std-footer>*/

Generated on Wed Jul 7 17:22:32 2010 for Shore Storage Manager by  doxygen 1.4.7