extent.h

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='EXTENT_H'>
00025 
00026  $Id: extent.h,v 1.20 2010/11/08 15:06:52 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 EXTENT_H
00054 #define EXTENT_H
00055 
00056 #include "w_defines.h"
00057 
00058 /*  -- do not edit anything above this line --   </std-header>*/
00059 
00060 
00061 /********************************************************************
00062  * class extlink_t
00063  ********************************************************************/
00064 /**\brief
00065  * Persistent structure (on an extent map page) representing an extent.
00066  * \details Contains a bitmap indicating which of its pages are allocated,
00067  * next and previous pointers to link this extent into a store, and
00068  * an owner (store number, zero means not owned).  
00069  * Also contains unlogged space-utilization information (bucket map) used by
00070  * the file manager.
00071  */
00072 
00073 class extlink_t {
00074     // Grot: this became 4-byte aligned when extnum_t grew to 4 bytes
00075     Pmap_Align4        pmap;        // LOGGED. this must be first
00076 public:
00077     /**\brief Linked list next */
00078     extnum_t           next;        // 4 bytes
00079     /**\brief Linked list previous */
00080     extnum_t           prev;        // 4 bytes
00081     /**\brief Store number of containging store */
00082     snum_t             owner;       // 4 bytes
00083     /**\brief Not logged; space utilization by histograms */
00084     uint4_t            pbucketmap; // 4 bytes, unlogged !!! 
00085     // NOTE re: pbucketmap: If we change the number of pages per
00086     // extent, we have to adjust the size of pbucketmap or 
00087     // we have to adjust HBUCKETBITS in page_s.h
00088     // They are all closely tied.
00089 
00090     static int       logged_size();
00091     NORET            extlink_t();
00092     NORET            extlink_t(const extlink_t& e);
00093     extlink_t&       operator=(const extlink_t&);
00094 
00095     void             clrall();
00096     void             setall();
00097     void             setmap(const Pmap &m);
00098     void             getmap(Pmap &m) const;
00099     void             set(int i);
00100     void             clr(int i);
00101     bool             is_set(int i) const;
00102     bool             is_clr(int i) const;
00103     int              first_set(int start) const;
00104     int              first_clr(int start) const;
00105     int              last_set(int start) const;
00106     int              last_clr(int start) const;
00107     int              num_set() const;
00108     int              num_clr() const;
00109 
00110     space_bucket_t         get_page_bucket(int i)const;
00111 
00112     friend ostream& operator<<(ostream &, const extlink_t &e);
00113 };
00114 
00115 inline NORET
00116 extlink_t::extlink_t(const extlink_t& e) 
00117 : pmap(e.pmap),
00118   next(e.next),
00119   prev(e.prev),
00120   owner(e.owner),
00121   pbucketmap(e.pbucketmap)
00122 {
00123     // this is needed elsewhere -- see extlink_p::set_byte
00124     w_assert9(w_offsetof(extlink_t, pmap) == 0);
00125 }
00126 
00127 inline extlink_t& 
00128 extlink_t::operator=(const extlink_t& e)
00129 {
00130     pmap = e.pmap;
00131     prev = e.prev;
00132     next = e.next; 
00133     owner = e.owner;
00134     pbucketmap = e.pbucketmap;
00135     return *this;
00136 }
00137 inline void 
00138 extlink_t::setmap(const Pmap &m)
00139 {
00140     pmap = m;
00141 }
00142 inline void 
00143 extlink_t::getmap(Pmap &m) const
00144 {
00145     m = pmap;
00146     DBGTHRD(<<"getmap " << m);
00147 }
00148 
00149 inline void 
00150 extlink_t::clrall()
00151 {
00152     pmap.clear_all();
00153 }
00154 
00155 inline void 
00156 extlink_t::setall()
00157 {
00158     pmap.set_all();
00159 }
00160 
00161 inline void 
00162 extlink_t::set(int i)
00163 {
00164     pmap.set(i);
00165 }
00166 
00167 inline void 
00168 extlink_t::clr(int i)
00169 {
00170     pmap.clear(i);
00171 }
00172 
00173 inline bool 
00174 extlink_t::is_set(int i) const
00175 {
00176     w_assert9(i < smlevel_0::ext_sz);
00177     return pmap.is_set(i);
00178 }
00179 
00180 inline bool 
00181 extlink_t::is_clr(int i) const
00182 {
00183     return (! is_set(i));
00184 }
00185 
00186 inline int extlink_t::first_set(int start) const
00187 {
00188     return pmap.first_set(start);
00189 }
00190 
00191 inline int 
00192 extlink_t::first_clr(int start) const
00193 {
00194     return pmap.first_clear(start);
00195 }
00196 
00197 inline int 
00198 extlink_t::last_set(int start) const
00199 {
00200     return pmap.last_set(start);
00201 }
00202 
00203 inline int 
00204 extlink_t::last_clr(int start) const
00205 {
00206     return pmap.last_clear(start);
00207 }
00208 
00209 inline int 
00210 extlink_t::num_set() const
00211 {
00212     return pmap.num_set();
00213 }
00214 
00215 inline int 
00216 extlink_t::num_clr() const
00217 {
00218     return pmap.num_clear();
00219 }
00220 
00221 /**\cond skip */
00222 
00223 /********************************************************************
00224 * class extlink_p
00225 ********************************************************************/
00226 /**\brief Extent map page that contains extent links (extlink_t).
00227  */
00228 
00229 class extlink_p : public page_p {
00230 public:
00231     MAKEPAGE(extlink_p, page_p, 2); // make extent links a little hotter than
00232     // others
00233 
00234     // max # extent links on a page
00235     enum { max = data_sz / sizeof(extlink_t) };
00236 
00237     const extlink_t& get(slotid_t idx);
00238     void             put(slotid_t idx, const extlink_t& e);
00239     w_rc_t           set_byte(slotid_t idx, u_char bits, 
00240                           enum page_p::logical_operation);
00241     w_rc_t           set_bytes(slotid_t idx,
00242                           smsize_t    offset,
00243                           smsize_t     count,
00244                           const uint1_t* bits, 
00245                           enum page_p::logical_operation);
00246     void             clr_pmap_bit(slotid_t idx, int bit); 
00247     static bool      on_same_page(extnum_t e1, extnum_t e2);
00248 
00249 private:
00250     extlink_t&             item(int i);
00251 
00252     struct layout_t {
00253     extlink_t             item[max];
00254     };
00255 
00256     // disable
00257     friend class page_link_log;        // just to keep g++ happy
00258     friend class extlink_i;        // needs access to item
00259 };
00260 
00261 inline bool
00262 extlink_p::on_same_page(extnum_t e1, extnum_t e2)
00263 {
00264     shpid_t p1 = e1 / (extlink_p::max);
00265     shpid_t p2 = e2 / (extlink_p::max);
00266     return (p1 == p2);
00267 }
00268 
00269 inline extlink_t&
00270 extlink_p::item(int i)
00271 {
00272     w_assert9(i < max);
00273     return ((layout_t*)tuple_addr(0))->item[i];
00274 }
00275 
00276 
00277 inline const extlink_t&
00278 extlink_p::get(slotid_t idx)
00279 {
00280     return item(idx);
00281 }
00282 
00283 inline int
00284 extlink_t::logged_size() {
00285     //
00286     // NOTE: watch the order of attributes so that we don't log the
00287     // pbucketmap!!!
00288     //
00289     // return __offsetof(extlink_t, pbucketmap);
00290     return w_offsetof(extlink_t, pbucketmap);
00291 }
00292 
00293 inline void
00294 extlink_p::put(slotid_t idx, const extlink_t& e)
00295 {
00296     DBG(<<"extlink_p::put(" <<  idx << " owner=" <<
00297     e.owner << ", " << e.next << ")");
00298     const vec_t    extent_vec_tmp(&e, extlink_t::logged_size());
00299     W_COERCE(overwrite(0, idx * sizeof(extlink_t), extent_vec_tmp));
00300 }
00301 
00302 /**\endcond skip */
00303 
00304 
00305 /**\brief Persistent structure representing the head of a store's extent list.
00306  * \details These structures sit on stnode_p pages and point to the
00307  * start of the extent list.
00308  * The stnode_t structures are indexed by store number.
00309  */
00310 struct stnode_t {
00311     /**\brief First extent of the store */
00312     extnum_t                 head; // 4 bytes
00313     /**\brief Fill factor (not used) */
00314     w_base_t::uint2_t        eff;
00315     /**\brief store flags  */
00316     w_base_t::uint2_t        flags;
00317     /**\brief non-zero if deleting or deleted */
00318     w_base_t::uint2_t        deleting; // see store_operation
00319     /**\brief alignment */
00320     fill2                    filler; // align to 4 bytes
00321 };
00322 
00323 /**\cond skip */
00324 
00325 /**\brief Extent map page that contains store nodes (stnode_t).
00326  * \details These are the pages that contain the starting points of 
00327  * a store's list of extents.
00328  */
00329 class stnode_p : public page_p {
00330     public:
00331     MAKEPAGE(stnode_p, page_p, 1);
00332 
00333     // max # store nodes on a page
00334     enum { max = data_sz / sizeof(stnode_t) };
00335 
00336     const stnode_t&       get(slotid_t idx);
00337     rc_t                  put(slotid_t idx, const stnode_t& e);
00338 
00339     private:
00340     stnode_t&             item(snum_t i);
00341     struct layout_t {
00342         stnode_t          item[max];
00343     };
00344 
00345     friend class page_link_log;        // just to keep g++ happy
00346     friend class stnode_i;        // needs access to item
00347 };    
00348 
00349 inline stnode_t&
00350 stnode_p::item(snum_t i)
00351 {
00352     w_assert9(i < max);
00353     return ((layout_t*)tuple_addr(0))->item[i];
00354 }
00355 
00356 inline const stnode_t&
00357 stnode_p::get(slotid_t idx)
00358 {
00359     return item(idx);
00360 }
00361 
00362 inline w_rc_t 
00363 stnode_p::put(slotid_t idx, const stnode_t& e)
00364 {
00365     const vec_t stnode_vec_tmp(&e, sizeof(e));
00366     W_DO(overwrite(0, idx * sizeof(stnode_t), stnode_vec_tmp));
00367     return RCOK;
00368 }
00369 /**\endcond skip */
00370 
00371 /**\brief Iterator over a list of extents.
00372  *\details  Constructor latches the given extent-map page.
00373  * Get() methods unlatch and latch extent-map pages as needed to return
00374  * a reference to the needed extlink_t.
00375  */
00376 class extlink_i {
00377 public:
00378     NORET            extlink_i(const lpid_t& root)
00379                     : 
00380                     _root(root) {
00381                         // The extent maps start on page 1. 
00382                         w_assert1(root.page >= 1);
00383                     }
00384             
00385     bool             on_same_root(extnum_t idx);
00386     
00387     lpid_t           get_pid(extnum_t idx) const;
00388     rc_t             get(extnum_t idx, const extlink_t* &);
00389     rc_t             get(extnum_t idx, extlink_t* &);
00390     rc_t             get_copy(extnum_t idx, extlink_t &);
00391     rc_t             put(extnum_t idx, const extlink_t&);
00392     bool             on_same_page(extnum_t ext1, extnum_t ext2) const ;
00393 
00394     rc_t             update_histo(extnum_t ext,     
00395                         int    offset,
00396                         space_bucket_t bucket);
00397     rc_t             fix_EX(extnum_t idx);
00398     void             unfix();
00399     rc_t             set_pmap_bits(snum_t snum, extnum_t idx, const Pmap &bits);
00400     rc_t             clr_pmap_bit(snum_t snum, extnum_t idx, int bit);
00401 
00402     rc_t             clr_pmap_bits(snum_t snum, extnum_t idx, const Pmap &bits);
00403     rc_t             set_next(extnum_t ext, extnum_t new_next, bool log_it = true);
00404     const extlink_p& page() const { return _page; } // for logging purposes
00405 
00406 private:
00407     extid_t             _id;
00408     lpid_t              _root;
00409     extlink_p           _page;
00410 
00411     inline w_rc_t       update_pmap(extnum_t idx,
00412                             const Pmap &pmap,
00413                             page_p::logical_operation how);
00414     inline w_rc_t       update_pbucketmap(extnum_t idx,
00415                             uint4_t map,
00416                             page_p::logical_operation how);
00417 };
00418 
00419 
00420 /*********************************************************************
00421  *
00422  *  class stnode_i
00423  *
00424  *  Iterator over store node area of volume.
00425  *
00426  *********************************************************************/
00427 /**\brief Iterator over store nodes.
00428  * \details  Constructor latches the given store node page; the get
00429  * methods unlatch and latch pages as necessary to return a reference to
00430  * a stnode_t for the given store number.
00431  * The store_operation method effects operations on entire stores, such
00432  * as deletion and changing logging attributes.
00433  */
00434 class stnode_i: private smlevel_0 {
00435 public:
00436     NORET               stnode_i(const lpid_t& root) : _root(root) {
00437                              // store nodes are after extent links and
00438                              // those start on page 1.
00439                              w_assert1(root.page >= 1);
00440                         };
00441     w_rc_t              get(snum_t idx, stnode_t &stnode);
00442     w_rc_t              get(snum_t idx, const stnode_t *&stnode);
00443     w_rc_t              put(snum_t idx, const stnode_t& stnode);      
00444     w_rc_t              store_operation(const store_operation_param & op);
00445 private:
00446     lpid_t              _root;
00447     stnode_p            _page;
00448 };
00449 
00450 
00451 /*<std-footer incl-file-exclusion='EXTENT_H'>  -- do not edit anything below this line -- */
00452 
00453 #endif          /*</std-footer>*/

Generated on Mon Nov 8 11:12:38 2010 for Shore Storage Manager by  doxygen 1.4.7