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.31 2010/08/23 14:28:18 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 (subject to certain limitations - see \ref SORTKEYS ) 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 * \note Keys that are located in the input records may not span pages. 00336 * The complexity to do key-comparisons (in parts, across pages) is 00337 * not implemented. To get around this, you may 00338 * put the keys in the record headers 00339 * or use marshalling to collect the keys from the records. 00340 * 00341 * When the output is to be a sorted copy of the input file, the 00342 * keys do not appear in the output file except inasmuch as they 00343 * are embedded in the original input records. 00344 * The sort keys in this case may be derived from the record contents, 00345 * in which case they truly do not appear in the output. 00346 * Multiple keys may be used for the sort, and they may be a combination 00347 * of fixed-location keys and derived keys. See \ref SORTOUTPUTFILE. 00348 * 00349 * When the output is to be a bulk-loadable file, its records takes the form 00350 * header = key, body = element, and sort-file gives the caller no control 00351 * over the elements' contents: they are the record-IDs of the original 00352 * records. If something other than the record-ID is desired for bulk-loading 00353 * an index, the output can be made to be a sorted copy of the 00354 * original file, with a suitable unmarshal (UMOF) applied. 00355 * 00356 * Only one sort key can be used in this case, but the index key can differ 00357 * differ from the sort key. See \ref SORTOUTPUTINDEX. 00358 * 00359 */ 00360 00361 // 00362 // chunk list for large object buffer 00363 // 00364 /**\cond skip */ 00365 struct s_chunk { 00366 00367 char* data; 00368 s_chunk* next; 00369 00370 NORET s_chunk() { data = 0; next = 0; }; 00371 NORET s_chunk(w_base_t::uint4_t size, s_chunk* tail) { 00372 data = new char[size]; 00373 next = tail; 00374 }; 00375 NORET ~s_chunk() { delete [] data; }; 00376 }; 00377 00378 class chunk_mgr_t { 00379 00380 private: 00381 s_chunk* head; 00382 00383 void _free_all() { 00384 s_chunk* curr; 00385 while (head) { 00386 curr = head; 00387 head = head->next; 00388 delete curr; 00389 } 00390 }; 00391 00392 public: 00393 00394 NORET chunk_mgr_t() { head = 0; }; 00395 NORET ~chunk_mgr_t() { _free_all(); }; 00396 00397 void reset() { _free_all(); head = 0; }; 00398 00399 void* alloc(w_base_t::uint4_t size) { 00400 s_chunk* curr = new s_chunk(size, head); 00401 head = curr; 00402 return (void*) curr->data; 00403 }; 00404 }; 00405 /**\endcond skip */ 00406 00407 # define PROTOTYPE(_parms) _parms 00408 00409 #ifndef PFCDEFINED 00410 00411 #define PFCDEFINED 00412 typedef int (*PFC) PROTOTYPE((w_base_t::uint4_t kLen1, 00413 const void* kval1, w_base_t::uint4_t kLen2, const void* kval2)); 00414 00415 #endif 00416 00417 /**\class sort_stream_i 00418 * \brief Sorting tool. 00419 * \details 00420 * \ingroup SSMSORT 00421 * Used for bulk-loading indexes but may be used independently. 00422 * After creating an instance of sort_stream_i, you can keep putting 00423 * <key,element> pairs into the stream, which will save the 00424 * records in a temporary persistent store, sort them, and then 00425 * return them in sorted order like an iterator over the temporary 00426 * store. The temporary store is destroyed upon completion (destruction). 00427 * 00428 * Before you can begin inserting pairs into the stream, you must initialize the 00429 * stream with information about the key on which to sort (where it is to 00430 * be found, what its length and type are, etc.). 00431 * 00432 * See example \ref sort_stream.cpp 00433 */ 00434 class sort_stream_i : public smlevel_top, public xct_dependent_t 00435 { 00436 typedef ssm_sort::key_info_t key_info_t; 00437 typedef ssm_sort::sort_parm_t sort_parm_t; 00438 typedef ssm_sort::sort_keys_t sort_keys_t; 00439 friend class ss_m; 00440 00441 public: 00442 00443 /**\brief Constructor. If you use this constructor you must use init(). 00444 */ 00445 NORET sort_stream_i(); 00446 /**\brief Constructor that calls init(). 00447 * 00448 * @param[in] k See key_info_t, which describes the keys used to 00449 * sort the data to be inserted. 00450 * @param[in] s See ssm_sort::sort_parm_t, which describes behavior of the sort. 00451 * @param[in] est_rec_sz Estimated record size; allows the sort to 00452 * estimate how many items will fit in a page. 00453 */ 00454 NORET sort_stream_i(const key_info_t& k, 00455 const sort_parm_t& s, uint est_rec_sz=0); 00456 00457 NORET ~sort_stream_i(); 00458 00459 /**\brief Return a key-comparison function for the given 00460 * pre-defined key type. 00461 * @param[in] type See key_info_t. 00462 * @param[in] up If true, the function returns will sort in 00463 * ascending order, if false, in descending order. 00464 */ 00465 static PFC get_cmp_func(key_info_t::key_type_t type, bool up); 00466 00467 /**\brief Initialize the stream with necessary metadata. 00468 * 00469 * @param[in] k See key_info_t, which describes the keys used to 00470 * sort the data to be inserted. 00471 * @param[in] s See ssm_sort::sort_parm_t, which describes behavior of the sort. 00472 * @param[in] est_rec_sz Estimated record size; allows the sort to 00473 * estimate how many items will fit in a page. 00474 */ 00475 void init(const key_info_t& k, const sort_parm_t& s, uint est_rec_sz=0); 00476 00477 /// Release resources, render unusable. (Called by destructor if apropos.) 00478 void finish(); 00479 00480 /**\brief Insert a key,elem pair into the stream. 00481 * @param[in] key Key of key,elem pair. 00482 * @param[in] elem Element of key,elem pair. 00483 * 00484 * \note Must be invoked in a transaction, although this is not 00485 * enforced gracefully. 00486 */ 00487 rc_t put(const cvec_t& key, const cvec_t& elem); 00488 00489 /**\brief Fetch the next key,elem pair from the stream (in sorted order). 00490 * @param[out] key Key of key,elem pair. 00491 * @param[out] elem Element of key,elem pair. 00492 * @param[out] eof Set to true if no more pairs in the stream. 00493 * 00494 * \note Must be invoked in a transaction, although this is not 00495 * enforced gracefully. 00496 */ 00497 rc_t get_next(vec_t& key, vec_t& elem, bool& eof) ; 00498 00499 /// Returns true until the first put() call. 00500 bool is_empty() const { return empty; } 00501 00502 /// Sort happens at first get_next call, returns false until then. 00503 bool is_sorted() const { return sorted; } 00504 00505 private: 00506 void set_file_sort() { _file_sort = true; _once = false; } 00507 void set_file_sort_once(sm_store_property_t prop) 00508 { 00509 _file_sort = true; _once = true; 00510 _property = prop; 00511 } 00512 rc_t file_put(const cvec_t& key, const void* rec, uint rlen, 00513 uint hlen, const rectag_t* tag); 00514 00515 rc_t file_get_next(vec_t& key, vec_t& elem, 00516 w_base_t::uint4_t& blen, bool& eof) ; 00517 00518 rc_t flush_run(); // sort and flush one run 00519 00520 rc_t flush_one_rec(const record_t *rec, rid_t& rid, 00521 const stid_t& out_fid, file_p& last_page, 00522 bool to_final_file); 00523 00524 rc_t remove_duplicates(); // remove duplicates for unique sort 00525 rc_t merge(bool skip_last_pass); 00526 00527 void xct_state_changed( xct_state_t old_state, xct_state_t new_state); 00528 00529 key_info_t ki; // key info 00530 sort_parm_t sp; // sort parameters 00531 sort_desc_t* sd; // sort descriptor 00532 00533 bool sorted; // sorted flag 00534 bool eof; // eof flag 00535 bool empty; // empty flag 00536 const record_t* old_rec; // used for sort unique 00537 00538 bool _file_sort; // true if sorting a file 00539 00540 int2_t* heap; // heap array 00541 int heap_size; // heap size 00542 run_scan_t* sc; // scan descriptor array 00543 w_base_t::uint4_t num_runs; // # of runs for each merge 00544 int r; // run index 00545 00546 chunk_mgr_t buf_space; // in-memory storage 00547 00548 // below vars used for speeding up sort if whole file fits in memory 00549 bool _once; // one pass write to result file 00550 sm_store_property_t _property; // property for the result file 00551 }; 00552 00553 class file_p; 00554 00555 // 00556 // run scans 00557 // 00558 /**\cond skip */ 00559 class run_scan_t { 00560 typedef ssm_sort::key_info_t key_info_t; 00561 typedef ssm_sort::sort_parm_t sort_parm_t; 00562 00563 lpid_t pid; // current page id 00564 file_p* fp; // page buffer (at most fix two pages for unique sort) 00565 int2_t i; // toggle between two pages 00566 int2_t slot; // slot for current record 00567 record_t* cur_rec; // pointer to current record 00568 bool eof; // end of run 00569 key_info_t kinfo; // key description (location, len, type) 00570 int2_t toggle_base; // default = 1, unique sort = 2 00571 bool single; // only one page 00572 bool _unique; // unique sort 00573 00574 public: 00575 PFC cmp; 00576 00577 NORET run_scan_t(); 00578 NORET ~run_scan_t(); 00579 00580 rc_t init(rid_t& begin, PFC c, const key_info_t& k, bool unique); 00581 rc_t current(const record_t*& rec); 00582 rc_t next(bool& eof); 00583 00584 bool is_eof() { return eof; } 00585 00586 friend bool operator>(run_scan_t& s1, run_scan_t& s2); 00587 friend bool operator<(run_scan_t& s1, run_scan_t& s2); 00588 00589 const lpid_t& page() const { return pid; } 00590 }; 00591 /**\endcond skip */ 00592 00593 00594 /*<std-footer incl-file-exclusion='SORT_H'> -- do not edit anything below this line -- */ 00595 00596 #endif /*</std-footer>*/