vtable.h

00001 /*<std-header orig-src='shore' incl-file-exclusion='VTABLE_INFO_H'>
00002 
00003  $Id: vtable.h,v 1.4 2010/07/07 20:50:12 nhall Exp $
00004 
00005 SHORE -- Scalable Heterogeneous Object REpository
00006 
00007 Copyright (c) 1994-99 Computer Sciences Department, University of
00008                       Wisconsin -- Madison
00009 All Rights Reserved.
00010 
00011 Permission to use, copy, modify and distribute this software and its
00012 documentation is hereby granted, provided that both the copyright
00013 notice and this permission notice appear in all copies of the
00014 software, derivative works or modified versions, and any portions
00015 thereof, and that both notices appear in supporting documentation.
00016 
00017 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00018 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00019 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00020 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00021 
00022 This software was developed with support by the Advanced Research
00023 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00024 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00025 Further funding for this work was provided by DARPA through
00026 Rome Research Laboratory Contract No. F30602-97-2-0247.
00027 
00028 */
00029 
00030 #ifndef VTABLE_INFO_H
00031 #define VTABLE_INFO_H
00032 
00033 #include "w_defines.h"
00034 
00035 /*  -- do not edit anything above this line --   </std-header>*/
00036 
00037 /* skip documentation for this for now. */
00038 
00039 #include <cstring>
00040 
00041 /**\brief Structure for converting arbitrary info to a row of a virtual table.  
00042  *
00043  * \details
00044  * A datum in a virtual table is an 64-byte string.
00045  * The strings usually take the form "name value".
00046  * A vtable_row_t is an array of these data, and represents a row in
00047  * a virtual table.
00048  * It is a structure "imposed" on an already-allocated block of data. 
00049  * This struct
00050  * does NOT allocate or deallocate anything.
00051  *
00052  * Each "attribute" or entry of the row is identified by an integer.
00053  */
00054 class vtable_row_t {
00055 private:
00056     int            N;
00057     int            M; // max value size
00058     int            _in_use;
00059     char           *_list;
00060     char           *_list_end;
00061     char           *_entry[1];
00062 
00063 public:
00064     // Must construct a row with at least 1 attribute.
00065     NORET vtable_row_t() : N(0), M(0), _in_use(0), _list(NULL),
00066                                 _list_end(NULL) { dump("construct"); }
00067     NORET ~vtable_row_t() { }
00068 
00069     /// Number of attributes in the row.
00070     int   quant() const { return _in_use; }
00071 
00072     // vtable_t needs to make sure this doesn't exceed the space
00073     // it allocated.
00074     char *end() const { return _list_end; }
00075     int  size_in_bytes() const { return _list_end - (char *)this; }
00076 
00077     /// Return # bytes user must allocate to accommodate n attributes of
00078     /// m bytes each plus whatever overhead we have in this structure.
00079     static int   bytes_required_for(int n, int m) {
00080         return 
00081             sizeof(vtable_row_t) 
00082             + (n-1) * sizeof(char * /*_entry[0]*/) 
00083             + (n * m);
00084     }
00085     int   value_size() const { return M; }
00086 
00087     /// Initialize a row for n attributes. Must be at least 1.
00088     /// Assumes we have enough space for this to happen.
00089     /// User of this row must have allocated enough space.
00090     /// Let the maximum value size be m.
00091     void init_for_attributes(int n, int m) 
00092     {
00093         w_assert0(n>0);
00094         N = n; 
00095         M = m; 
00096 
00097         // had better have been allocated by caller.
00098         memset(&_entry[0], '\0', n * m +
00099                 + (n*sizeof(_entry[0])));
00100 
00101         _in_use=0;
00102         _list = (char *)&_entry[N]; // one past the last _entry
00103         _list_end = _list; // none in use
00104         _entry[0] = _list;
00105 
00106 #if W_DEBUG_LEVEL > 3
00107         // had better have been initialized by caller
00108         for(int a=0; a<n; a++) {
00109             w_assert3(strlen(_get_const(a)) == 0); 
00110         }
00111 #endif
00112         w_assert1(size_in_bytes() <= bytes_required_for(n,m));
00113     }
00114 
00115     /// realloc for larger number of attributes. This means we
00116     /// have to shift around the values. We don't allow change of
00117     /// maximum value size (M)
00118     void reinit_for_attributes(int n) 
00119     {
00120         int additional = n - N;
00121         if(additional > 0) {
00122             int bytes = sizeof(_entry[0]) * additional;
00123 
00124             // move the data. args: dest, src, amt
00125             memmove(&_list[additional], &_list[0], bytes);
00126             for(int i=N; i < n; i++) {
00127                 _entry[i] = 0;
00128             }
00129             _list = &_list[bytes];
00130             _list_end = &_list_end[bytes];
00131             // _in_use doesn't change.
00132         }
00133     }
00134 
00135     /// Convert the unsigned int to a string datum at the location for \e a.
00136     void set_uint(int a, unsigned int v);
00137     /// Convert the int to a string datum at the location for \e a.
00138     void set_int(int a, int v);
00139     /// Convert the base_stat_t to a string datum at the location for \e a.
00140     void set_base(int a, w_base_t::base_stat_t v);
00141     /// Convert the base_float_t to a string datum at the location for \e a.
00142     void set_base(int a, w_base_t::base_float_t v);
00143     /// Copy the string to a string datum at the location for \e a.
00144     void set_string(int a, const char *v);
00145 
00146     /// Return whatever string is already written to the location for \e a.
00147     const char *operator[](int a) const {
00148         return _get_const(a);
00149     }
00150 
00151 
00152     ostream& operator<<(ostream &o);
00153     /// Return the number of entries/locations/attributes for this "row".
00154     int n() const { return N; }
00155 
00156     void dump(const char *msg)const;
00157 private:
00158     vtable_row_t(const vtable_row_t&); // disabled 
00159     vtable_row_t& operator=(const vtable_row_t&); // disabled 
00160     /// From a given int a, return a pointer to the entry
00161     /// for that int so that we can stuff something into 
00162     /// that entry. NO ALIGNMENT!
00163     char *_insert_attribute(int a) {
00164         w_assert1(a < N);
00165         w_assert1(a >= 0);
00166         char * v = (char *)_entry[a];
00167         if(v==NULL) {
00168             v = (_entry[a] = _list_end);
00169         }
00170         return v;
00171     }
00172 
00173     const char *_get_const(int a) const {
00174         const char *x =  (const char *)_entry[a];
00175         w_assert1(x < _list_end);
00176         return x;
00177     }
00178 
00179     /// Notify the row that we inserted something in attribute #a.
00180     void _inserted(int a);
00181 };
00182 
00183 /**\brief Structure for converting lower layer info to a virtual table.  
00184  * \details
00185  * This structure holds a set of vtable_row_t, which is a set of attributes.
00186  * The space for the whole mess is allocated by the vtable_t, and the rows
00187  * must be populated strictly in sequence, and the attributes of the rows
00188  * likewise must be populated in sequence.  As a row is populated,
00189  * space for the attributes is peeled off the chunk allocated by the vtable.
00190  * The idea here is to create, without undue heap activity, a 
00191  * string-based (untyped)
00192  * virtual table containing various and sundry information.
00193  * The things that can be gathered and stuffed into virtual tables include:
00194  * Info about the threads, transactions.
00195  * A server could, if it so chose, convert this information into a
00196  * relational table.
00197  * Originally this was used to send across the wire, via RPC, this info
00198  * to a client in client/server SHORE. Now it has been stripped down.
00199  * Someday if this facility proves useful, we should make 
00200  * this collect typed information so that the attributes
00201  * can be int or double.  But for now, they are string representations of the
00202  * values.
00203  *
00204  * Test programs may use ss_m::xct_collect(vtable &) and kin,
00205  * and output the results with the operator<< for vtable_t.
00206  */
00207 class vtable_t {
00208 public:
00209     NORET vtable_t() : _rows(0), _rows_filled(0),
00210        _rowsize_attributes(0), _rowsize_bytes(0),
00211        _array_alias(NULL) {}
00212 
00213     /// Initialize table with \e R rows, with up to \e A attributes, 
00214     /// each with a maximum size of \e S bytes.
00215     int init(int R, int A, int S);
00216 
00217     NORET ~vtable_t() {
00218         delete[] _array_alias;
00219         _array_alias = NULL;
00220     }
00221 
00222     vtable_row_t& operator[] (int i) const {
00223         // called by updater so can't use this assertion
00224         // w_assert1(i < _rows_filled);
00225         return *_get_row(i);
00226     }
00227 
00228     ostream& operator<<(ostream &o) const;
00229 
00230     /// Return number of rows filled.
00231     int            quant() const { return _rows_filled; }
00232     int            size() const { return _rows; }
00233     void           filled_one();
00234     void           back_out(int n) {  _rows_filled -= n; }
00235     int            realloc();
00236 private:
00237     vtable_t(const vtable_t&); // disabled
00238     vtable_t& operator=(const vtable_t&); // disabled
00239 
00240     vtable_row_t* _get_row(int i) const;
00241 
00242     int            _rows;
00243     int            _rows_filled;
00244     int            _rowsize_attributes; //#strings
00245     int            _rowsize_bytes;//#string * sizeof string
00246     char*          _array_alias;
00247 
00248 };
00249 
00250 /**\brief Template class for converting lower layer info to a virtual table.  
00251  * \details
00252  * This function is called for each entity that will be represented by
00253  * a row in a virtual table.
00254  * We construct it with an entire virtual table, which must have been
00255  * pre-allocated with the right number for rows, N. TODO FIX
00256  * 
00257  * Then we invoke it (call its operator ()) N times,  passing  in
00258  * each time a reference to the entity (of type T) we want it to "convert" to
00259  * a row.  
00260  * Each class T whose instances are to be represented in
00261  * a virtual table must have a method
00262  * \code
00263         T::vtable_collect(vtable_row_t &)
00264  * \endcode
00265  */
00266 template <class T>
00267 class vtable_func 
00268 {
00269 public: 
00270     NORET vtable_func(vtable_t &v): _curr(0), _array(v) { }
00271     NORET ~vtable_func() { }
00272 
00273     void insert_names() {
00274         T::vtable_collect_names(_array[_curr]);
00275         _array.filled_one();
00276         w_assert9(_curr < _array.size());
00277         _curr++;
00278     }
00279     /// Gather information about t and stuff it into row @ index _curr.
00280     /// It gathers by calling the T::vtable_collect(vtable_row_t &)
00281     void operator()(const T& t) // gather func
00282     {
00283         // escape the const-ness if possible
00284         T &t2 = (T &)t;
00285         t2.vtable_collect( _array[_curr] );
00286 
00287         // bump its counter
00288         _array.filled_one();
00289         w_assert9(_curr < _array.size());
00290         _curr++;
00291     }
00292     /// Un-collect the last \e n entries. 
00293     void        back_out(int n) {  
00294         _curr -= n; 
00295         _array.back_out(n);
00296     }
00297 
00298     int            realloc() {
00299         return _array.realloc();
00300     }
00301 
00302 protected:
00303     int                  _curr;
00304     vtable_t&            _array; // uses vtable_t::operator[]
00305 };
00306 
00307 
00308 /**\cond skip */
00309 class  vtable_names_init_t {
00310     size_t _size;
00311     int _argc;
00312     const char * const * _argv;
00313 public:
00314     NORET vtable_names_init_t(int argc, const char *const argv[]) : _size(0),
00315         _argc(argc), _argv(argv)
00316     {
00317         // Let _size be the larger of sizeof(double) and the
00318         // the longest string name of the sthread vtable 
00319         // attributes.  The minimum being sizeof(double) is so that
00320         // we can ultimately have these attribute be typed rather than
00321         // all strings.
00322         int mx=0;
00323         for(int i=0; i < _argc; i++) {
00324              if(_argv[i]==NULL) break;
00325              int j = strlen(_argv[i]);
00326              if(j > mx) mx = j;
00327         }
00328         _size = size_t(mx)+1; // leave room for trailing null.
00329         if(_size < sizeof(double)) _size = sizeof(double);
00330     }
00331     const char *name(int i) const {
00332         return _argv[i];
00333     }
00334     void collect_names(vtable_row_t &t) {
00335         for(int i=0; i < _argc; i++)
00336         {
00337             if(_argv[i]) t.set_string(i, _argv[i]);
00338         }
00339     }
00340     int max_size() const { return int(_size); }
00341 };
00342 /**\endcond  skip */
00343 
00344 /*<std-footer incl-file-exclusion='VTABLE_INFO_H'>  -- do not edit anything below this line -- */
00345 
00346 #endif          /*</std-footer>*/

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