2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $XConsortium: page_storage.C /main/8 1996/10/04 10:49:57 drk $
26 * Copyright (c) 1992 HAL Computer Systems International, Ltd.
27 * All rights reserved. Unpublished -- rights reserved under
28 * the Copyright Laws of the United States. USE OF A COPYRIGHT
29 * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
32 * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
33 * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
34 * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
35 * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
38 * RESTRICTED RIGHTS LEGEND
39 * Use, duplication, or disclosure by the Government is subject
40 * to the restrictions as set forth in subparagraph (c)(l)(ii)
41 * of the Rights in Technical Data and Computer Software clause
42 * at DFARS 252.227-7013.
44 * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
51 #include "storage/page.h"
52 #include "storage/page_storage.h"
53 #include "storage/version.h"
54 #include "utility/db_version.h"
56 #define db_type "MMDB"
57 #define db_type_sz strlen(db_type)
59 #define db_order_sz sizeof(char)
61 int page_storage::dv_sz = 0;
62 int page_storage::abs_off = 0;
65 page_cache_global_part page_storage::f_global_pcache;
67 page_cache_global_part* page_storage::f_global_pcache_ptr = 0;
71 static char* db_version = 0;
72 static char* data_version = 0;
74 str_index_record_t::str_index_record_t(int offset, mmdb_pos_t lc)
75 : str_offset(offset), loc(lc)
79 void delete_str_index_record(const void* t)
81 delete ((str_index_record_t*)t);
84 extern void_ptr_array g_store_array;
85 extern Boolean g_transaction_on;
87 //////////////////////////////
89 //////////////////////////////
90 store_trans::store_trans(char* p, char* n, int psz) :
91 path(p), name(n), status(DISABLED),
92 log_store(0), log_index(0), max_pages(0), page_sz(psz)
96 store_trans::~store_trans()
99 MESSAGE(cerr, "dstr store_trans object");
101 debug(cerr, DISABLED);
102 debug(cerr, int(log_store));
105 if ( status == DISABLED && log_store ) {
107 del_file(form("%s.log", name), path);
112 void store_trans::init(rep_policy* policy)
114 if ( log_store == 0 ) {
115 log_store = new unixf_storage(path, form("%s.log", name), policy);
117 if ( ! (*log_store) )
118 throw(streamException(log_store -> rdstate()));
121 if ( log_index == 0 ) {
122 log_index = new imp_die;
126 void store_trans::quit()
129 log_store -> truncate(0);
132 log_index -> clean();
135 ///////////////////////////////////
137 ///////////////////////////////////
138 page_storage::page_storage( char* _path, char* _name,
139 unixf_storage* store, int pg_sz,
140 int/*no_pages*/, mmdb_byte_order_t create_order) :
141 abs_storage(_path, _name, PAGE_STORAGE_CODE),
142 trans_info(page_storage::path, page_storage::name, pg_sz),
145 v_db_order(create_order), v_buf(0),
150 //debug(cerr, my_name());
151 //debug(cerr, (void*)this);
154 dv_sz = db_type_sz + mm_version::version_bytes() + db_order_sz;
162 int bts = ((unixf_storage*)storage_ptr) -> bytes();
164 v_server_order = byte_order();
165 //debug(cerr, v_server_order);
168 //////////////////////
170 //////////////////////
172 if ( db_version == 0 ) {
173 db_version = new char[dv_sz];
175 memcpy(db_version, db_type, db_type_sz);
177 mm_version x(MAJOR, MINOR);
179 x.to_byte_string(db_version+db_type_sz,
180 (v_db_order != v_server_order) ? true : false
184 memcpy(db_version+db_type_sz+mm_version::version_bytes(),
188 storage_ptr -> updateString( 0, db_version, dv_sz, 0, true);
190 v_swap_order = (v_db_order != v_server_order) ? true : false;
199 if ( data_version == 0 ) {
200 data_version = new char[dv_sz];
203 storage_ptr -> readString(0, data_version, dv_sz);
205 /////////////////////////////////
206 // "MMDB" magic number testing
207 /////////////////////////////////
208 if ( memcmp(data_version, db_type, db_type_sz) != 0 ) {
209 throw(stringException(
210 form("bad magic number. corrupted store %s/%s", _path, _name)
215 ///////////////////////////////
217 ///////////////////////////////
220 data_version + db_type_sz + mm_version::version_bytes(),
226 if ( v_db_order != mmdb_big_endian && v_db_order != mmdb_little_endian ) {
227 debug(cerr, v_db_order);
228 throw(stringException(
229 "data is in neither big endian nor little endian format"
234 ///////////////////////////////
236 ///////////////////////////////
237 v_swap_order = (v_db_order != v_server_order) ? true : false;
239 mm_version dv(data_version+db_type_sz, v_swap_order);
243 mm_version cv(MAJOR, MINOR);
246 cerr << "code major = " << cv.major_version() << "\n";
247 cerr << "code minor = " << cv.minor_version() << "\n";
248 cerr << "data major = " << dv.major_version() << "\n";
249 cerr << "data minor = " << dv.minor_version() << "\n";
250 throw(stringException(
251 form("data and code version mismatch on store %s/%s", _path, _name)
258 //debug(cerr, v_db_order);
261 total_pages = bts / page_sz;
263 f_local_pcache.init_heap(this);
265 set_mode(HEALTH, true);
268 /***********************************************************/
270 /***********************************************************/
271 page_storage::~page_storage()
273 //MESSAGE(cerr, "dstr page_storage");
274 //debug(cerr, my_name());
285 f_local_pcache.quit_heap(this);
287 f_global_pcache.remove_pages(this);
290 MESSAGE(cerr, my_name());
291 debug(cerr, total_page_access);
292 debug(cerr, pagings);
293 debug(cerr, float(pagings)/total_page_access);
297 void page_storage::remove()
299 storage_ptr -> remove();
302 void page_storage::sync()
306 MESSAGE(cerr, "page_storage::sync()");
307 debug(cerr, my_path());
308 debug(cerr, my_name());
309 debug(cerr, pages());
310 debug(cerr, int(this));
314 long ind = f_global_pcache.f_replace_policy.first();
317 lru_page *p= (lru_page*)(f_global_pcache.f_replace_policy)(ind, ACTIVE);
318 if ( p -> f_store == this )
320 f_global_pcache.f_replace_policy.next(ind);
323 //MESSAGE(cerr, "page_storage::sync() done");
326 void page_storage::sync( int page_num )
328 sync((*this)(page_num, READ));
331 void page_storage::sync( page* p )
333 if ( p == 0 || p -> page_id() <= 0 ) {
334 throw(stringException("null page pointer"));
337 if ( p -> dirty == true ) {
340 //cerr << "dirty PAGE swapped out " << p -> page_id();
341 //cerr << " " << my_name() << "\n";
343 int offset = ( p -> page_id() - 1 ) * page_sz ;
346 p -> _swap_order(false);
352 fprintf(stderr, "purging page at %p size=%d into %s/%s @ %s:%d\n",
353 p -> page_base(), page_sz,
354 storage_ptr->my_path(), storage_ptr->my_name(),
357 storage_ptr -> updateString( abs_off + mmdb_pos_t(offset),
362 //////////////////////////////////////////////////////////////
363 // flip back to original. as the server will not quit after
365 //////////////////////////////////////////////////////////////
366 p -> _swap_order(true);
373 //static Boolean xflag = false;
374 /***********************************************************/
376 /***********************************************************/
378 page_storage::readString(mmdb_pos_t loc, char* base, int len, int str_offset)
381 int xstring_ofst = str_offset;
385 MESSAGE(cerr, "page_storage: readString");
386 debug(cerr, my_path());
387 debug(cerr, my_name());
389 debug(cerr, int(base));
391 debug(cerr, str_offset);
397 in_cache.set_chunk(base, len);
399 spointer_t *slot_info;
404 throw(stringException("damaged store."));
407 int page_num = PAGE_ID( loc, page_sz );
408 int page_slot = PAGE_IDX( loc, page_sz );
410 //debug(cerr, page_num);
411 //debug(cerr, page_slot);
413 page *y = (*this)(page_num, READ);
415 slot_info = y -> get_spointer(page_slot);
417 int str_leng = slot_info -> string_leng();
418 loc = slot_info -> forward_ptr();
420 MESSAGE(cerr, "slot info:");
421 debug(cerr, str_leng);
423 debug(cerr, slot_info -> string_ofst());
428 if ( str_offset >= str_leng ) {
430 str_offset -= str_leng;
433 int bytes_read = MIN(len, str_leng - str_offset);
437 debug(cerr, bytes_read);
440 y -> get( page_slot, in_cache, str_offset, bytes_read );
448 //MESSAGE(cerr, "page_storage:: readString done");
454 page_storage::get_str_ptr(mmdb_pos_t loc, char*& str,
457 int page_num = PAGE_ID( loc, page_sz );
458 int page_slot = PAGE_IDX( loc, page_sz );
461 //MESSAGE(cerr, "IN get_str_ptr()");
462 //debug(cerr, my_path());
463 //debug(cerr, my_name());
464 //debug(cerr, page_num);
465 //debug(cerr, page_slot);
468 page *y = (*this)(page_num, READ);
470 spointer_t* slot_info = y -> get_spointer(page_slot);
472 //debug(cerr, int(slot_info -> get_mode(spointer_t::DELETED)));
474 if ( page_num == 1 && page_slot == 1 ) {
475 debug(cerr, hex(slot_info -> header.int_view));
476 debug(cerr, hex(slot_info -> header.bit_view.spointer));
477 debug(cerr, hex(slot_info -> header.bit_view.length));
478 debug(cerr, hex(slot_info -> header.bit_view.deleted));
479 debug(cerr, hex(slot_info -> header.bit_view.first_recd));
480 debug(cerr, hex(slot_info -> header.bit_view.updated));
481 debug(cerr, hex(slot_info -> header.bit_view.is_object));
486 if ( slot_info -> get_mode(spointer_t::DELETED) == true ) {
488 throw(stringException("read deleted byte string"));
492 y -> get_str_ptr(page_slot, str, len);
497 int page_storage::insertString(mmdb_pos_t& loc, const char* base, int len, Boolean flush_opt)
500 cerr << "insert: len=" << len << "\n";
506 MESSAGE(cerr, "page_storage insertString");
514 int str_offset = len;
517 Boolean first_recd = true;
520 while ( str_offset > 0 ) {
522 loc = (page_num != 0 ) ?
523 FORM_PAGE_REF(page_num, page_oft, page_sz) :
526 fbytes_t* v = f_local_pcache.find_host_page(this, new_page) ;
527 page_num = v -> page_num;
529 page* y = (*this)(page_num, WRITE);
531 sec_len = MIN(len, y -> free_bytes());
533 str_offset -= sec_len;
536 temp_buf.set_chunk((char*)(base + str_offset), sec_len);
537 temp_buf.set_content_sz(sec_len);
539 y -> put( page_oft, temp_buf );
541 spointer_t *x = y -> get_spointer(page_oft);
542 x -> set_mode(spointer_t::FIRST_RECD, first_recd);
543 x -> set_forward_ptr(loc);
546 v -> free_bytes = y -> free_bytes();
547 f_local_pcache.adjust_heap(v, new_page);
549 if ( flush_opt == true ) sync(page_num);
557 MESSAGE(cerr, "FINAL LOC COMPONENT");
558 debug(cerr, page_oft);
559 debug(cerr, page_sz);
560 debug(cerr, page_num);
563 loc = FORM_PAGE_REF(page_num, page_oft, page_sz);
568 int u1 = PAGE_ID( loc, page_sz );
569 int u2 = PAGE_IDX( loc, page_sz );
570 cerr << "insert:" << page_num << "." << page_oft << " " << u3 << "\n";
578 /***********************************************************/
580 /***********************************************************/
582 page_storage::updateString(mmdb_pos_t loc, const char* base, int len,
583 int string_ofst, Boolean flush_opt)
586 int u1 = PAGE_ID( loc, page_sz );
587 int u2 = PAGE_IDX( loc, page_sz );
588 cerr << "update:" << u1 << "." << u2 << " " << len << " " << string_ofst << "\n";
593 MESSAGE(cerr, "update string");
604 while ( len > 0 && loc != 0 ) {
606 page_num = PAGE_ID( loc, page_sz );
607 slot_num = PAGE_IDX( loc, page_sz );
608 //debug(cerr, page_num);
609 //debug(cerr, slot_num);
611 y = (*this)(page_num, WRITE);
613 x = y -> get_spointer(slot_num);
616 debug(cerr, x -> forward_ptr());
617 debug(cerr, x -> string_leng());
618 debug(cerr, x -> string_ofst());
621 loc = x -> forward_ptr();
622 int this_len = x -> string_leng();
625 if ( string_ofst >= this_len ) {
626 string_ofst -= this_len;
630 int update_len = MIN(len, this_len - string_ofst);
633 sbuf.set_chunk((char*)(base+offset), update_len);
634 sbuf.set_content_sz(update_len);
636 y -> update_slot(slot_num, sbuf, string_ofst);
638 if ( flush_opt == true ) sync(page_num);
641 offset += update_len;
648 //debug(cerr, offset);
650 /*****************************/
651 // the update is an expanding
652 /*****************************/
654 insertString(new_loc, base+offset, len, flush_opt) ;
656 y = (*this)(page_num, WRITE);
657 x = y -> get_spointer(slot_num);
658 x -> set_forward_ptr(new_loc);
661 page_num = PAGE_ID( new_loc, page_sz );
662 slot_num = PAGE_IDX( new_loc, page_sz );
663 y = (*this)(page_num, WRITE);
664 x = y -> get_spointer(slot_num);
665 x -> set_mode(spointer_t::FIRST_RECD, false);
675 /*****************************/
676 // the update is a shrinking
677 /*****************************/
678 // y = (*this)(page_num);
679 // x = y -> get_spointer(slot_num);
680 // x -> set_forward_ptr(0);
681 // return deleteString(loc);
688 /***********************************************************/
690 /***********************************************************/
691 int page_storage::deleteString(mmdb_pos_t loc, Boolean flush_opt)
694 int page_num = PAGE_ID( loc, page_sz );
695 int slot_num = PAGE_IDX( loc, page_sz );
696 //debug(cerr, page_num);
697 //debug(cerr, slot_num);
699 page* y = (*this)(page_num, WRITE);
701 spointer_t *x = y -> get_spointer(slot_num);
703 if ( x -> get_mode(spointer_t::DELETED) == true )
706 loc = x -> forward_ptr();
710 y -> del_slot(slot_num);
712 if ( flush_opt == true ) sync(page_num);
718 /***********************************************************/
719 // allocate a chunk on a page.
720 /***********************************************************/
722 page_storage::allocString(mmdb_pos_t& loc, int len, char*& string_ptr, int mode)
724 //MESSAGE(cerr, "AllocString:");
725 //debug(cerr, my_name());
728 if ( len > page_sz ) {
729 MESSAGE(cerr, "allocString(): string too long");
730 throw(boundaryException(0, page_sz, len));
735 fbytes_t* v = f_local_pcache.find_host_page(this, new_page, len) ;
737 page* x = (*this)(v -> page_num, WRITE);
741 x->alloc_slot(slot_num, len, string_ptr);
743 spointer_t* slot_info = x -> get_spointer(slot_num);
744 slot_info -> add_mode(mode);
748 v -> free_bytes = x -> free_bytes();
749 f_local_pcache.adjust_heap(v, new_page);
751 loc = FORM_PAGE_REF(v -> page_num, slot_num, page_sz);
754 MESSAGE(cerr, "in allocString(): final params");
755 debug(cerr, int(x -> dirty));
756 debug(cerr, page_num);
757 debug(cerr, slot_num);
758 debug(cerr, my_name());
760 debug(cerr, int(string_ptr));
764 int u1 = PAGE_ID( loc, page_sz );
765 int u2 = PAGE_IDX( loc, page_sz );
766 //cerr << "Allocated ID=" << u1 << "." << u2 << " " << len << "\n";
772 int page_storage::appendString(mmdb_pos_t loc, const char* base, int len, Boolean)
775 int u1 = PAGE_ID( loc, page_sz );
776 int u2 = PAGE_IDX( loc, page_sz );
777 cerr << "append:" << u1 << "." << u2 << " " << len << "\n";
789 page_num = PAGE_ID( loc, page_sz );
790 slot_num = PAGE_IDX( loc, page_sz );
792 y = (*this)(page_num, READ);
793 x = y -> get_spointer(slot_num);
795 loc = x -> forward_ptr();
799 insertString(loc, base, len) ;
801 y = (*this)(page_num, WRITE);
802 x = y -> get_spointer(slot_num);
803 x -> set_forward_ptr(loc);
806 page_num = PAGE_ID( loc, page_sz );
807 slot_num = PAGE_IDX( loc, page_sz );
808 y = (*this)(page_num, WRITE);
809 x = y -> get_spointer(slot_num);
810 x -> set_mode(spointer_t::FIRST_RECD, false);
816 /***********************************************************/
817 // create new page frame.
818 /***********************************************************/
819 int page_storage::add_page_frames(int pages)
821 total_pages += pages;
823 //////////////////////////////////////
824 // prepare the new page in the cache
825 //////////////////////////////////////
826 for (int i=1; i<=pages; i++)
827 operator()(total_pages+i-pages, WRITE);
832 /***********************************************************/
833 // return the mmdb_pos_t of the first page.
834 /***********************************************************/
835 int page_storage::first() const
837 return ( total_pages > 0 ) ? 1 : 0;
840 //////////////////////////////////////////
841 /* ind should be the page id */
842 //////////////////////////////////////////
843 page* page_storage::operator()(int ind, enum access mode)
846 if ( mode == WRITE ) {
847 MESSAGE(cerr, "opera(): write mode");
854 if ( mode == WRITE ) {
855 char* s = name + strlen(name) - 11;
857 if ( strcmp(s, "index.store") == 0 )
862 //cerr << "Try to get page " << ind << " from " << my_name() << "\n";
864 if ( ! INRANGE( ind, 1, pages() ) ) {
865 debug(cerr, my_path());
866 debug(cerr, my_name());
868 form("page_storage:: operator(): mmdb_pos_t %d out of range.", ind)
870 throw(boundaryException(1, pages(), ind));
873 page* p = f_local_pcache.in_cache(this, ind);
877 //cerr << "swapping in a page " << ind << endl;
878 p = f_global_pcache.load_new_page( this, ind,
879 (v_db_order==v_server_order) ? false : true
885 debug(cerr, my_name());
886 debug(cerr, p -> count());
887 debug(cerr, int(mode));
888 debug(cerr, int(WRITE));
890 if ( mode == WRITE ) {
898 /***********************************************************/
899 // update ind to the mmdb_pos_t of next page.
900 /***********************************************************/
901 void page_storage::next(int& ind) const
903 if ( ind >= pages() )
909 io_status page_storage::asciiOut(ostream& out)
913 page* p = (*this)(ind, READ);
920 debug(cerr, pagings);
926 page_storage::seek_loc(mmdb_pos_t& loc, const direction d, int smd)
928 if ( d == positive ) {
929 return seek_loc_positive(loc, smd);
931 return seek_loc_negative(loc, smd);
935 Boolean page_storage::seek_loc_positive(mmdb_pos_t& loc, int smd)
939 int page_num = PAGE_ID( loc, page_sz );
940 int page_slot = PAGE_IDX( loc, page_sz );
942 while ( page_num <= pgs ) {
944 page* x = (*this)(page_num, READ);
946 if ( page_slot == 0 )
947 page_slot = x -> first();
949 x -> next( page_slot );
953 while ( page_slot && (y = x -> get_spointer(page_slot)) != 0 ) {
954 if ( y -> get_mode(spointer_t::DELETED) == false &&
955 y -> test_mode(smd) == true ) {
956 loc = FORM_PAGE_REF(page_num, page_slot, page_sz);
961 x -> next(page_slot);
972 Boolean page_storage::seek_loc_negative(mmdb_pos_t& loc, int smd)
974 int page_num = PAGE_ID( loc, page_sz );
975 int page_slot = PAGE_IDX( loc, page_sz );
977 while ( page_num > 0 ) {
979 page* x = (*this)(page_num, READ);
981 if ( page_slot == 0 )
982 page_slot = x -> count() - 1;
984 x -> prev(page_slot);
988 while ( page_slot && (y = x -> get_spointer(page_slot)) != 0 )
990 if ( y -> get_mode(spointer_t::DELETED) == false &&
991 y -> test_mode(smd) == true ) {
992 loc = FORM_PAGE_REF(page_num, page_slot, page_sz);
997 x -> prev(page_slot);
1008 void page_storage::reset_paging_count()
1011 if ( storage_ptr -> rdbuf() -> is_open() ) {
1012 cerr << storage_ptr -> my_name() << " has not been closed\n";
1013 storage_ptr -> close();
1015 cerr << storage_ptr -> my_name() << " is already closed\n";
1022 int page_storage::paging_count() const
1027 mmdb_pos_t page_storage::first_loc()
1029 if ( pages() >= 1 && (*this)(1, READ) -> count() != 0 )
1030 return FORM_PAGE_REF(1, 1, page_sz);
1035 mmdb_pos_t page_storage::last_loc()
1042 for ( int i=pgs; i>0; i-- ) {
1043 int ct = (*this)(i, READ) -> count();
1045 return FORM_PAGE_REF(i, ct, page_sz);
1052 page_storage::get_str_locs(mmdb_pos_t str_loc,
1053 str_index_record_tPtr*& vector, int& vector_len
1057 vector = new str_index_record_tPtr[vector_sz];
1063 while ( str_loc > 0 ) {
1065 if ( num_pieces >= vector_sz ) {
1067 vector = (str_index_record_tPtr*)realloc(
1069 vector_sz*sizeof(str_index_record_tPtr)
1073 vector[num_pieces++] =
1074 new str_index_record_t(str_offset, str_loc);
1076 int page_num = PAGE_ID( str_loc, page_sz );
1077 int page_slot = PAGE_IDX( str_loc, page_sz );
1079 page *y = (*this)(page_num, READ);
1081 x = y -> get_spointer(page_slot);
1083 str_offset += x -> string_leng();
1084 str_loc = x -> forward_ptr();
1089 vector_len = num_pieces;
1093 int page_storage::set_page_dirty(mmdb_pos_t loc)
1095 MESSAGE(cerr, "set page dirty: page loc is");
1098 page* x = (*this)(PAGE_ID( loc, page_sz ), WRITE);
1103 Boolean page_storage::io_mode(int mode)
1106 return storage_ptr -> io_mode(mode);
1111 void page_storage::begin_trans()
1114 if ( trans_info.status == store_trans::ENABLED )
1115 throw(stringException("trans is still in progress"));
1117 trans_info.init(policy);
1118 trans_info.set_max_pages(total_pages);
1120 trans_info.status = store_trans::ENABLED;
1122 int l_max_pages = trans_info.max_pages;
1123 if ( swap_order() == true )
1124 ORDER_SWAP_UINT(l_max_pages);
1126 trans_info.log_store ->
1127 updateString(0, (char*)&l_max_pages, sizeof(l_max_pages), 0, true);
1130 catch (mmdbException&, e) {
1131 // workaround for solaris's /SUNWspro/bin/CC compiler.
1132 beginTransException x;
1134 //throw(beginTransException());
1139 void page_storage::commit_trans()
1141 //////////////////////////////
1142 // sync the touched pages
1143 //////////////////////////////
1145 int ind = trans_info.log_index -> first_bucket();
1147 while ( ind != -1 ) {
1149 imp_bucket* bucket = trans_info.log_index -> get_bucket(ind);
1152 long b_ind = bucket -> first();
1153 while ( b_ind != 0 ) {
1154 data_t* z = (*bucket)(b_ind);
1155 //debug(cerr, ((page*)(z -> dt)) -> count());
1156 sync((page*)(z -> dt));
1157 bucket -> next(b_ind);
1160 trans_info.log_index -> next_bucket(ind);
1165 trans_info.status = store_trans::DISABLED;
1168 catch (mmdbException &,e) {
1169 // workaround for solaris's /SUNWspro/bin/CC compiler.
1170 commitTransException x;
1175 void page_storage::roll_back()
1179 if ( exist_file(form("%s.log", name), path) == false )
1182 MESSAGE(cerr, "roll_back() begins");
1184 trans_info.init(policy); // init the log store
1186 //////////////////////////////////
1187 // verify the log is in good shape
1188 //////////////////////////////////
1190 int log_bytes = trans_info.log_store -> bytes();
1192 if ( trans_info.log_store &&
1193 (*trans_info.log_store) &&
1194 log_bytes > sizeof(m) )
1197 //////////////////////////////////
1198 // truncate the store to previous
1200 //////////////////////////////////
1201 trans_info.log_store -> readString(0, (char*)&m, sizeof(m));
1203 if ( swap_order() == true )
1206 trans_info.set_max_pages(m); // init the log store
1208 ((unixf_storage*)storage_ptr) -> truncate(abs_off + m*page_sz);
1211 //////////////////////////////////
1212 // restore the store to previous
1214 //////////////////////////////////
1217 if ( (log_bytes - sizeof(m)) % (page_sz+sizeof(l_pid)) != 0 )
1218 throw(stringException("corrupted transaction log"));
1220 int u = (log_bytes - sizeof(m)) / (page_sz+sizeof(l_pid));
1224 buffer log_buf(page_sz);
1225 for ( int i=0; i<u; i++ ) {
1227 int offset = sizeof(m) + i*(page_sz + sizeof(l_pid));
1229 trans_info.log_store ->
1230 readString(offset, // page id
1231 (char*)&l_pid, sizeof(l_pid)
1234 if ( swap_order() == true ) // swap byte order if necessary
1235 ORDER_SWAP_UINT(l_pid);
1237 trans_info.log_store ->
1238 readString(offset + sizeof(l_pid), // page content
1244 storage_ptr -> updateString( abs_off + (l_pid-1)*page_sz,
1253 ///////////////////////////////////////////////
1254 // make sure the cached pages are not synced
1255 ///////////////////////////////////////////////
1257 long ind = f_global_pcache.f_replace_policy.first();
1259 while ( ind != 0 ) {
1260 lru_page *p = (lru_page*)
1261 (f_global_pcache.f_replace_policy)(ind, ACTIVE);
1263 if ( p -> f_store == this )
1265 f_global_pcache.f_replace_policy.next(ind);
1268 trans_info.quit(); // remove the log store
1270 trans_info.status = store_trans::DISABLED;
1273 catch (mmdbException &,e)
1275 // workaround for solaris's /SUNWspro/bin/CC compiler.
1276 rollbackTransException x;
1280 MESSAGE(cerr, "roll_back() completes");
1283 void page_storage::save_to_log(page* p)
1286 MESSAGE(cerr, "About to save to log");
1287 debug(cerr, my_name());
1288 debug(cerr, int(trans_info.status));
1289 debug(cerr, int(store_trans::ENABLED));
1290 debug(cerr, trans_info.max_pages);
1293 if ( trans_info.status == store_trans::ENABLED &&
1294 INRANGE(p -> page_id(), 1, trans_info.max_pages)
1297 //assert ( trans_info.log_store );
1298 //assert ( trans_info.log_index );
1300 if ( trans_info.log_store == 0 || trans_info.log_index == 0 )
1301 throw(stringException("corrupted store"));
1303 int l_pid = p -> page_id();
1304 data_t pkey(l_pid, voidPtr(p));
1307 if ( trans_info.log_index -> member(pkey) == false ) {
1308 //MESSAGE(cerr, form("Save_to_log pid=%d, pcnt = %d, name=%s",
1309 // l_pid, p -> count(), name));
1311 int log_bytes_before = trans_info.log_store -> bytes();
1314 if ( swap_order() == true ) // swap to desired order
1315 ORDER_SWAP_UINT(l_pid);
1317 trans_info.log_store ->
1318 appendString( 0, (char*)&l_pid, sizeof(l_pid), false );
1320 if ( swap_order() == true ) // swap back
1321 ORDER_SWAP_UINT(l_pid);
1323 p -> _swap_order(false);
1325 trans_info.log_store ->
1326 appendString( 0, p -> page_base(), page_sz, true );
1328 //debug(cerr, trans_info.log_store -> bytes());
1329 p -> _swap_order(true);
1331 trans_info.log_index -> insert(pkey);
1334 catch (mmdbException&, e) {
1335 trans_info.log_store -> truncate(log_bytes_before);
1342 //MESSAGE(cerr, form("Not save_to_log pid=%d, name=%s", l_pid, name));
1347 buffer& page_storage::aux_buf()
1350 v_buf = new buffer(LBUFSIZ);