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.82 2010/12/08 17:37:37 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 statistics that are always 64-bit numbers
00287      */
00288     typedef uint8_t         large_stat_t; 
00289 
00290     /* 
00291      * For statistics that are 64-bit numbers 
00292      * only when #defined LARGEFILE_AWARE
00293      */
00294 // ARCH_LP64 and LARGEFILE_AWARE are determined by configure
00295 // and set isn config/shore-config.h
00296 #if defined(LARGEFILE_AWARE) || defined(ARCH_LP64)
00297     typedef int8_t          base_stat_t;
00298     typedef double          base_float_t;
00299 #else
00300     typedef int4_t          base_stat_t;
00301     typedef float           base_float_t;
00302 #endif
00303 
00304     typedef float        f4_t;
00305     typedef double        f8_t;
00306 
00307     static const int1_t        int1_max, int1_min;
00308     static const int2_t        int2_max, int2_min;
00309     static const int4_t        int4_max, int4_min;
00310     static const int8_t        int8_max, int8_min;
00311 
00312     static const uint1_t    uint1_max, uint1_min;
00313     static const uint2_t    uint2_max, uint2_min;
00314     static const uint4_t    uint4_max, uint4_min;
00315     static const uint8_t    uint8_max, uint8_min;
00316 
00317     /*
00318      *  miscellaneous
00319      */
00320 
00321 /// helper for alignon
00322 #define alignonarg(a) (((ptrdiff_t)(a))-1)
00323 /// aligns a pointer p on a size a
00324 #define alignon(p,a) (((ptrdiff_t)((ptrdiff_t)(p) + alignonarg(a))) & ~alignonarg(a))
00325 
00326     /*
00327      * turned into a macro for the purpose of folding
00328      * static uint4_t        align(uint4_t sz);
00329      *
00330      * Align to 8-byte boundary.
00331      * We now support *only* 8-byte alignment of records
00332      */
00333 #    ifndef align
00334 #    define ALIGNON 0x8
00335 #    define ALIGNON1 (ALIGNON-1)
00336 #    define align(sz) ((size_t)((sz + ALIGNON1) & ~ALIGNON1))
00337 #    endif /* align */
00338     static bool        is_aligned(size_t sz);
00339     static bool        is_aligned(const void* s);
00340 
00341     static bool        is_big_endian();
00342     static bool        is_little_endian();
00343 
00344     /*!
00345      * strtoi8 and strtou8 act like strto[u]ll with the following
00346      *  two exceptions: the only bases supported are 0, 8, 10, 16;
00347      *  ::errno is not set
00348      */
00349     /**\brief Convert string to 8-byte integer  
00350      *
00351      * strtoi8 acts like strto[u]ll with the following
00352      *  two exceptions: the only bases supported are 0, 8, 10, 16;
00353      *  ::errno is not set
00354      */
00355     static int8_t    strtoi8(const char *, char ** end=0 , int base=0);
00356     /**\brief Convert string to 8-byte unsigned integer.  
00357      *
00358      * strtou8 acts like strto[u]ll with the following
00359      *  two exceptions: the only bases supported are 0, 8, 10, 16;
00360      *  ::errno is not set
00361      */
00362     static uint8_t    strtou8(const char *, char ** end=0, int base=0);
00363 
00364     // Input to an instream
00365     static istream&    _scan_uint8(istream& i, uint8_t &, 
00366                 bool chew_white,
00367                 bool is_signed,
00368                 bool& rangerr);
00369 
00370     static bool        is_finite(const f8_t x);
00371     static bool        is_infinite(const f8_t x);
00372     static bool        is_nan(const f8_t x);
00373     static bool        is_infinite_or_nan(const f8_t x);
00374 
00375     /*
00376      * Endian conversions that don't require any non-shore headers.
00377      * These may not be inlined, but that is the portability tradeoff.
00378      * w_ prefix due to typical macro problems with the names.
00379      * Why not use overloaded args?   Great idea, but unintentional
00380      * conversions could be a big problem with this stuff.
00381      * Used by w_opaque.
00382      */
00383     static uint2_t    w_ntohs(uint2_t);
00384     static uint2_t    w_htons(uint2_t);
00385     static uint4_t    w_ntohl(uint4_t);
00386     static uint4_t    w_htonl(uint4_t);
00387 
00388     ///  standard streams
00389     friend ostream&        operator<<(
00390         ostream&            o,
00391         const w_base_t&            obj);
00392 
00393     /// print a message and abort
00394     static void            assert_failed(
00395         const char*            desc,
00396         const char*            file,
00397         uint4_t             line);
00398 
00399     /// dump core
00400     static    void        abort();
00401 
00402     /**\brief Comparison Operators 
00403      * \enum CompareOp
00404      * */ 
00405     enum CompareOp {
00406     badOp=0x0, eqOp=0x1, gtOp=0x2, geOp=0x3, ltOp=0x4, leOp=0x5,
00407     /* for internal use only: */
00408     NegInf=0x100, eqNegInf, gtNegInf, geNegInf, ltNegInf, leNegInf,
00409     PosInf=0x400, eqPosInf, gtPosInf, gePosInf, ltPosInf, lePosInf
00410     };
00411 
00412     /**\enum lock_mode_t 
00413      * \brief Lock modes for the Storage Manager.
00414      * Note: Capital letters are used to match common usage in DB literature
00415      * Note: Values MUST NOT CHANGE since order is significant.
00416      * \ref SSMLOCK
00417      */
00418     enum lock_mode_t {
00419         NL = 0,         /* no lock                */
00420         IS,         /* intention share (read)        */
00421         IX,            /* intention exclusive (write)        */
00422         SH,            /* share (read)             */
00423         SIX,        /* share with intention exclusive    */
00424         UD,            /* update (allow no more readers)    */
00425         EX            /* exclusive (write)            */
00426     };
00427 
00428     /**\enum lock_duration_t
00429      * \brief Duration for locks
00430      * \ref SSMLOCK
00431      */
00432     enum lock_duration_t {
00433         t_instant     = 0,    /* released as soon as the lock is acquired */
00434         t_short     = 1,    /* held until end of some operation         */
00435         t_medium     = 2,    /* held until explicitly released           */
00436         t_long     = 3,    /* held until xct commits                   */
00437         t_very_long = 4,    /* held across xct boundaries               */
00438         t_num_durations = 5 /* not a duration -- used for typed comparisons */
00439     };
00440 
00441     /**\enum vote_t
00442      * \brief Votes for two-phase commit.
00443      * - vote_readonly : storage manager will return this from 
00444      *   ss_m::prepare_xct when transaction has not logged anything.
00445      *   See also ss_m::force_vote_readonly.
00446      * - vote_abort : Might be returned if error occurs.
00447      * - vote_commit : Usual result of prepare.
00448      * \ref SSM2PC
00449      */
00450     enum vote_t {
00451         vote_bad,    /* illegit value                */
00452         vote_readonly,  /* no ex locks acquired for this tx         */
00453         vote_abort,     /* cannot commit                            */
00454         vote_commit     /* can commit if so told                    */
00455     };
00456 };
00457 
00458 
00459 /* XXX compilers+environment that need this operator defined */
00460 
00461 /**\def w_reset_strstream(s)
00462  *\brief Allow a ostrstream to be reused.  
00463  */
00464 
00465 /* This works for the shore w_strstream.   But, wait, why
00466    is it different for visual c++?  It doesn't need to be?
00467    It is different so you can reset an ordinary strstream 
00468    with it also.    A better solution for w_strstreams and
00469    strstreams would be something overloaded instead of a macro. */
00470 
00471 #if defined (__SUNPRO_CC)
00472 #define w_reset_strstream(s) \
00473   do { \
00474     s.clear();                \
00475     s.seekp(0); \
00476   } while(0)
00477 #else
00478 #define    w_reset_strstream(s)        \
00479     do {                \
00480         s.clear();        \
00481         s.seekp(ios::beg);    \
00482     } while (0)
00483 #endif
00484 
00485 
00486 /*--------------------------------------------------------------*
00487  *  w_base_t::is_aligned()                    *
00488  *--------------------------------------------------------------*/
00489 inline bool
00490 w_base_t::is_aligned(size_t sz)
00491 {
00492     return (align(sz) == sz);
00493 }
00494 
00495 inline bool
00496 w_base_t::is_aligned(const void* s)
00497 {
00498     /* XXX works OK if there is a size mismatch because we are looking
00499        at the *low* bits */
00500     return is_aligned((ptrdiff_t)(s));
00501 }
00502 
00503 /*--------------------------------------------------------------*
00504  *  w_base_t::is_big_endian()                    *
00505  *--------------------------------------------------------------*/
00506 inline bool w_base_t::is_big_endian()
00507 {
00508 #ifdef WORDS_BIGENDIAN
00509     return true;
00510 #else
00511     return false;
00512 #endif
00513 }
00514 
00515 /*--------------------------------------------------------------*
00516  *  w_base_t::is_little_endian()                *
00517  *--------------------------------------------------------------*/
00518 inline bool
00519 w_base_t::is_little_endian()
00520 {
00521     return ! is_big_endian();
00522 }
00523 
00524 /**\brief Class that adds virtual destructor to w_base_t. 
00525  */
00526 class w_vbase_t : public w_base_t {
00527 public:
00528     NORET                w_vbase_t()    {};
00529     virtual NORET        ~w_vbase_t()    {};
00530 };
00531 
00532 /*
00533  * These types are auto-initialized filler space for alignment
00534  * in structures.  The auto init helps with purify.
00535  *
00536  * XXX Some of the users of these structures DEPEND on zero
00537  * fill (sm keys, etc). Eventually this will be seperated into
00538  * zero fill and plain fill (zeroed with ZERO_INIT).  Until then
00539  * these must always be initialized to 0.
00540  */
00541 /**\brief Auto-initialized 1-byte filler for alignment of structures*/
00542 struct fill1 {
00543     w_base_t::uint1_t u1;
00544     fill1() : u1(0) {}
00545 };
00546 
00547 /**\brief Auto-initialized 2-byte filler for alignment of structures*/
00548 struct fill2 {
00549     w_base_t::uint2_t u2;
00550     fill2() : u2(0) {}
00551 };
00552 
00553 /**\brief Auto-initialized 3-byte filler for alignment of structures*/
00554 struct fill3 {
00555     w_base_t::uint1_t    u1[3];
00556     fill3() { u1[0] = u1[1] = u1[2] = 0; }
00557 };
00558 
00559 /**\brief Auto-initialized 4-byte filler for alignment of structures*/
00560 struct fill4 {
00561     w_base_t::uint4_t u4;
00562     fill4() : u4(0) {}
00563 };
00564 
00565 
00566 #include <w_autodel.h>
00567 #include <w_error.h>
00568 #include <w_rc.h>
00569 
00570 template<bool B> struct CompileTimeAssertion;
00571 /** \brief Compile-time assertion trick. 
00572  * \details
00573  * See compile_time_assert.
00574  */
00575 template<> struct CompileTimeAssertion<true> { void reference() {} };
00576 
00577 /** \brief Compile-time assertion trick. 
00578  * \details
00579  * If the assertion fails 
00580  * you will get a compile error.
00581  * The problem is that you will also get an unused variable
00582  * complaint if warnings are turned on, so we make a bogus
00583  * reference to the named structure.
00584  *
00585  * This is used by macros 
00586  * - ASSERT_FITS_IN_LONGLONG 
00587  * - ASSERT_FITS_IN_POINTER 
00588  *   which are enabled only if built with some
00589  *   debug level 1 or above (e.g., configure --with-debug-level1)
00590  *   This enables us to continue to build a --disable-lp64 system even
00591  *   though it's known yet fully supported (not safe).
00592  *
00593  */
00594 template<typename T> struct compile_time_assert 
00595 {
00596     compile_time_assert() {
00597         CompileTimeAssertion<sizeof(long) == 8> assert_8byte_long;
00598         CompileTimeAssertion<sizeof(long) >= sizeof(T)> assert_long_holds_T;
00599     }
00600 };
00601 
00602 #if W_DEBUG_LEVEL > 4
00603 #define ASSERT_FITS_IN_LONGLONG(T) {                \
00604     CompileTimeAssertion<sizeof(long long) >= sizeof(T)> assert__##T##__fits_in_longlong; \
00605     assert__##T##__fits_in_longlong.reference(); \
00606     }                    
00607 #define ASSERT_FITS_IN_POINTER(T) {                \
00608     CompileTimeAssertion<sizeof(void*) >= sizeof(T)> assert__##T##__fits_in_pointer; \
00609     assert__##T##__fits_in_pointer.reference(); \
00610     }                    
00611 #else
00612 
00613 #define ASSERT_FITS_IN_POINTER(T) 
00614 #define ASSERT_FITS_IN_LONGLONG(T) 
00615 #endif
00616 /*<std-footer incl-file-exclusion='W_BASE_H'>  -- do not edit anything below this line -- */
00617 
00618 #endif          /*</std-footer>*/

Generated on Thu Dec 9 08:42:27 2010 for Shore Storage Manager by  doxygen 1.4.7