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='SORT_H'> 00025 00026 $Id: sort.h,v 1.30 2010/05/26 01:20:45 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 SORT_H 00054 #define SORT_H 00055 00056 #include "w_defines.h" 00057 00058 /* -- do not edit anything above this line -- </std-header>*/ 00059 00060 // NOTE: you cannot run all the smsh scripts w/o INSTRUMENT_SORT 00061 // turned on. 00062 // We define a method that will allow us to find out 00063 // if INSTRUMENT_SORT is defined; this way the smsh scripts can 00064 // avoid croaking by running things that rely on this being defined. 00065 // It can't be inlined. It's called only by smsh. 00066 #undef INSTRUMENT_SORT 00067 extern "C" bool sort_is_instrumentd(); // sort.cpp 00068 00069 #include <lexify.h> 00070 #include <sort_s.h> 00071 00072 #ifdef __GNUG__ 00073 #pragma interface 00074 #endif 00075 00076 00077 struct sort_desc_t; 00078 class run_scan_t; 00079 00080 /**\addtogroup SSMSORT 00081 * 00082 * The storage manager provides two tools for sorting, 00083 * the class sort_stream_i and the method ss_m::sort_file. 00084 * 00085 * The class sort_stream_i implements 00086 * sorting of <key,elem> pairs with a simple interface. 00087 * It is an adjunct of bulk-loading indexes. One inserts 00088 * <key,elem> pairs into the stream, and then iterates over 00089 * the stream with its sort_stream_i::get_next method to 00090 * retrieve the pairs in order. The sort_stream_i uses temporary 00091 * files as necessary to store the data stream. 00092 * 00093 * The storage manager function ss_m::sort_file implements 00094 * a polyphase merge-sort. 00095 * 00096 * Both methods offer a variety of run-time options. 00097 * The options are specified with different APIs: 00098 * - The sort_stream_i uses \ref ssm_sort::key_info_t to describe keys 00099 * and \ref ssm_sort::sort_parm_t to describe behavior options. 00100 * - The ss_m::sort_file uses \ref ssm_sort::sort_keys_t to describe keys 00101 * and behavior options. 00102 * 00103 * \note Historical note: The original implementation of the sort_file 00104 * method used the same APIs (for specifying sort behavior and describing 00105 * keys) as sort_stream_i, but that implementation for sort_file was 00106 * inadequate for the needs of the projects using the storage manager 00107 * at the time (viz user-defined key types, 00108 * marshalling and unmarshalling, etc.). 00109 * The new implementation is more general, but the sort_stream_i 00110 * has not been rewritten to use the new options- and key- descriptor classes. 00111 * 00112 * See sort_stream_i for details and \ref sort_stream.cpp for an example 00113 * of its use. 00114 * The balance of this section describes the use of ss_m::sort_file and 00115 * its application to bulk-loading. 00116 * 00117 * Sort_file supports: 00118 * - sorting on one or more keys 00119 * - key types may be 00120 * - fundamental (predefined) or user-defined 00121 * - derived or embedded 00122 * - records being sorted may require marshalling when read from disk 00123 * to memory and unmarshalling when written back to disk 00124 * - the result of the sort can be 00125 * - a sorted copy of the input file 00126 * - a file ready for bulk-loading an index to the original file 00127 * 00128 * For all this generality, the sort uses \ref SORTCALLBACK "callbacks" 00129 * to the server for such things as 00130 * - key comparisons 00131 * - key derivation 00132 * - object marshalling and unmarshalling 00133 * - producing the final form of keys for output, when the sort key 00134 * is not the key to be loaded into the index (for example consider R-trees: 00135 * a polygon is the index key, but the records are sorted on 00136 * the polygon's Hilbert value) 00137 * 00138 * \section SORTRUN Runs 00139 * 00140 * The sort takes as many runs as required to read and sort the 00141 * entire input file, while limiting the amount of memory used. 00142 * The run size is given as an argument to sort_file. 00143 * 00144 * The sort uses temporary files when the input file contains more records 00145 * than can fit in one run (determined by the run size). 00146 * These temporary files may be spread across 00147 * multiple volumes, which is useful if the 00148 * volumes reside on different spindles. 00149 * 00150 * If the entire input file fits into the buffer pool pages of one run, 00151 * much of the complexity of the sort is eliminated, because the copying 00152 * of objects and metadata to scratch files is unnecessary, but for the 00153 * general (polyphase) case, behavioral options describe how the 00154 * writing to scratch files is handled, and these options depend on 00155 * the kind of output desired (see \ref SORTOUTPUT). 00156 * 00157 * 00158 * \section SORTCALLBACK Callbacks 00159 * 00160 * The sort has to call back to the server for 00161 * 00162 * - marshalling a record (ssm_sort::MOF): 00163 * When a record is first encountered in the 00164 * input file, it may be marshalled to produce an in-memory version of the 00165 * entire object (presumably byte-swapped, pointer-swizzled, etc.). This 00166 * copy of the record (in the form of an object_t, 00167 * which is a handle for the record or in-memory representation) 00168 * is passed to the next callback function (ssm_sort::CSKF). 00169 * If a marshal function is supplied it is called at least once on 00170 * every record. 00171 * 00172 * - creating or locating a key (ssm_sort::CSKF): 00173 * This callback locates or derives a key for the object. 00174 * Its result is an skey_t, which is a handle for the derived or 00175 * embedded key. This function might have to allocate heap space for 00176 * the derived keys, in which case sort_file has to deallocate such 00177 * space, so this callback takes a factory_t for heap management. 00178 * 00179 * - comparing two keys (ssm_sort::CF): The server provides this function to compare 00180 * two byte streams of some given length each. 00181 * 00182 * - unmarshalling an object (ssm_sort::UMOF): 00183 * Before the object is written to the output 00184 * file after the last run, it may be unmarshalled to produce an on-disk 00185 * version of the object. The unmarshal function need not be called 00186 * on every record. When the output is to be a bulk-loadable file 00187 * for indexes, unmarshal is not needed. When the output is a copy 00188 * of the input file, it is sometimes needed: 00189 * - Case 1, Large object, not deep copy (large-object store will be 00190 * transferred to the output file so carrying the object has no 00191 * effect here) : No need to unmarshal; 00192 * the large object 00193 * was marshaled in the first place only for the purpose of locating 00194 * or deriving a sort key. 00195 * - Case 2, Large object with deep copy or small object 00196 * - Case 2a, Carrying object : Call unmarshal function (UMOF), write 00197 * its result to the output file. 00198 * - Case 2b, Not carrying object : No need to unmarshal; pin the original 00199 * object and copy it to the output file. 00200 * 00201 * \section SORTOUTPUT Behavior and Results of Sort 00202 * 00203 * Behaviors that can be controlled are the following; these 00204 * behaviors are determined by the contents of the sort_keys_t 00205 * argument to sort_file: 00206 * - The kind of output the sort produces, which can be 00207 * - a sorted copy of the input file (ssm_sort::sort_keys_t::set_for_file), or 00208 * - a file suitable for bulk-loading an index (sort_keys_t::set_for_index), 00209 * the format of which is: 00210 * - header contains key in lexicographic format 00211 * - body contains element 00212 * - whether the original file is to be retained or deleted by the sort 00213 * (sort_keys_t::set_keep_orig), with variations on these choices 00214 * - how the key is to be located or derived (sort_keys_t::set_sortkey_fixed, 00215 sort_keys_t::set_sortkey_derived, and other attributes of 00216 sort_keys_t) 00217 * - whether the sort is to be stable (sort_keys_t::set_stable) 00218 * - whether the sort is ascending or descending (sort_keys_t::set_ascending) 00219 * - whether the sort is to eliminate duplicate nulls (sort_keys_t::set_null_unique) 00220 * - whether the sort is to eliminate all duplicates (sort_keys_t::set_unique) 00221 * - whether the sort is to call user-defined marshal and unmarshal 00222 * functions to get/put the resulting data from/to disk 00223 * 00224 * Many behavioral options depend on other options, as discussed below. 00225 * 00226 * \subsection SORTOUTPUTFILE Result is Sorted Copy of Input File 00227 * 00228 * Use ssm_sort::sort_keys_t::set_for_file to create a sorted copy of the input file. 00229 * 00230 * Applicable key description data: 00231 * - number of keys : >= 1 00232 * - key access (for each key): 00233 * - in header or body : a key or its source data 00234 * may reside in either header or body of the original record 00235 * - at fixed location (ssm_sort::sort_keys_t::set_sortkey_fixed): 00236 * In all records this key is at the same 00237 * location in the record (header or body). User may not provide 00238 * a ssm_sort::CSKF for the key (it will not be used, so it is rejected). 00239 * - aligned : By indicating that a key is adequately aligned in 00240 * the original record for its key-comparison function (ssm_sort::CF) to 00241 * operate on it, the sort function can avoid the work 00242 * of copying to an aligned and contiguous buffer before calling the 00243 * comparison function (ssm_sort::CF). (The sort function determines if the 00244 * key resides entirely on one page; the user does not have to 00245 * indicate this.) If the key is in lexicographic format in the 00246 * original record (after marshalling, if marshalling is used), 00247 * alignment is immaterial. 00248 * - derived (ssm_sort::sort_keys_t::set_sortkey_derived) : User must provide a ssm_sort::CSKF callback function to derive the 00249 * key. The source data may be in 00250 * the header or body of the record. The ssm_sort::CSKF "knows" the 00251 * key's offset from the header or body, or receives that 00252 * information from an argument (key_cookie_t) passed to the 00253 * callback function. 00254 * - lexicographic format: ssm_sort::sort_keys_t::is_lexico indicates that 00255 * the key is in \ref LEXICOFORMAT "lexigographic format" 00256 * in the original record, so it can be compared in 00257 * segments (if, say, it is spread 00258 * across page boundaries) and its alignment is immaterial. 00259 * 00260 * Applicable sort behavior options: 00261 * - marshalling : A callback marshal function (MOF) will be called 00262 * to reformat records from which keys are created. This will 00263 * be done before the ssm_sort::CSKF is called. 00264 * - ascending : sort in ascending or descending order 00265 * - stable : optionally ensure stable sort 00266 * - unique : eliminate records with duplicate keys 00267 * - null_unique : eliminate records with duplicate null keys 00268 * - keep_orig : optionally delete the original file 00269 * - carry_obj : optionally duplicate the entire object in the runs 00270 * - deep_copy : optionally copy the large objects 00271 * 00272 * \subsection SORTOUTPUTINDEX Result is Input to Bulk-Load 00273 * 00274 * Applicable key description data: 00275 * - number of sort keys : only one-key sort is supported 00276 * - index key derivation: the index key may differ from the sort key, 00277 * in which case the user provides a callback (ssm_sort::CSKF) function 00278 * to produce the index key. It must be produced in 00279 * \ref LEXICOFORMAT "lexigographic format". 00280 * - sort key access: 00281 * - in header or body : a key or its source data 00282 * may reside in either header or body of the original record 00283 * - at fixed location (ssm_sort::sort_keys_t::set_sortkey_fixed): 00284 * In all records the key is at the same 00285 * location in the record (header or body). User may not provide 00286 * a ssm_sort::CSKF for the key (it will not be used, so it is rejected). 00287 * - aligned : By indicating that a key is adequately aligned in 00288 * the original record for its key-comparison function (ssm_sort::CF) to 00289 * operate on it, the sort function can avoid the work 00290 * of copying to an aligned and contiguous buffer before calling the 00291 * comparison function (ssm_sort::CF). (The sort function determines if the 00292 * key resides entirely on one page; the user does not have to 00293 * indicate this.) If the key is in lexicographic format in the 00294 * original record (after marshalling, if marshalling is used), 00295 * alignment is immaterial. 00296 * - derived (ssm_sort::sort_keys_t::set_sortkey_derived) : User must provide a ssm_sort::CSKF callback function to derive the 00297 * key. The source data may be in 00298 * the header or body of the record. The ssm_sort::CSKF "knows" the 00299 * key's offset from the header or body, or receives that 00300 * information from an argument (key_cookie_t) passed to the 00301 * callback function. 00302 * - lexicographic format: if 00303 * the key is in \ref LEXICOFORMAT "lexigographic format" 00304 * in the original record, it can be compared in 00305 * segments (if, say, it is spread 00306 * across page boundaries) and its alignment is immaterial. 00307 * \b NOTE If it is \b not in 00308 * lexicographic format, a ssm_sort::CSKF callback 00309 * must put it in lexicographic format for the purpose of 00310 * loading into a B+-Tree (should the sort key be used as the 00311 * index key), so the sort key must therefore be 00312 * derived in this case. 00313 * 00314 * Applicable sort behavior options: 00315 * - marshalling : use callback marshal function (MOF) to reformat 00316 * records from which keys are created 00317 * - ascending : sort in ascending or descending order 00318 * - stable : may not be set because it might violate RID order in the 00319 * event of duplicates (the elements for the pairs with the same 00320 * key are sorted on the element in the B+-Tree). If stability 00321 * is needed, the key should be derived from two keys, or should 00322 * be a concatenation of multiple keys (either suitable colocated 00323 in the object or derived) that would ensure the stability. 00324 * - unique : eliminate records with duplicate keys 00325 * - null_unique : eliminate records with duplicate null keys 00326 * - keep_orig : n/a 00327 * - carry_obj : n/a 00328 * - deep_copy : n/a 00329 * 00330 * \section SORTKEYS Keys 00331 * 00332 * Sort keys may be located in the input records or derived from 00333 * the input records. 00334 * Index keys that are different from the sort key are derived. 00335 * 00336 * When the output is to be a sorted copy of the input file, the 00337 * keys do not appear in the output file except inasmuch as they 00338 * are embedded in the original input records. 00339 * The sort keys in this case may be derived from the record contents, 00340 * in which case they truly do not appear in the output. 00341 * Multiple keys may be used for the sort, and they may be a combination 00342 * of fixed-location keys and derived keys. See \ref SORTOUTPUTFILE. 00343 * 00344 * When the output is to be a bulk-loadable file, its records takes the form 00345 * header = key, body = element, and sort-file gives the caller no control 00346 * over the elements' contents: they are the record-IDs of the original 00347 * records. If something other than the record-ID is desired for bulk-loading 00348 * an index, the output can be made to be a sorted copy of the 00349 * original file, with a suitable unmarshal (UMOF) applied. 00350 * 00351 * Only one sort key can be used in this case, but the index key can differ 00352 * differ from the sort key. See \ref SORTOUTPUTINDEX. 00353 * 00354 */ 00355 00356 // 00357 // chunk list for large object buffer 00358 // 00359 /**\cond skip */ 00360 struct s_chunk { 00361 00362 char* data; 00363 s_chunk* next; 00364 00365 NORET s_chunk() { data = 0; next = 0; }; 00366 NORET s_chunk(w_base_t::uint4_t size, s_chunk* tail) { 00367 data = new char[size]; 00368 next = tail; 00369 }; 00370 NORET ~s_chunk() { delete [] data; }; 00371 }; 00372 00373 class chunk_mgr_t { 00374 00375 private: 00376 s_chunk* head; 00377 00378 void _free_all() { 00379 s_chunk* curr; 00380 while (head) { 00381 curr = head; 00382 head = head->next; 00383 delete curr; 00384 } 00385 }; 00386 00387 public: 00388 00389 NORET chunk_mgr_t() { head = 0; }; 00390 NORET ~chunk_mgr_t() { _free_all(); }; 00391 00392 void reset() { _free_all(); head = 0; }; 00393 00394 void* alloc(w_base_t::uint4_t size) { 00395 s_chunk* curr = new s_chunk(size, head); 00396 head = curr; 00397 return (void*) curr->data; 00398 }; 00399 }; 00400 /**\endcond skip */ 00401 00402 # define PROTOTYPE(_parms) _parms 00403 00404 #ifndef PFCDEFINED 00405 00406 #define PFCDEFINED 00407 typedef int (*PFC) PROTOTYPE((w_base_t::uint4_t kLen1, 00408 const void* kval1, w_base_t::uint4_t kLen2, const void* kval2)); 00409 00410 #endif 00411 00412 /**\class sort_stream_i 00413 * \brief Sorting tool. 00414 * \details 00415 * \ingroup SSMSORT 00416 * Used for bulk-loading indexes but may be used independently. 00417 * After creating an instance of sort_stream_i, you can keep putting 00418 * <key,element> pairs into the stream, which will save the 00419 * records in a temporary persistent store, sort them, and then 00420 * return them in sorted order like an iterator over the temporary 00421 * store. The temporary store is destroyed upon completion (destruction). 00422 * 00423 * Before you can begin inserting pairs into the stream, you must initialize the 00424 * stream with information about the key on which to sort (where it is to 00425 * be found, what its length and type are, etc.). 00426 * 00427 * See example \ref sort_stream.cpp 00428 */ 00429 class sort_stream_i : public smlevel_top, public xct_dependent_t 00430 { 00431 typedef ssm_sort::key_info_t key_info_t; 00432 typedef ssm_sort::sort_parm_t sort_parm_t; 00433 typedef ssm_sort::sort_keys_t sort_keys_t; 00434 friend class ss_m; 00435 00436 public: 00437 00438 /**\brief Constructor. If you use this constructor you must use init(). 00439 */ 00440 NORET sort_stream_i(); 00441 /**\brief Constructor that calls init(). 00442 * 00443 * @param[in] k See key_info_t, which describes the keys used to 00444 * sort the data to be inserted. 00445 * @param[in] s See ssm_sort::sort_parm_t, which describes behavior of the sort. 00446 * @param[in] est_rec_sz Estimated record size; allows the sort to 00447 * estimate how many items will fit in a page. 00448 */ 00449 NORET sort_stream_i(const key_info_t& k, 00450 const sort_parm_t& s, uint est_rec_sz=0); 00451 00452 NORET ~sort_stream_i(); 00453 00454 /**\brief Return a key-comparison function for the given 00455 * pre-defined key type. 00456 * @param[in] type See key_info_t. 00457 * @param[in] up If true, the function returns will sort in 00458 * ascending order, if false, in descending order. 00459 */ 00460 static PFC get_cmp_func(key_info_t::key_type_t type, bool up); 00461 00462 /**\brief Initialize the stream with necessary metadata. 00463 * 00464 * @param[in] k See key_info_t, which describes the keys used to 00465 * sort the data to be inserted. 00466 * @param[in] s See ssm_sort::sort_parm_t, which describes behavior of the sort. 00467 * @param[in] est_rec_sz Estimated record size; allows the sort to 00468 * estimate how many items will fit in a page. 00469 */ 00470 void init(const key_info_t& k, const sort_parm_t& s, uint est_rec_sz=0); 00471 00472 /// Release resources, render unusable. (Called by destructor if apropos.) 00473 void finish(); 00474 00475 /**\brief Insert a key,elem pair into the stream. 00476 * @param[in] key Key of key,elem pair. 00477 * @param[in] elem Element of key,elem pair. 00478 * 00479 * \note Must be invoked in a transaction, although this is not 00480 * enforced gracefully. 00481 */ 00482 rc_t put(const cvec_t& key, const cvec_t& elem); 00483 00484 /**\brief Fetch the next key,elem pair from the stream (in sorted order). 00485 * @param[out] key Key of key,elem pair. 00486 * @param[out] elem Element of key,elem pair. 00487 * @param[out] eof Set to true if no more pairs in the stream. 00488 * 00489 * \note Must be invoked in a transaction, although this is not 00490 * enforced gracefully. 00491 */ 00492 rc_t get_next(vec_t& key, vec_t& elem, bool& eof) ; 00493 00494 /// Returns true until the first put() call. 00495 bool is_empty() const { return empty; } 00496 00497 /// Sort happens at first get_next call, returns false until then. 00498 bool is_sorted() const { return sorted; } 00499 00500 private: 00501 void set_file_sort() { _file_sort = true; _once = false; } 00502 void set_file_sort_once(sm_store_property_t prop) 00503 { 00504 _file_sort = true; _once = true; 00505 _property = prop; 00506 } 00507 rc_t file_put(const cvec_t& key, const void* rec, uint rlen, 00508 uint hlen, const rectag_t* tag); 00509 00510 rc_t file_get_next(vec_t& key, vec_t& elem, 00511 w_base_t::uint4_t& blen, bool& eof) ; 00512 00513 rc_t flush_run(); // sort and flush one run 00514 00515 rc_t flush_one_rec(const record_t *rec, rid_t& rid, 00516 const stid_t& out_fid, file_p& last_page, 00517 bool to_final_file); 00518 00519 rc_t remove_duplicates(); // remove duplicates for unique sort 00520 rc_t merge(bool skip_last_pass); 00521 00522 void xct_state_changed( xct_state_t old_state, xct_state_t new_state); 00523 00524 key_info_t ki; // key info 00525 sort_parm_t sp; // sort parameters 00526 sort_desc_t* sd; // sort descriptor 00527 00528 bool sorted; // sorted flag 00529 bool eof; // eof flag 00530 bool empty; // empty flag 00531 const record_t* old_rec; // used for sort unique 00532 00533 bool _file_sort; // true if sorting a file 00534 00535 int2_t* heap; // heap array 00536 int heap_size; // heap size 00537 run_scan_t* sc; // scan descriptor array 00538 w_base_t::uint4_t num_runs; // # of runs for each merge 00539 int r; // run index 00540 00541 chunk_mgr_t buf_space; // in-memory storage 00542 00543 // below vars used for speeding up sort if whole file fits in memory 00544 bool _once; // one pass write to result file 00545 sm_store_property_t _property; // property for the result file 00546 }; 00547 00548 class file_p; 00549 00550 // 00551 // run scans 00552 // 00553 /**\cond skip */ 00554 class run_scan_t { 00555 typedef ssm_sort::key_info_t key_info_t; 00556 typedef ssm_sort::sort_parm_t sort_parm_t; 00557 00558 lpid_t pid; // current page id 00559 file_p* fp; // page buffer (at most fix two pages for unique sort) 00560 int2_t i; // toggle between two pages 00561 int2_t slot; // slot for current record 00562 record_t* cur_rec; // pointer to current record 00563 bool eof; // end of run 00564 key_info_t kinfo; // key description (location, len, type) 00565 int2_t toggle_base; // default = 1, unique sort = 2 00566 bool single; // only one page 00567 bool _unique; // unique sort 00568 00569 public: 00570 PFC cmp; 00571 00572 NORET run_scan_t(); 00573 NORET ~run_scan_t(); 00574 00575 rc_t init(rid_t& begin, PFC c, const key_info_t& k, bool unique); 00576 rc_t current(const record_t*& rec); 00577 rc_t next(bool& eof); 00578 00579 bool is_eof() { return eof; } 00580 00581 friend bool operator>(run_scan_t& s1, run_scan_t& s2); 00582 friend bool operator<(run_scan_t& s1, run_scan_t& s2); 00583 00584 const lpid_t& page() const { return pid; } 00585 }; 00586 /**\endcond skip */ 00587 00588 00589 /*<std-footer incl-file-exclusion='SORT_H'> -- do not edit anything below this line -- */ 00590 00591 #endif /*</std-footer>*/