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

Generated on Mon Jan 2 15:13:56 2012 for Shore Storage Manager by  doxygen 1.4.7