page_storage.C 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * $XConsortium: page_storage.C /main/8 1996/10/04 10:49:57 drk $
  25. *
  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
  30. * OR DISCLOSURE.
  31. *
  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
  36. * INTERNATIONAL, LTD.
  37. *
  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.
  43. *
  44. * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
  45. * 1315 Dell Avenue
  46. * Campbell, CA 95008
  47. *
  48. */
  49. #include "storage/page.h"
  50. #include "storage/page_storage.h"
  51. #include "storage/version.h"
  52. #include "utility/db_version.h"
  53. #define db_type "MMDB"
  54. #define db_type_sz strlen(db_type)
  55. #define db_order_sz sizeof(char)
  56. int page_storage::dv_sz = 0;
  57. int page_storage::abs_off = 0;
  58. #ifndef C_API
  59. page_cache_global_part page_storage::f_global_pcache;
  60. #else
  61. page_cache_global_part* page_storage::f_global_pcache_ptr = 0;
  62. #endif
  63. static char* db_version = 0;
  64. static char* data_version = 0;
  65. str_index_record_t::str_index_record_t(int offset, mmdb_pos_t lc)
  66. : str_offset(offset), loc(lc)
  67. {
  68. }
  69. void delete_str_index_record(const void* t)
  70. {
  71. delete ((str_index_record_t*)t);
  72. }
  73. extern void_ptr_array g_store_array;
  74. extern Boolean g_transaction_on;
  75. //////////////////////////////
  76. //
  77. //////////////////////////////
  78. store_trans::store_trans(char* p, char* n, int psz) :
  79. path(p), name(n), status(DISABLED),
  80. log_store(0), log_index(0), max_pages(0), page_sz(psz)
  81. {
  82. }
  83. store_trans::~store_trans()
  84. {
  85. /*
  86. MESSAGE(cerr, "dstr store_trans object");
  87. debug(cerr, status);
  88. debug(cerr, DISABLED);
  89. debug(cerr, int(log_store));
  90. */
  91. if ( status == DISABLED && log_store ) {
  92. delete log_store;
  93. if ( exist_file(form("%s.log", name), path) )
  94. del_file(form("%s.log", name), path);
  95. }
  96. delete log_index;
  97. }
  98. void store_trans::init(rep_policy* policy)
  99. {
  100. if ( log_store == 0 ) {
  101. log_store = new unixf_storage(path, form("%s.log", name), policy);
  102. if ( ! (*log_store) )
  103. throw(streamException(log_store -> rdstate()));
  104. }
  105. if ( log_index == 0 ) {
  106. log_index = new imp_die;
  107. }
  108. }
  109. void store_trans::quit()
  110. {
  111. if ( log_store )
  112. log_store -> truncate(0);
  113. if ( log_index )
  114. log_index -> clean();
  115. }
  116. ///////////////////////////////////
  117. // Constructor
  118. ///////////////////////////////////
  119. page_storage::page_storage( char* _path, char* _name,
  120. unixf_storage* store, int pg_sz,
  121. int/*no_pages*/, mmdb_byte_order_t create_order) :
  122. abs_storage(_path, _name, PAGE_STORAGE_CODE),
  123. trans_info(page_storage::path, page_storage::name, pg_sz),
  124. page_sz(pg_sz),
  125. f_local_pcache(30),
  126. v_db_order(create_order), v_buf(0),
  127. pagings(0),
  128. total_page_access(0)
  129. {
  130. //debug(cerr, my_name());
  131. //debug(cerr, (void*)this);
  132. //#ifdef C_API
  133. if ( dv_sz == 0 ) {
  134. dv_sz = db_type_sz + mm_version::version_bytes() + db_order_sz;
  135. abs_off = dv_sz;
  136. }
  137. //#endif
  138. storage_ptr = store;
  139. int bts = ((unixf_storage*)storage_ptr) -> bytes();
  140. v_server_order = byte_order();
  141. //debug(cerr, v_server_order);
  142. if ( bts == 0 ) {
  143. //////////////////////
  144. // empty store file
  145. //////////////////////
  146. if ( db_version == 0 ) {
  147. db_version = new char[dv_sz];
  148. memcpy(db_version, db_type, db_type_sz);
  149. mm_version x(MAJOR, MINOR);
  150. x.to_byte_string(db_version+db_type_sz,
  151. (v_db_order != v_server_order) ? true : false
  152. );
  153. char z = v_db_order;
  154. memcpy(db_version+db_type_sz+mm_version::version_bytes(),
  155. &z, db_order_sz);
  156. }
  157. storage_ptr -> updateString( 0, db_version, dv_sz, 0, true);
  158. v_swap_order = (v_db_order != v_server_order) ? true : false;
  159. } else {
  160. ///////////////////
  161. // store exists.
  162. ///////////////////
  163. bts -= abs_off;
  164. if ( data_version == 0 ) {
  165. data_version = new char[dv_sz];
  166. }
  167. storage_ptr -> readString(0, data_version, dv_sz);
  168. /////////////////////////////////
  169. // "MMDB" magic number testing
  170. /////////////////////////////////
  171. if ( memcmp(data_version, db_type, db_type_sz) != 0 ) {
  172. throw(stringException(
  173. form("bad magic number. corrupted store %s/%s", _path, _name)
  174. )
  175. );
  176. }
  177. ///////////////////////////////
  178. // get db byte order
  179. ///////////////////////////////
  180. char z;
  181. memcpy(&z,
  182. data_version + db_type_sz + mm_version::version_bytes(),
  183. db_order_sz
  184. );
  185. v_db_order = int(z);
  186. if ( v_db_order != mmdb_big_endian && v_db_order != mmdb_little_endian ) {
  187. debug(cerr, v_db_order);
  188. throw(stringException(
  189. "data is in neither big endian nor little endian format"
  190. ));
  191. }
  192. ///////////////////////////////
  193. // test version
  194. ///////////////////////////////
  195. v_swap_order = (v_db_order != v_server_order) ? true : false;
  196. mm_version dv(data_version+db_type_sz, v_swap_order);
  197. f_version = dv;
  198. mm_version cv(MAJOR, MINOR);
  199. if ( cv < dv ) {
  200. cerr << "code major = " << cv.major_version() << "\n";
  201. cerr << "code minor = " << cv.minor_version() << "\n";
  202. cerr << "data major = " << dv.major_version() << "\n";
  203. cerr << "data minor = " << dv.minor_version() << "\n";
  204. throw(stringException(
  205. form("data and code version mismatch on store %s/%s", _path, _name)
  206. )
  207. );
  208. }
  209. }
  210. //debug(cerr, v_db_order);
  211. total_pages = bts / page_sz;
  212. f_local_pcache.init_heap(this);
  213. set_mode(HEALTH, true);
  214. }
  215. /***********************************************************/
  216. // Destructor
  217. /***********************************************************/
  218. page_storage::~page_storage()
  219. {
  220. //MESSAGE(cerr, "dstr page_storage");
  221. //debug(cerr, my_name());
  222. delete v_buf;
  223. delete storage_ptr;
  224. delete data_version;
  225. data_version = 0;
  226. delete db_version;
  227. db_version = 0;
  228. f_local_pcache.quit_heap(this);
  229. f_global_pcache.remove_pages(this);
  230. /*
  231. MESSAGE(cerr, my_name());
  232. debug(cerr, total_page_access);
  233. debug(cerr, pagings);
  234. debug(cerr, float(pagings)/total_page_access);
  235. */
  236. }
  237. void page_storage::remove()
  238. {
  239. storage_ptr -> remove();
  240. }
  241. void page_storage::sync()
  242. {
  243. /*
  244. MESSAGE(cerr, "page_storage::sync()");
  245. debug(cerr, my_path());
  246. debug(cerr, my_name());
  247. debug(cerr, pages());
  248. debug(cerr, int(this));
  249. */
  250. long ind = f_global_pcache.f_replace_policy.first();
  251. while ( ind != 0 ) {
  252. lru_page *p= (lru_page*)(f_global_pcache.f_replace_policy)(ind, ACTIVE);
  253. if ( p -> f_store == this )
  254. sync( p );
  255. f_global_pcache.f_replace_policy.next(ind);
  256. }
  257. //MESSAGE(cerr, "page_storage::sync() done");
  258. }
  259. void page_storage::sync( int page_num )
  260. {
  261. sync((*this)(page_num, READ));
  262. }
  263. void page_storage::sync( page* p )
  264. {
  265. if ( p == 0 || p -> page_id() <= 0 ) {
  266. throw(stringException("null page pointer"));
  267. }
  268. if ( p -> dirty == true ) {
  269. //cerr << "dirty PAGE swapped out " << p -> page_id();
  270. //cerr << " " << my_name() << "\n";
  271. int offset = ( p -> page_id() - 1 ) * page_sz ;
  272. #ifdef PORTABLE_DB
  273. p -> _swap_order(false);
  274. #endif
  275. //debug(cerr, *p);
  276. #ifdef DEBUG
  277. fprintf(stderr, "purging page at %p size=%d into %s/%s @ %s:%d\n",
  278. p -> page_base(), page_sz,
  279. storage_ptr->my_path(), storage_ptr->my_name(),
  280. __FILE__, __LINE__);
  281. #endif
  282. storage_ptr -> updateString( abs_off + mmdb_pos_t(offset),
  283. p -> page_base(),
  284. page_sz, 0, true
  285. );
  286. #ifdef PORTABLE_DB
  287. //////////////////////////////////////////////////////////////
  288. // flip back to original. as the server will not quit after
  289. // the sync.
  290. //////////////////////////////////////////////////////////////
  291. p -> _swap_order(true);
  292. #endif
  293. p -> dirty = false;
  294. }
  295. }
  296. //static Boolean xflag = false;
  297. /***********************************************************/
  298. // readString().
  299. /***********************************************************/
  300. int
  301. page_storage::readString(mmdb_pos_t loc, char* base, int len, int str_offset)
  302. {
  303. /*
  304. int xstring_ofst = str_offset;
  305. int xloc = loc;
  306. int xlen = len;
  307. MESSAGE(cerr, "page_storage: readString");
  308. debug(cerr, my_path());
  309. debug(cerr, my_name());
  310. debug(cerr, loc);
  311. debug(cerr, int(base));
  312. debug(cerr, len);
  313. debug(cerr, str_offset);
  314. */
  315. buffer in_cache(0);
  316. in_cache.set_chunk(base, len);
  317. spointer_t *slot_info;
  318. while ( len > 0 ) {
  319. if ( loc == 0 ) {
  320. throw(stringException("damaged store."));
  321. }
  322. int page_num = PAGE_ID( loc, page_sz );
  323. int page_slot = PAGE_IDX( loc, page_sz );
  324. //debug(cerr, page_num);
  325. //debug(cerr, page_slot);
  326. page *y = (*this)(page_num, READ);
  327. slot_info = y -> get_spointer(page_slot);
  328. int str_leng = slot_info -> string_leng();
  329. loc = slot_info -> forward_ptr();
  330. /*
  331. MESSAGE(cerr, "slot info:");
  332. debug(cerr, str_leng);
  333. debug(cerr, loc);
  334. debug(cerr, slot_info -> string_ofst());
  335. */
  336. delete slot_info;
  337. if ( str_offset >= str_leng ) {
  338. str_offset -= str_leng;
  339. } else {
  340. int bytes_read = MIN(len, str_leng - str_offset);
  341. /*
  342. debug(cerr, len);
  343. debug(cerr, bytes_read);
  344. */
  345. y -> get( page_slot, in_cache, str_offset, bytes_read );
  346. len -= bytes_read;
  347. str_offset = 0;
  348. }
  349. }
  350. //MESSAGE(cerr, "page_storage:: readString done");
  351. return 0;
  352. }
  353. int
  354. page_storage::get_str_ptr(mmdb_pos_t loc, char*& str,
  355. int& len)
  356. {
  357. int page_num = PAGE_ID( loc, page_sz );
  358. int page_slot = PAGE_IDX( loc, page_sz );
  359. //MESSAGE(cerr, "IN get_str_ptr()");
  360. //debug(cerr, my_path());
  361. //debug(cerr, my_name());
  362. //debug(cerr, page_num);
  363. //debug(cerr, page_slot);
  364. page *y = (*this)(page_num, READ);
  365. spointer_t* slot_info = y -> get_spointer(page_slot);
  366. //debug(cerr, int(slot_info -> get_mode(spointer_t::DELETED)));
  367. /*
  368. if ( page_num == 1 && page_slot == 1 ) {
  369. debug(cerr, hex(slot_info -> header.int_view));
  370. debug(cerr, hex(slot_info -> header.bit_view.spointer));
  371. debug(cerr, hex(slot_info -> header.bit_view.length));
  372. debug(cerr, hex(slot_info -> header.bit_view.deleted));
  373. debug(cerr, hex(slot_info -> header.bit_view.first_recd));
  374. debug(cerr, hex(slot_info -> header.bit_view.updated));
  375. debug(cerr, hex(slot_info -> header.bit_view.is_object));
  376. }
  377. */
  378. if ( slot_info -> get_mode(spointer_t::DELETED) == true ) {
  379. delete slot_info;
  380. throw(stringException("read deleted byte string"));
  381. }
  382. delete slot_info;
  383. y -> get_str_ptr(page_slot, str, len);
  384. return 0;
  385. }
  386. int page_storage::insertString(mmdb_pos_t& loc, const char* base, int len, Boolean flush_opt)
  387. {
  388. /*
  389. cerr << "insert: len=" << len << "\n";
  390. int u3 = len;
  391. */
  392. #ifdef STORAGE_DEBUG
  393. MESSAGE(cerr, "page_storage insertString");
  394. debug(cerr, len);
  395. #endif
  396. buffer temp_buf(0);
  397. int page_num = 0;
  398. int page_oft = 0;
  399. int str_offset = len;
  400. int sec_len;
  401. Boolean first_recd = true;
  402. Boolean new_page;
  403. while ( str_offset > 0 ) {
  404. loc = (page_num != 0 ) ?
  405. FORM_PAGE_REF(page_num, page_oft, page_sz) :
  406. 0;
  407. fbytes_t* v = f_local_pcache.find_host_page(this, new_page) ;
  408. page_num = v -> page_num;
  409. page* y = (*this)(page_num, WRITE);
  410. sec_len = MIN(len, y -> free_bytes());
  411. str_offset -= sec_len;
  412. temp_buf.set_chunk((char*)(base + str_offset), sec_len);
  413. temp_buf.set_content_sz(sec_len);
  414. y -> put( page_oft, temp_buf );
  415. spointer_t *x = y -> get_spointer(page_oft);
  416. x -> set_mode(spointer_t::FIRST_RECD, first_recd);
  417. x -> set_forward_ptr(loc);
  418. delete x;
  419. v -> free_bytes = y -> free_bytes();
  420. f_local_pcache.adjust_heap(v, new_page);
  421. if ( flush_opt == true ) sync(page_num);
  422. first_recd = false;
  423. len -= sec_len;
  424. }
  425. #ifdef STORAGE_DEBUG
  426. MESSAGE(cerr, "FINAL LOC COMPONENT");
  427. debug(cerr, page_oft);
  428. debug(cerr, page_sz);
  429. debug(cerr, page_num);
  430. #endif
  431. loc = FORM_PAGE_REF(page_num, page_oft, page_sz);
  432. /*
  433. int u1 = PAGE_ID( loc, page_sz );
  434. int u2 = PAGE_IDX( loc, page_sz );
  435. cerr << "insert:" << page_num << "." << page_oft << " " << u3 << "\n";
  436. */
  437. return 0;
  438. }
  439. /***********************************************************/
  440. // updateString().
  441. /***********************************************************/
  442. int
  443. page_storage::updateString(mmdb_pos_t loc, const char* base, int len,
  444. int string_ofst, Boolean flush_opt)
  445. {
  446. /*
  447. int u1 = PAGE_ID( loc, page_sz );
  448. int u2 = PAGE_IDX( loc, page_sz );
  449. cerr << "update:" << u1 << "." << u2 << " " << len << " " << string_ofst << "\n";
  450. */
  451. /*
  452. MESSAGE(cerr, "update string");
  453. debug(cerr, name);
  454. debug(cerr, loc);
  455. */
  456. int page_num =0;
  457. int slot_num =0;
  458. int offset = 0;
  459. page* y = 0;
  460. spointer_t *x = 0;
  461. while ( len > 0 && loc != 0 ) {
  462. page_num = PAGE_ID( loc, page_sz );
  463. slot_num = PAGE_IDX( loc, page_sz );
  464. //debug(cerr, page_num);
  465. //debug(cerr, slot_num);
  466. y = (*this)(page_num, WRITE);
  467. x = y -> get_spointer(slot_num);
  468. /*
  469. debug(cerr, x -> forward_ptr());
  470. debug(cerr, x -> string_leng());
  471. debug(cerr, x -> string_ofst());
  472. */
  473. loc = x -> forward_ptr();
  474. int this_len = x -> string_leng();
  475. delete x;
  476. if ( string_ofst >= this_len ) {
  477. string_ofst -= this_len;
  478. continue;
  479. }
  480. int update_len = MIN(len, this_len - string_ofst);
  481. buffer sbuf(0);
  482. sbuf.set_chunk((char*)(base+offset), update_len);
  483. sbuf.set_content_sz(update_len);
  484. y -> update_slot(slot_num, sbuf, string_ofst);
  485. if ( flush_opt == true ) sync(page_num);
  486. string_ofst = 0;
  487. offset += update_len;
  488. len -= update_len;
  489. }
  490. if ( len > 0 ) {
  491. //debug(cerr, len);
  492. //debug(cerr, offset);
  493. /*****************************/
  494. // the update is an expanding
  495. /*****************************/
  496. mmdb_pos_t new_loc;
  497. insertString(new_loc, base+offset, len, flush_opt) ;
  498. y = (*this)(page_num, WRITE);
  499. x = y -> get_spointer(slot_num);
  500. x -> set_forward_ptr(new_loc);
  501. delete x;
  502. page_num = PAGE_ID( new_loc, page_sz );
  503. slot_num = PAGE_IDX( new_loc, page_sz );
  504. y = (*this)(page_num, WRITE);
  505. x = y -> get_spointer(slot_num);
  506. x -> set_mode(spointer_t::FIRST_RECD, false);
  507. delete x;
  508. y -> dirty = true;
  509. return 0;
  510. }
  511. // if ( loc != 0 ) {
  512. /*****************************/
  513. // the update is a shrinking
  514. /*****************************/
  515. // y = (*this)(page_num);
  516. // x = y -> get_spointer(slot_num);
  517. // x -> set_forward_ptr(0);
  518. // return deleteString(loc);
  519. // }
  520. return 0;
  521. }
  522. /***********************************************************/
  523. // deleteString().
  524. /***********************************************************/
  525. int page_storage::deleteString(mmdb_pos_t loc, Boolean flush_opt)
  526. {
  527. while ( loc != 0 ) {
  528. int page_num = PAGE_ID( loc, page_sz );
  529. int slot_num = PAGE_IDX( loc, page_sz );
  530. //debug(cerr, page_num);
  531. //debug(cerr, slot_num);
  532. page* y = (*this)(page_num, WRITE);
  533. spointer_t *x = y -> get_spointer(slot_num);
  534. if ( x -> get_mode(spointer_t::DELETED) == true ) {
  535. delete x;
  536. return 0;
  537. }
  538. loc = x -> forward_ptr();
  539. //debug(cerr, loc);
  540. delete x;
  541. y -> del_slot(slot_num);
  542. if ( flush_opt == true ) sync(page_num);
  543. }
  544. return 0;
  545. }
  546. /***********************************************************/
  547. // allocate a chunk on a page.
  548. /***********************************************************/
  549. int
  550. page_storage::allocString(mmdb_pos_t& loc, int len, char*& string_ptr, int mode)
  551. {
  552. //MESSAGE(cerr, "AllocString:");
  553. //debug(cerr, my_name());
  554. //debug(cerr, len);
  555. if ( len > page_sz ) {
  556. MESSAGE(cerr, "allocString(): string too long");
  557. throw(boundaryException(0, page_sz, len));
  558. }
  559. Boolean new_page;
  560. fbytes_t* v = f_local_pcache.find_host_page(this, new_page, len) ;
  561. page* x = (*this)(v -> page_num, WRITE);
  562. int slot_num;
  563. x->alloc_slot(slot_num, len, string_ptr);
  564. spointer_t* slot_info = x -> get_spointer(slot_num);
  565. slot_info -> add_mode(mode);
  566. delete slot_info;
  567. v -> free_bytes = x -> free_bytes();
  568. f_local_pcache.adjust_heap(v, new_page);
  569. loc = FORM_PAGE_REF(v -> page_num, slot_num, page_sz);
  570. #ifdef STORAGE_DEBUG
  571. MESSAGE(cerr, "in allocString(): final params");
  572. debug(cerr, int(x -> dirty));
  573. debug(cerr, page_num);
  574. debug(cerr, slot_num);
  575. debug(cerr, my_name());
  576. debug(cerr, loc);
  577. debug(cerr, int(string_ptr));
  578. #endif
  579. // int u1 = PAGE_ID( loc, page_sz );
  580. // int u2 = PAGE_IDX( loc, page_sz );
  581. // cerr << "Allocated ID=" << u1 << "." << u2 << " " << len << "\n";
  582. return 0;
  583. }
  584. int page_storage::appendString(mmdb_pos_t loc, const char* base, int len, Boolean)
  585. {
  586. /*
  587. int u1 = PAGE_ID( loc, page_sz );
  588. int u2 = PAGE_IDX( loc, page_sz );
  589. cerr << "append:" << u1 << "." << u2 << " " << len << "\n";
  590. */
  591. int page_num = 0;
  592. int slot_num = 0;
  593. page* y;
  594. spointer_t *x;
  595. while ( loc != 0 ) {
  596. page_num = PAGE_ID( loc, page_sz );
  597. slot_num = PAGE_IDX( loc, page_sz );
  598. y = (*this)(page_num, READ);
  599. x = y -> get_spointer(slot_num);
  600. loc = x -> forward_ptr();
  601. delete x;
  602. }
  603. insertString(loc, base, len) ;
  604. y = (*this)(page_num, WRITE);
  605. x = y -> get_spointer(slot_num);
  606. x -> set_forward_ptr(loc);
  607. delete x;
  608. page_num = PAGE_ID( loc, page_sz );
  609. slot_num = PAGE_IDX( loc, page_sz );
  610. y = (*this)(page_num, WRITE);
  611. x = y -> get_spointer(slot_num);
  612. x -> set_mode(spointer_t::FIRST_RECD, false);
  613. delete x;
  614. return 0;
  615. }
  616. /***********************************************************/
  617. // create new page frame.
  618. /***********************************************************/
  619. int page_storage::add_page_frames(int pages)
  620. {
  621. total_pages += pages;
  622. //////////////////////////////////////
  623. // prepare the new page in the cache
  624. //////////////////////////////////////
  625. for (int i=1; i<=pages; i++)
  626. operator()(total_pages+i-pages, WRITE);
  627. return 0;
  628. }
  629. /***********************************************************/
  630. // return the mmdb_pos_t of the first page.
  631. /***********************************************************/
  632. int page_storage::first() const
  633. {
  634. return ( total_pages > 0 ) ? 1 : 0;
  635. }
  636. //////////////////////////////////////////
  637. /* ind should be the page id */
  638. //////////////////////////////////////////
  639. page* page_storage::operator()(int ind, enum access mode)
  640. {
  641. /*
  642. if ( mode == WRITE ) {
  643. MESSAGE(cerr, "opera(): write mode");
  644. debug(cerr, ind);
  645. debug(cerr, name);
  646. }
  647. */
  648. /*
  649. if ( mode == WRITE ) {
  650. char* s = name + strlen(name) - 11;
  651. debug(cerr, s);
  652. if ( strcmp(s, "index.store") == 0 )
  653. debug(cerr, name);
  654. }
  655. */
  656. //cerr << "Try to get page " << ind << " from " << my_name() << "\n";
  657. if ( ! INRANGE( ind, 1, pages() ) ) {
  658. debug(cerr, my_path());
  659. debug(cerr, my_name());
  660. MESSAGE(cerr,
  661. form("page_storage:: operator(): mmdb_pos_t %d out of range.", ind)
  662. );
  663. throw(boundaryException(1, pages(), ind));
  664. }
  665. page* p = f_local_pcache.in_cache(this, ind);
  666. if ( p == 0 ) {
  667. //cerr << "swapping in a page " << ind << endl;
  668. p = f_global_pcache.load_new_page( this, ind,
  669. (v_db_order==v_server_order) ? false : true
  670. );
  671. }
  672. /*
  673. debug(cerr, my_name());
  674. debug(cerr, p -> count());
  675. debug(cerr, int(mode));
  676. debug(cerr, int(WRITE));
  677. */
  678. if ( mode == WRITE ) {
  679. p -> dirty = true;
  680. save_to_log(p);
  681. }
  682. return p;
  683. }
  684. /***********************************************************/
  685. // update ind to the mmdb_pos_t of next page.
  686. /***********************************************************/
  687. void page_storage::next(int& ind) const
  688. {
  689. if ( ind >= pages() )
  690. ind = 0;
  691. else
  692. ind++;
  693. }
  694. io_status page_storage::asciiOut(ostream& out)
  695. {
  696. int ind = first();
  697. while ( ind != 0 ) {
  698. #ifdef DEBUG
  699. page* p = (*this)(ind, READ);
  700. debug(out, *p);
  701. #endif
  702. next(ind);
  703. }
  704. return done;
  705. /*
  706. debug(cerr, pagings);
  707. pagings = 0;
  708. */
  709. }
  710. Boolean
  711. page_storage::seek_loc(mmdb_pos_t& loc, const direction d, int smd)
  712. {
  713. if ( d == positive ) {
  714. return seek_loc_positive(loc, smd);
  715. } else {
  716. return seek_loc_negative(loc, smd);
  717. }
  718. }
  719. Boolean page_storage::seek_loc_positive(mmdb_pos_t& loc, int smd)
  720. {
  721. int pgs = pages();
  722. int page_num = PAGE_ID( loc, page_sz );
  723. int page_slot = PAGE_IDX( loc, page_sz );
  724. while ( page_num <= pgs ) {
  725. page* x = (*this)(page_num, READ);
  726. if ( page_slot == 0 )
  727. page_slot = x -> first();
  728. else
  729. x -> next( page_slot );
  730. spointer_t *y;
  731. while ( page_slot && (y = x -> get_spointer(page_slot)) != 0 ) {
  732. if ( y -> get_mode(spointer_t::DELETED) == false &&
  733. y -> test_mode(smd) == true ) {
  734. loc = FORM_PAGE_REF(page_num, page_slot, page_sz);
  735. delete y;
  736. return true;
  737. } else {
  738. delete y;
  739. x -> next(page_slot);
  740. }
  741. }
  742. page_num++;
  743. page_slot = 0;
  744. }
  745. return false;
  746. }
  747. Boolean page_storage::seek_loc_negative(mmdb_pos_t& loc, int smd)
  748. {
  749. int page_num = PAGE_ID( loc, page_sz );
  750. int page_slot = PAGE_IDX( loc, page_sz );
  751. while ( page_num > 0 ) {
  752. page* x = (*this)(page_num, READ);
  753. if ( page_slot == 0 )
  754. page_slot = x -> count() - 1;
  755. else
  756. x -> prev(page_slot);
  757. spointer_t *y;
  758. while ( page_slot && (y = x -> get_spointer(page_slot)) != 0 )
  759. {
  760. if ( y -> get_mode(spointer_t::DELETED) == false &&
  761. y -> test_mode(smd) == true ) {
  762. loc = FORM_PAGE_REF(page_num, page_slot, page_sz);
  763. delete y;
  764. return true;
  765. } else {
  766. delete y;
  767. x -> prev(page_slot);
  768. }
  769. }
  770. page_num--;
  771. page_slot = 0;
  772. }
  773. return false;
  774. }
  775. void page_storage::reset_paging_count()
  776. {
  777. /*
  778. if ( storage_ptr -> rdbuf() -> is_open() ) {
  779. cerr << storage_ptr -> my_name() << " has not been closed\n";
  780. storage_ptr -> close();
  781. } else {
  782. cerr << storage_ptr -> my_name() << " is already closed\n";
  783. }
  784. */
  785. pagings = 0;
  786. }
  787. int page_storage::paging_count() const
  788. {
  789. return pagings;
  790. }
  791. mmdb_pos_t page_storage::first_loc()
  792. {
  793. if ( pages() >= 1 && (*this)(1, READ) -> count() != 0 )
  794. return FORM_PAGE_REF(1, 1, page_sz);
  795. else
  796. return 0;
  797. }
  798. mmdb_pos_t page_storage::last_loc()
  799. {
  800. int pgs = pages();
  801. if ( pgs == 0 )
  802. return 0;
  803. for ( int i=pgs; i>0; i-- ) {
  804. int ct = (*this)(i, READ) -> count();
  805. if ( ct > 0 )
  806. return FORM_PAGE_REF(i, ct, page_sz);
  807. }
  808. return 0;
  809. }
  810. int
  811. page_storage::get_str_locs(mmdb_pos_t str_loc,
  812. str_index_record_tPtr*& vector, int& vector_len
  813. )
  814. {
  815. int vector_sz = 20;
  816. vector = new str_index_record_tPtr[vector_sz];
  817. int num_pieces = 0;
  818. int str_offset = 0;
  819. spointer_t *x = 0;
  820. while ( str_loc > 0 ) {
  821. if ( num_pieces >= vector_sz ) {
  822. vector_sz *= 2;
  823. vector = (str_index_record_tPtr*)realloc(
  824. (char*)vector,
  825. vector_sz*sizeof(str_index_record_tPtr)
  826. );
  827. }
  828. vector[num_pieces++] =
  829. new str_index_record_t(str_offset, str_loc);
  830. int page_num = PAGE_ID( str_loc, page_sz );
  831. int page_slot = PAGE_IDX( str_loc, page_sz );
  832. page *y = (*this)(page_num, READ);
  833. x = y -> get_spointer(page_slot);
  834. str_offset += x -> string_leng();
  835. str_loc = x -> forward_ptr();
  836. delete x;
  837. }
  838. vector_len = num_pieces;
  839. return 0;
  840. }
  841. int page_storage::set_page_dirty(mmdb_pos_t loc)
  842. {
  843. MESSAGE(cerr, "set page dirty: page loc is");
  844. debug(cerr, loc);
  845. page* x = (*this)(PAGE_ID( loc, page_sz ), WRITE);
  846. x -> dirty = true;
  847. return 0;
  848. }
  849. Boolean page_storage::io_mode(int mode)
  850. {
  851. if ( storage_ptr )
  852. return storage_ptr -> io_mode(mode);
  853. else
  854. return false;
  855. }
  856. void page_storage::begin_trans()
  857. {
  858. mtry {
  859. if ( trans_info.status == store_trans::ENABLED )
  860. throw(stringException("trans is still in progress"));
  861. trans_info.init(policy);
  862. trans_info.set_max_pages(total_pages);
  863. trans_info.status = store_trans::ENABLED;
  864. int l_max_pages = trans_info.max_pages;
  865. if ( swap_order() == true )
  866. ORDER_SWAP_UINT(l_max_pages);
  867. trans_info.log_store ->
  868. updateString(0, (char*)&l_max_pages, sizeof(l_max_pages), 0, true);
  869. }
  870. mcatch (mmdbException&, e) {
  871. // workaround for solaris's /SUNWspro/bin/CC compiler.
  872. beginTransException x;
  873. throw(x);
  874. //throw(beginTransException());
  875. }
  876. end_try;
  877. }
  878. void page_storage::commit_trans()
  879. {
  880. //////////////////////////////
  881. // sync the touched pages
  882. //////////////////////////////
  883. mtry {
  884. int ind = trans_info.log_index -> first_bucket();
  885. while ( ind != -1 ) {
  886. imp_bucket* bucket = trans_info.log_index -> get_bucket(ind);
  887. if ( bucket ) {
  888. long b_ind = bucket -> first();
  889. while ( b_ind != 0 ) {
  890. data_t* z = (*bucket)(b_ind);
  891. //debug(cerr, ((page*)(z -> dt)) -> count());
  892. sync((page*)(z -> dt));
  893. bucket -> next(b_ind);
  894. }
  895. }
  896. trans_info.log_index -> next_bucket(ind);
  897. }
  898. trans_info.quit();
  899. trans_info.status = store_trans::DISABLED;
  900. }
  901. mcatch (mmdbException &,e) {
  902. // workaround for solaris's /SUNWspro/bin/CC compiler.
  903. commitTransException x;
  904. throw(x);
  905. } end_try;
  906. }
  907. void page_storage::roll_back()
  908. {
  909. mtry
  910. {
  911. if ( exist_file(form("%s.log", name), path) == false )
  912. return;
  913. MESSAGE(cerr, "roll_back() begins");
  914. trans_info.init(policy); // init the log store
  915. //////////////////////////////////
  916. // verify the log is in good shape
  917. //////////////////////////////////
  918. int m;
  919. unsigned int log_bytes = trans_info.log_store -> bytes();
  920. if ( trans_info.log_store &&
  921. (*trans_info.log_store) &&
  922. log_bytes > sizeof(m) )
  923. {
  924. //////////////////////////////////
  925. // truncate the store to previous
  926. // length
  927. //////////////////////////////////
  928. trans_info.log_store -> readString(0, (char*)&m, sizeof(m));
  929. if ( swap_order() == true )
  930. ORDER_SWAP_UINT(m);
  931. trans_info.set_max_pages(m); // init the log store
  932. ((unixf_storage*)storage_ptr) -> truncate(abs_off + m*page_sz);
  933. //debug(cerr, m);
  934. //////////////////////////////////
  935. // restore the store to previous
  936. // state
  937. //////////////////////////////////
  938. int l_pid = 0;
  939. if ( (log_bytes - sizeof(m)) % (page_sz+sizeof(l_pid)) != 0 )
  940. throw(stringException("corrupted transaction log"));
  941. int u = (log_bytes - sizeof(m)) / (page_sz+sizeof(l_pid));
  942. //debug(cerr, u);
  943. buffer log_buf(page_sz);
  944. for ( int i=0; i<u; i++ ) {
  945. int offset = sizeof(m) + i*(page_sz + sizeof(l_pid));
  946. trans_info.log_store ->
  947. readString(offset, // page id
  948. (char*)&l_pid, sizeof(l_pid)
  949. );
  950. if ( swap_order() == true ) // swap byte order if necessary
  951. ORDER_SWAP_UINT(l_pid);
  952. trans_info.log_store ->
  953. readString(offset + sizeof(l_pid), // page content
  954. log_buf.get_base(),
  955. page_sz
  956. );
  957. storage_ptr -> updateString( abs_off + (l_pid-1)*page_sz,
  958. log_buf.get_base(),
  959. page_sz,
  960. 0,
  961. true
  962. );
  963. }
  964. }
  965. ///////////////////////////////////////////////
  966. // make sure the cached pages are not synced
  967. ///////////////////////////////////////////////
  968. long ind = f_global_pcache.f_replace_policy.first();
  969. while ( ind != 0 ) {
  970. lru_page *p = (lru_page*)
  971. (f_global_pcache.f_replace_policy)(ind, ACTIVE);
  972. if ( p -> f_store == this )
  973. p -> dirty = false;
  974. f_global_pcache.f_replace_policy.next(ind);
  975. }
  976. trans_info.quit(); // remove the log store
  977. trans_info.status = store_trans::DISABLED;
  978. }
  979. mcatch (mmdbException &,e)
  980. {
  981. // workaround for solaris's /SUNWspro/bin/CC compiler.
  982. rollbackTransException x;
  983. throw(x);
  984. } end_try;
  985. MESSAGE(cerr, "roll_back() completes");
  986. }
  987. void page_storage::save_to_log(page* p)
  988. {
  989. /*
  990. MESSAGE(cerr, "About to save to log");
  991. debug(cerr, my_name());
  992. debug(cerr, int(trans_info.status));
  993. debug(cerr, int(store_trans::ENABLED));
  994. debug(cerr, trans_info.max_pages);
  995. */
  996. if ( trans_info.status == store_trans::ENABLED &&
  997. INRANGE(p -> page_id(), 1, trans_info.max_pages)
  998. )
  999. {
  1000. //assert ( trans_info.log_store );
  1001. //assert ( trans_info.log_index );
  1002. if ( trans_info.log_store == 0 || trans_info.log_index == 0 )
  1003. throw(stringException("corrupted store"));
  1004. int l_pid = p -> page_id();
  1005. data_t pkey(l_pid, voidPtr(p));
  1006. if ( trans_info.log_index -> member(pkey) == false ) {
  1007. //MESSAGE(cerr, form("Save_to_log pid=%d, pcnt = %d, name=%s",
  1008. // l_pid, p -> count(), name));
  1009. int log_bytes_before = trans_info.log_store -> bytes();
  1010. mtry {
  1011. if ( swap_order() == true ) // swap to desired order
  1012. ORDER_SWAP_UINT(l_pid);
  1013. trans_info.log_store ->
  1014. appendString( 0, (char*)&l_pid, sizeof(l_pid), false );
  1015. if ( swap_order() == true ) // swap back
  1016. ORDER_SWAP_UINT(l_pid);
  1017. p -> _swap_order(false);
  1018. trans_info.log_store ->
  1019. appendString( 0, p -> page_base(), page_sz, true );
  1020. //debug(cerr, trans_info.log_store -> bytes());
  1021. p -> _swap_order(true);
  1022. trans_info.log_index -> insert(pkey);
  1023. }
  1024. mcatch (mmdbException&, e) {
  1025. trans_info.log_store -> truncate(log_bytes_before);
  1026. rethrow;
  1027. }
  1028. end_try;
  1029. }
  1030. // else
  1031. //MESSAGE(cerr, form("Not save_to_log pid=%d, name=%s", l_pid, name));
  1032. }
  1033. }
  1034. buffer& page_storage::aux_buf()
  1035. {
  1036. if ( v_buf == 0 )
  1037. v_buf = new buffer(LBUFSIZ);
  1038. return *v_buf;
  1039. }