123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /*
- * $XConsortium: page_storage.C /main/8 1996/10/04 10:49:57 drk $
- *
- * Copyright (c) 1992 HAL Computer Systems International, Ltd.
- * All rights reserved. Unpublished -- rights reserved under
- * the Copyright Laws of the United States. USE OF A COPYRIGHT
- * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
- * OR DISCLOSURE.
- *
- * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
- * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
- * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
- * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
- * INTERNATIONAL, LTD.
- *
- * RESTRICTED RIGHTS LEGEND
- * Use, duplication, or disclosure by the Government is subject
- * to the restrictions as set forth in subparagraph (c)(l)(ii)
- * of the Rights in Technical Data and Computer Software clause
- * at DFARS 252.227-7013.
- *
- * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
- * 1315 Dell Avenue
- * Campbell, CA 95008
- *
- */
- #include "storage/page.h"
- #include "storage/page_storage.h"
- #include "storage/version.h"
- #include "utility/db_version.h"
- #define db_type "MMDB"
- #define db_type_sz strlen(db_type)
- #define db_order_sz sizeof(char)
- int page_storage::dv_sz = 0;
- int page_storage::abs_off = 0;
- #ifndef C_API
- page_cache_global_part page_storage::f_global_pcache;
- #else
- page_cache_global_part* page_storage::f_global_pcache_ptr = 0;
- #endif
- static char* db_version = 0;
- static char* data_version = 0;
- str_index_record_t::str_index_record_t(int offset, mmdb_pos_t lc)
- : str_offset(offset), loc(lc)
- {
- }
- void delete_str_index_record(const void* t)
- {
- delete ((str_index_record_t*)t);
- }
- extern void_ptr_array g_store_array;
- extern Boolean g_transaction_on;
- //////////////////////////////
- //
- //////////////////////////////
- store_trans::store_trans(char* p, char* n, int psz) :
- path(p), name(n), status(DISABLED),
- log_store(0), log_index(0), max_pages(0), page_sz(psz)
- {
- }
- store_trans::~store_trans()
- {
- /*
- MESSAGE(cerr, "dstr store_trans object");
- debug(cerr, status);
- debug(cerr, DISABLED);
- debug(cerr, int(log_store));
- */
- if ( status == DISABLED && log_store ) {
- delete log_store;
- if ( exist_file(form("%s.log", name), path) )
- del_file(form("%s.log", name), path);
- }
- delete log_index;
- }
- void store_trans::init(rep_policy* policy)
- {
- if ( log_store == 0 ) {
- log_store = new unixf_storage(path, form("%s.log", name), policy);
- if ( ! (*log_store) )
- throw(streamException(log_store -> rdstate()));
- }
- if ( log_index == 0 ) {
- log_index = new imp_die;
- }
- }
- void store_trans::quit()
- {
- if ( log_store )
- log_store -> truncate(0);
- if ( log_index )
- log_index -> clean();
- }
- ///////////////////////////////////
- // Constructor
- ///////////////////////////////////
- page_storage::page_storage( char* _path, char* _name,
- unixf_storage* store, int pg_sz,
- int/*no_pages*/, mmdb_byte_order_t create_order) :
- abs_storage(_path, _name, PAGE_STORAGE_CODE),
- trans_info(page_storage::path, page_storage::name, pg_sz),
- page_sz(pg_sz),
- f_local_pcache(30),
- v_db_order(create_order), v_buf(0),
- pagings(0),
- total_page_access(0)
- {
- //debug(cerr, my_name());
- //debug(cerr, (void*)this);
- //#ifdef C_API
- if ( dv_sz == 0 ) {
- dv_sz = db_type_sz + mm_version::version_bytes() + db_order_sz;
- abs_off = dv_sz;
- }
- //#endif
- storage_ptr = store;
- int bts = ((unixf_storage*)storage_ptr) -> bytes();
- v_server_order = byte_order();
- //debug(cerr, v_server_order);
- if ( bts == 0 ) {
- //////////////////////
- // empty store file
- //////////////////////
- if ( db_version == 0 ) {
- db_version = new char[dv_sz];
- memcpy(db_version, db_type, db_type_sz);
- mm_version x(MAJOR, MINOR);
- x.to_byte_string(db_version+db_type_sz,
- (v_db_order != v_server_order) ? true : false
- );
- char z = v_db_order;
- memcpy(db_version+db_type_sz+mm_version::version_bytes(),
- &z, db_order_sz);
- }
- storage_ptr -> updateString( 0, db_version, dv_sz, 0, true);
- v_swap_order = (v_db_order != v_server_order) ? true : false;
- } else {
- ///////////////////
- // store exists.
- ///////////////////
- bts -= abs_off;
- if ( data_version == 0 ) {
- data_version = new char[dv_sz];
- }
- storage_ptr -> readString(0, data_version, dv_sz);
- /////////////////////////////////
- // "MMDB" magic number testing
- /////////////////////////////////
- if ( memcmp(data_version, db_type, db_type_sz) != 0 ) {
- throw(stringException(
- form("bad magic number. corrupted store %s/%s", _path, _name)
- )
- );
- }
- ///////////////////////////////
- // get db byte order
- ///////////////////////////////
- char z;
- memcpy(&z,
- data_version + db_type_sz + mm_version::version_bytes(),
- db_order_sz
- );
-
- v_db_order = int(z);
- if ( v_db_order != mmdb_big_endian && v_db_order != mmdb_little_endian ) {
- debug(cerr, v_db_order);
- throw(stringException(
- "data is in neither big endian nor little endian format"
- ));
- }
- ///////////////////////////////
- // test version
- ///////////////////////////////
- v_swap_order = (v_db_order != v_server_order) ? true : false;
- mm_version dv(data_version+db_type_sz, v_swap_order);
- f_version = dv;
- mm_version cv(MAJOR, MINOR);
- if ( cv < dv ) {
- cerr << "code major = " << cv.major_version() << "\n";
- cerr << "code minor = " << cv.minor_version() << "\n";
- cerr << "data major = " << dv.major_version() << "\n";
- cerr << "data minor = " << dv.minor_version() << "\n";
- throw(stringException(
- form("data and code version mismatch on store %s/%s", _path, _name)
- )
- );
- }
- }
- //debug(cerr, v_db_order);
- total_pages = bts / page_sz;
- f_local_pcache.init_heap(this);
- set_mode(HEALTH, true);
- }
- /***********************************************************/
- // Destructor
- /***********************************************************/
- page_storage::~page_storage()
- {
- //MESSAGE(cerr, "dstr page_storage");
- //debug(cerr, my_name());
- delete v_buf;
- delete storage_ptr;
- delete data_version;
- data_version = 0;
- delete db_version;
- db_version = 0;
- f_local_pcache.quit_heap(this);
- f_global_pcache.remove_pages(this);
- /*
- MESSAGE(cerr, my_name());
- debug(cerr, total_page_access);
- debug(cerr, pagings);
- debug(cerr, float(pagings)/total_page_access);
- */
- }
- void page_storage::remove()
- {
- storage_ptr -> remove();
- }
- void page_storage::sync()
- {
- /*
- MESSAGE(cerr, "page_storage::sync()");
- debug(cerr, my_path());
- debug(cerr, my_name());
- debug(cerr, pages());
- debug(cerr, int(this));
- */
- long ind = f_global_pcache.f_replace_policy.first();
- while ( ind != 0 ) {
- lru_page *p= (lru_page*)(f_global_pcache.f_replace_policy)(ind, ACTIVE);
- if ( p -> f_store == this )
- sync( p );
- f_global_pcache.f_replace_policy.next(ind);
- }
- //MESSAGE(cerr, "page_storage::sync() done");
- }
- void page_storage::sync( int page_num )
- {
- sync((*this)(page_num, READ));
- }
- void page_storage::sync( page* p )
- {
- if ( p == 0 || p -> page_id() <= 0 ) {
- throw(stringException("null page pointer"));
- }
- if ( p -> dirty == true ) {
- //cerr << "dirty PAGE swapped out " << p -> page_id();
- //cerr << " " << my_name() << "\n";
- int offset = ( p -> page_id() - 1 ) * page_sz ;
- #ifdef PORTABLE_DB
- p -> _swap_order(false);
- #endif
- //debug(cerr, *p);
- #ifdef DEBUG
- fprintf(stderr, "purging page at %p size=%d into %s/%s @ %s:%d\n",
- p -> page_base(), page_sz,
- storage_ptr->my_path(), storage_ptr->my_name(),
- __FILE__, __LINE__);
- #endif
- storage_ptr -> updateString( abs_off + mmdb_pos_t(offset),
- p -> page_base(),
- page_sz, 0, true
- );
- #ifdef PORTABLE_DB
- //////////////////////////////////////////////////////////////
- // flip back to original. as the server will not quit after
- // the sync.
- //////////////////////////////////////////////////////////////
- p -> _swap_order(true);
- #endif
- p -> dirty = false;
- }
- }
- //static Boolean xflag = false;
- /***********************************************************/
- // readString().
- /***********************************************************/
- int
- page_storage::readString(mmdb_pos_t loc, char* base, int len, int str_offset)
- {
- /*
- int xstring_ofst = str_offset;
- int xloc = loc;
- int xlen = len;
- MESSAGE(cerr, "page_storage: readString");
- debug(cerr, my_path());
- debug(cerr, my_name());
- debug(cerr, loc);
- debug(cerr, int(base));
- debug(cerr, len);
- debug(cerr, str_offset);
- */
- buffer in_cache(0);
- in_cache.set_chunk(base, len);
- spointer_t *slot_info;
- while ( len > 0 ) {
- if ( loc == 0 ) {
- throw(stringException("damaged store."));
- }
- int page_num = PAGE_ID( loc, page_sz );
- int page_slot = PAGE_IDX( loc, page_sz );
- //debug(cerr, page_num);
- //debug(cerr, page_slot);
-
- page *y = (*this)(page_num, READ);
- slot_info = y -> get_spointer(page_slot);
- int str_leng = slot_info -> string_leng();
- loc = slot_info -> forward_ptr();
- /*
- MESSAGE(cerr, "slot info:");
- debug(cerr, str_leng);
- debug(cerr, loc);
- debug(cerr, slot_info -> string_ofst());
- */
- delete slot_info;
- if ( str_offset >= str_leng ) {
- str_offset -= str_leng;
- } else {
- int bytes_read = MIN(len, str_leng - str_offset);
- /*
- debug(cerr, len);
- debug(cerr, bytes_read);
- */
- y -> get( page_slot, in_cache, str_offset, bytes_read );
- len -= bytes_read;
- str_offset = 0;
- }
- }
- //MESSAGE(cerr, "page_storage:: readString done");
- return 0;
- }
- int
- page_storage::get_str_ptr(mmdb_pos_t loc, char*& str,
- int& len)
- {
- int page_num = PAGE_ID( loc, page_sz );
- int page_slot = PAGE_IDX( loc, page_sz );
- //MESSAGE(cerr, "IN get_str_ptr()");
- //debug(cerr, my_path());
- //debug(cerr, my_name());
- //debug(cerr, page_num);
- //debug(cerr, page_slot);
- page *y = (*this)(page_num, READ);
- spointer_t* slot_info = y -> get_spointer(page_slot);
- //debug(cerr, int(slot_info -> get_mode(spointer_t::DELETED)));
- /*
- if ( page_num == 1 && page_slot == 1 ) {
- debug(cerr, hex(slot_info -> header.int_view));
- debug(cerr, hex(slot_info -> header.bit_view.spointer));
- debug(cerr, hex(slot_info -> header.bit_view.length));
- debug(cerr, hex(slot_info -> header.bit_view.deleted));
- debug(cerr, hex(slot_info -> header.bit_view.first_recd));
- debug(cerr, hex(slot_info -> header.bit_view.updated));
- debug(cerr, hex(slot_info -> header.bit_view.is_object));
- }
- */
- if ( slot_info -> get_mode(spointer_t::DELETED) == true ) {
- delete slot_info;
- throw(stringException("read deleted byte string"));
- }
- delete slot_info;
- y -> get_str_ptr(page_slot, str, len);
- return 0;
- }
- int page_storage::insertString(mmdb_pos_t& loc, const char* base, int len, Boolean flush_opt)
- {
- /*
- cerr << "insert: len=" << len << "\n";
- int u3 = len;
- */
- #ifdef STORAGE_DEBUG
- MESSAGE(cerr, "page_storage insertString");
- debug(cerr, len);
- #endif
- buffer temp_buf(0);
- int page_num = 0;
- int page_oft = 0;
- int str_offset = len;
- int sec_len;
- Boolean first_recd = true;
- Boolean new_page;
- while ( str_offset > 0 ) {
- loc = (page_num != 0 ) ?
- FORM_PAGE_REF(page_num, page_oft, page_sz) :
- 0;
- fbytes_t* v = f_local_pcache.find_host_page(this, new_page) ;
- page_num = v -> page_num;
- page* y = (*this)(page_num, WRITE);
- sec_len = MIN(len, y -> free_bytes());
- str_offset -= sec_len;
- temp_buf.set_chunk((char*)(base + str_offset), sec_len);
- temp_buf.set_content_sz(sec_len);
- y -> put( page_oft, temp_buf );
- spointer_t *x = y -> get_spointer(page_oft);
- x -> set_mode(spointer_t::FIRST_RECD, first_recd);
- x -> set_forward_ptr(loc);
- delete x;
- v -> free_bytes = y -> free_bytes();
- f_local_pcache.adjust_heap(v, new_page);
- if ( flush_opt == true ) sync(page_num);
- first_recd = false;
- len -= sec_len;
- }
- #ifdef STORAGE_DEBUG
- MESSAGE(cerr, "FINAL LOC COMPONENT");
- debug(cerr, page_oft);
- debug(cerr, page_sz);
- debug(cerr, page_num);
- #endif
- loc = FORM_PAGE_REF(page_num, page_oft, page_sz);
- /*
- int u1 = PAGE_ID( loc, page_sz );
- int u2 = PAGE_IDX( loc, page_sz );
- cerr << "insert:" << page_num << "." << page_oft << " " << u3 << "\n";
- */
- return 0;
- }
- /***********************************************************/
- // updateString().
- /***********************************************************/
- int
- page_storage::updateString(mmdb_pos_t loc, const char* base, int len,
- int string_ofst, Boolean flush_opt)
- {
- /*
- int u1 = PAGE_ID( loc, page_sz );
- int u2 = PAGE_IDX( loc, page_sz );
- cerr << "update:" << u1 << "." << u2 << " " << len << " " << string_ofst << "\n";
- */
- /*
- MESSAGE(cerr, "update string");
- debug(cerr, name);
- debug(cerr, loc);
- */
- int page_num =0;
- int slot_num =0;
- int offset = 0;
- page* y = 0;
- spointer_t *x = 0;
- while ( len > 0 && loc != 0 ) {
- page_num = PAGE_ID( loc, page_sz );
- slot_num = PAGE_IDX( loc, page_sz );
- //debug(cerr, page_num);
- //debug(cerr, slot_num);
- y = (*this)(page_num, WRITE);
- x = y -> get_spointer(slot_num);
- /*
- debug(cerr, x -> forward_ptr());
- debug(cerr, x -> string_leng());
- debug(cerr, x -> string_ofst());
- */
- loc = x -> forward_ptr();
- int this_len = x -> string_leng();
- delete x;
- if ( string_ofst >= this_len ) {
- string_ofst -= this_len;
- continue;
- }
- int update_len = MIN(len, this_len - string_ofst);
- buffer sbuf(0);
- sbuf.set_chunk((char*)(base+offset), update_len);
- sbuf.set_content_sz(update_len);
- y -> update_slot(slot_num, sbuf, string_ofst);
- if ( flush_opt == true ) sync(page_num);
- string_ofst = 0;
- offset += update_len;
- len -= update_len;
- }
- if ( len > 0 ) {
- //debug(cerr, len);
- //debug(cerr, offset);
- /*****************************/
- // the update is an expanding
- /*****************************/
- mmdb_pos_t new_loc;
- insertString(new_loc, base+offset, len, flush_opt) ;
- y = (*this)(page_num, WRITE);
- x = y -> get_spointer(slot_num);
- x -> set_forward_ptr(new_loc);
- delete x;
- page_num = PAGE_ID( new_loc, page_sz );
- slot_num = PAGE_IDX( new_loc, page_sz );
- y = (*this)(page_num, WRITE);
- x = y -> get_spointer(slot_num);
- x -> set_mode(spointer_t::FIRST_RECD, false);
- delete x;
- y -> dirty = true;
- return 0;
- }
- // if ( loc != 0 ) {
- /*****************************/
- // the update is a shrinking
- /*****************************/
- // y = (*this)(page_num);
- // x = y -> get_spointer(slot_num);
- // x -> set_forward_ptr(0);
- // return deleteString(loc);
- // }
- return 0;
- }
- /***********************************************************/
- // deleteString().
- /***********************************************************/
- int page_storage::deleteString(mmdb_pos_t loc, Boolean flush_opt)
- {
- while ( loc != 0 ) {
- int page_num = PAGE_ID( loc, page_sz );
- int slot_num = PAGE_IDX( loc, page_sz );
- //debug(cerr, page_num);
- //debug(cerr, slot_num);
- page* y = (*this)(page_num, WRITE);
- spointer_t *x = y -> get_spointer(slot_num);
- if ( x -> get_mode(spointer_t::DELETED) == true ) {
- delete x;
- return 0;
- }
- loc = x -> forward_ptr();
- //debug(cerr, loc);
- delete x;
- y -> del_slot(slot_num);
- if ( flush_opt == true ) sync(page_num);
- }
- return 0;
- }
- /***********************************************************/
- // allocate a chunk on a page.
- /***********************************************************/
- int
- page_storage::allocString(mmdb_pos_t& loc, int len, char*& string_ptr, int mode)
- {
- //MESSAGE(cerr, "AllocString:");
- //debug(cerr, my_name());
- //debug(cerr, len);
- if ( len > page_sz ) {
- MESSAGE(cerr, "allocString(): string too long");
- throw(boundaryException(0, page_sz, len));
- }
- Boolean new_page;
- fbytes_t* v = f_local_pcache.find_host_page(this, new_page, len) ;
- page* x = (*this)(v -> page_num, WRITE);
- int slot_num;
- x->alloc_slot(slot_num, len, string_ptr);
- spointer_t* slot_info = x -> get_spointer(slot_num);
- slot_info -> add_mode(mode);
- delete slot_info;
- v -> free_bytes = x -> free_bytes();
- f_local_pcache.adjust_heap(v, new_page);
- loc = FORM_PAGE_REF(v -> page_num, slot_num, page_sz);
- #ifdef STORAGE_DEBUG
- MESSAGE(cerr, "in allocString(): final params");
- debug(cerr, int(x -> dirty));
- debug(cerr, page_num);
- debug(cerr, slot_num);
- debug(cerr, my_name());
- debug(cerr, loc);
- debug(cerr, int(string_ptr));
- #endif
- // int u1 = PAGE_ID( loc, page_sz );
- // int u2 = PAGE_IDX( loc, page_sz );
- // cerr << "Allocated ID=" << u1 << "." << u2 << " " << len << "\n";
- return 0;
- }
- int page_storage::appendString(mmdb_pos_t loc, const char* base, int len, Boolean)
- {
- /*
- int u1 = PAGE_ID( loc, page_sz );
- int u2 = PAGE_IDX( loc, page_sz );
- cerr << "append:" << u1 << "." << u2 << " " << len << "\n";
- */
- int page_num = 0;
- int slot_num = 0;
- page* y;
- spointer_t *x;
- while ( loc != 0 ) {
- page_num = PAGE_ID( loc, page_sz );
- slot_num = PAGE_IDX( loc, page_sz );
- y = (*this)(page_num, READ);
- x = y -> get_spointer(slot_num);
- loc = x -> forward_ptr();
- delete x;
- }
- insertString(loc, base, len) ;
- y = (*this)(page_num, WRITE);
- x = y -> get_spointer(slot_num);
- x -> set_forward_ptr(loc);
- delete x;
- page_num = PAGE_ID( loc, page_sz );
- slot_num = PAGE_IDX( loc, page_sz );
- y = (*this)(page_num, WRITE);
- x = y -> get_spointer(slot_num);
- x -> set_mode(spointer_t::FIRST_RECD, false);
- delete x;
- return 0;
- }
- /***********************************************************/
- // create new page frame.
- /***********************************************************/
- int page_storage::add_page_frames(int pages)
- {
- total_pages += pages;
- //////////////////////////////////////
- // prepare the new page in the cache
- //////////////////////////////////////
- for (int i=1; i<=pages; i++)
- operator()(total_pages+i-pages, WRITE);
- return 0;
- }
- /***********************************************************/
- // return the mmdb_pos_t of the first page.
- /***********************************************************/
- int page_storage::first() const
- {
- return ( total_pages > 0 ) ? 1 : 0;
- }
- //////////////////////////////////////////
- /* ind should be the page id */
- //////////////////////////////////////////
- page* page_storage::operator()(int ind, enum access mode)
- {
- /*
- if ( mode == WRITE ) {
- MESSAGE(cerr, "opera(): write mode");
- debug(cerr, ind);
- debug(cerr, name);
- }
- */
- /*
- if ( mode == WRITE ) {
- char* s = name + strlen(name) - 11;
- debug(cerr, s);
- if ( strcmp(s, "index.store") == 0 )
- debug(cerr, name);
- }
- */
- //cerr << "Try to get page " << ind << " from " << my_name() << "\n";
- if ( ! INRANGE( ind, 1, pages() ) ) {
- debug(cerr, my_path());
- debug(cerr, my_name());
- MESSAGE(cerr,
- form("page_storage:: operator(): mmdb_pos_t %d out of range.", ind)
- );
- throw(boundaryException(1, pages(), ind));
- }
- page* p = f_local_pcache.in_cache(this, ind);
-
- if ( p == 0 ) {
-
- //cerr << "swapping in a page " << ind << endl;
- p = f_global_pcache.load_new_page( this, ind,
- (v_db_order==v_server_order) ? false : true
- );
-
- }
-
- /*
- debug(cerr, my_name());
- debug(cerr, p -> count());
- debug(cerr, int(mode));
- debug(cerr, int(WRITE));
- */
- if ( mode == WRITE ) {
- p -> dirty = true;
- save_to_log(p);
- }
- return p;
- }
- /***********************************************************/
- // update ind to the mmdb_pos_t of next page.
- /***********************************************************/
- void page_storage::next(int& ind) const
- {
- if ( ind >= pages() )
- ind = 0;
- else
- ind++;
- }
- io_status page_storage::asciiOut(ostream& out)
- {
- int ind = first();
- while ( ind != 0 ) {
- #ifdef DEBUG
- page* p = (*this)(ind, READ);
- debug(out, *p);
- #endif
- next(ind);
- }
- return done;
- /*
- debug(cerr, pagings);
- pagings = 0;
- */
- }
- Boolean
- page_storage::seek_loc(mmdb_pos_t& loc, const direction d, int smd)
- {
- if ( d == positive ) {
- return seek_loc_positive(loc, smd);
- } else {
- return seek_loc_negative(loc, smd);
- }
- }
- Boolean page_storage::seek_loc_positive(mmdb_pos_t& loc, int smd)
- {
- int pgs = pages();
- int page_num = PAGE_ID( loc, page_sz );
- int page_slot = PAGE_IDX( loc, page_sz );
- while ( page_num <= pgs ) {
- page* x = (*this)(page_num, READ);
- if ( page_slot == 0 )
- page_slot = x -> first();
- else
- x -> next( page_slot );
- spointer_t *y;
- while ( page_slot && (y = x -> get_spointer(page_slot)) != 0 ) {
- if ( y -> get_mode(spointer_t::DELETED) == false &&
- y -> test_mode(smd) == true ) {
- loc = FORM_PAGE_REF(page_num, page_slot, page_sz);
- delete y;
- return true;
- } else {
- delete y;
- x -> next(page_slot);
- }
- }
- page_num++;
- page_slot = 0;
- }
- return false;
- }
- Boolean page_storage::seek_loc_negative(mmdb_pos_t& loc, int smd)
- {
- int page_num = PAGE_ID( loc, page_sz );
- int page_slot = PAGE_IDX( loc, page_sz );
- while ( page_num > 0 ) {
- page* x = (*this)(page_num, READ);
- if ( page_slot == 0 )
- page_slot = x -> count() - 1;
- else
- x -> prev(page_slot);
- spointer_t *y;
- while ( page_slot && (y = x -> get_spointer(page_slot)) != 0 )
- {
- if ( y -> get_mode(spointer_t::DELETED) == false &&
- y -> test_mode(smd) == true ) {
- loc = FORM_PAGE_REF(page_num, page_slot, page_sz);
- delete y;
- return true;
- } else {
- delete y;
- x -> prev(page_slot);
- }
- }
- page_num--;
- page_slot = 0;
- }
- return false;
- }
- void page_storage::reset_paging_count()
- {
- /*
- if ( storage_ptr -> rdbuf() -> is_open() ) {
- cerr << storage_ptr -> my_name() << " has not been closed\n";
- storage_ptr -> close();
- } else {
- cerr << storage_ptr -> my_name() << " is already closed\n";
- }
- */
- pagings = 0;
-
- }
-
- int page_storage::paging_count() const
- {
- return pagings;
- }
- mmdb_pos_t page_storage::first_loc()
- {
- if ( pages() >= 1 && (*this)(1, READ) -> count() != 0 )
- return FORM_PAGE_REF(1, 1, page_sz);
- else
- return 0;
- }
- mmdb_pos_t page_storage::last_loc()
- {
- int pgs = pages();
-
- if ( pgs == 0 )
- return 0;
- for ( int i=pgs; i>0; i-- ) {
- int ct = (*this)(i, READ) -> count();
- if ( ct > 0 )
- return FORM_PAGE_REF(i, ct, page_sz);
- }
- return 0;
- }
- int
- page_storage::get_str_locs(mmdb_pos_t str_loc,
- str_index_record_tPtr*& vector, int& vector_len
- )
- {
- int vector_sz = 20;
- vector = new str_index_record_tPtr[vector_sz];
- int num_pieces = 0;
- int str_offset = 0;
- spointer_t *x = 0;
- while ( str_loc > 0 ) {
- if ( num_pieces >= vector_sz ) {
- vector_sz *= 2;
- vector = (str_index_record_tPtr*)realloc(
- (char*)vector,
- vector_sz*sizeof(str_index_record_tPtr)
- );
- }
- vector[num_pieces++] =
- new str_index_record_t(str_offset, str_loc);
- int page_num = PAGE_ID( str_loc, page_sz );
- int page_slot = PAGE_IDX( str_loc, page_sz );
- page *y = (*this)(page_num, READ);
- x = y -> get_spointer(page_slot);
- str_offset += x -> string_leng();
- str_loc = x -> forward_ptr();
- delete x;
- }
- vector_len = num_pieces;
- return 0;
- }
- int page_storage::set_page_dirty(mmdb_pos_t loc)
- {
- MESSAGE(cerr, "set page dirty: page loc is");
- debug(cerr, loc);
- page* x = (*this)(PAGE_ID( loc, page_sz ), WRITE);
- x -> dirty = true;
- return 0;
- }
- Boolean page_storage::io_mode(int mode)
- {
- if ( storage_ptr )
- return storage_ptr -> io_mode(mode);
- else
- return false;
- }
- void page_storage::begin_trans()
- {
- mtry {
- if ( trans_info.status == store_trans::ENABLED )
- throw(stringException("trans is still in progress"));
-
- trans_info.init(policy);
- trans_info.set_max_pages(total_pages);
-
- trans_info.status = store_trans::ENABLED;
-
- int l_max_pages = trans_info.max_pages;
- if ( swap_order() == true )
- ORDER_SWAP_UINT(l_max_pages);
-
- trans_info.log_store ->
- updateString(0, (char*)&l_max_pages, sizeof(l_max_pages), 0, true);
- }
- mcatch (mmdbException&, e) {
- // workaround for solaris's /SUNWspro/bin/CC compiler.
- beginTransException x;
- throw(x);
- //throw(beginTransException());
- }
- end_try;
- }
- void page_storage::commit_trans()
- {
- //////////////////////////////
- // sync the touched pages
- //////////////////////////////
- mtry {
- int ind = trans_info.log_index -> first_bucket();
-
- while ( ind != -1 ) {
-
- imp_bucket* bucket = trans_info.log_index -> get_bucket(ind);
-
- if ( bucket ) {
- long b_ind = bucket -> first();
- while ( b_ind != 0 ) {
- data_t* z = (*bucket)(b_ind);
- //debug(cerr, ((page*)(z -> dt)) -> count());
- sync((page*)(z -> dt));
- bucket -> next(b_ind);
- }
- }
- trans_info.log_index -> next_bucket(ind);
- }
-
- trans_info.quit();
-
- trans_info.status = store_trans::DISABLED;
- }
- mcatch (mmdbException &,e) {
- // workaround for solaris's /SUNWspro/bin/CC compiler.
- commitTransException x;
- throw(x);
- } end_try;
- }
- void page_storage::roll_back()
- {
- mtry
- {
- if ( exist_file(form("%s.log", name), path) == false )
- return;
-
- MESSAGE(cerr, "roll_back() begins");
-
- trans_info.init(policy); // init the log store
-
- //////////////////////////////////
- // verify the log is in good shape
- //////////////////////////////////
- int m;
- unsigned int log_bytes = trans_info.log_store -> bytes();
-
- if ( trans_info.log_store &&
- (*trans_info.log_store) &&
- log_bytes > sizeof(m) )
- {
-
- //////////////////////////////////
- // truncate the store to previous
- // length
- //////////////////////////////////
- trans_info.log_store -> readString(0, (char*)&m, sizeof(m));
-
- if ( swap_order() == true )
- ORDER_SWAP_UINT(m);
-
- trans_info.set_max_pages(m); // init the log store
-
- ((unixf_storage*)storage_ptr) -> truncate(abs_off + m*page_sz);
-
- //debug(cerr, m);
- //////////////////////////////////
- // restore the store to previous
- // state
- //////////////////////////////////
- int l_pid = 0;
-
- if ( (log_bytes - sizeof(m)) % (page_sz+sizeof(l_pid)) != 0 )
- throw(stringException("corrupted transaction log"));
-
- int u = (log_bytes - sizeof(m)) / (page_sz+sizeof(l_pid));
- //debug(cerr, u);
-
-
- buffer log_buf(page_sz);
- for ( int i=0; i<u; i++ ) {
-
- int offset = sizeof(m) + i*(page_sz + sizeof(l_pid));
-
- trans_info.log_store ->
- readString(offset, // page id
- (char*)&l_pid, sizeof(l_pid)
- );
-
- if ( swap_order() == true ) // swap byte order if necessary
- ORDER_SWAP_UINT(l_pid);
-
- trans_info.log_store ->
- readString(offset + sizeof(l_pid), // page content
- log_buf.get_base(),
- page_sz
- );
-
-
- storage_ptr -> updateString( abs_off + (l_pid-1)*page_sz,
- log_buf.get_base(),
- page_sz,
- 0,
- true
- );
- }
- }
-
- ///////////////////////////////////////////////
- // make sure the cached pages are not synced
- ///////////////////////////////////////////////
-
- long ind = f_global_pcache.f_replace_policy.first();
-
- while ( ind != 0 ) {
- lru_page *p = (lru_page*)
- (f_global_pcache.f_replace_policy)(ind, ACTIVE);
- if ( p -> f_store == this )
- p -> dirty = false;
- f_global_pcache.f_replace_policy.next(ind);
- }
-
- trans_info.quit(); // remove the log store
-
- trans_info.status = store_trans::DISABLED;
- }
- mcatch (mmdbException &,e)
- {
- // workaround for solaris's /SUNWspro/bin/CC compiler.
- rollbackTransException x;
- throw(x);
- } end_try;
- MESSAGE(cerr, "roll_back() completes");
- }
- void page_storage::save_to_log(page* p)
- {
- /*
- MESSAGE(cerr, "About to save to log");
- debug(cerr, my_name());
- debug(cerr, int(trans_info.status));
- debug(cerr, int(store_trans::ENABLED));
- debug(cerr, trans_info.max_pages);
- */
- if ( trans_info.status == store_trans::ENABLED &&
- INRANGE(p -> page_id(), 1, trans_info.max_pages)
- )
- {
- //assert ( trans_info.log_store );
- //assert ( trans_info.log_index );
- if ( trans_info.log_store == 0 || trans_info.log_index == 0 )
- throw(stringException("corrupted store"));
-
- int l_pid = p -> page_id();
- data_t pkey(l_pid, voidPtr(p));
-
- if ( trans_info.log_index -> member(pkey) == false ) {
- //MESSAGE(cerr, form("Save_to_log pid=%d, pcnt = %d, name=%s",
- // l_pid, p -> count(), name));
- int log_bytes_before = trans_info.log_store -> bytes();
-
- mtry {
- if ( swap_order() == true ) // swap to desired order
- ORDER_SWAP_UINT(l_pid);
- trans_info.log_store ->
- appendString( 0, (char*)&l_pid, sizeof(l_pid), false );
- if ( swap_order() == true ) // swap back
- ORDER_SWAP_UINT(l_pid);
-
- p -> _swap_order(false);
- trans_info.log_store ->
- appendString( 0, p -> page_base(), page_sz, true );
- //debug(cerr, trans_info.log_store -> bytes());
- p -> _swap_order(true);
-
- trans_info.log_index -> insert(pkey);
- }
- mcatch (mmdbException&, e) {
- trans_info.log_store -> truncate(log_bytes_before);
- rethrow;
- }
- end_try;
- }
- // else
- //MESSAGE(cerr, form("Not save_to_log pid=%d, name=%s", l_pid, name));
- }
- }
- buffer& page_storage::aux_buf()
- {
- if ( v_buf == 0 )
- v_buf = new buffer(LBUFSIZ);
- return *v_buf;
- }
|