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.cc /main/6 1996/08/15 14:14:45 cde-hal $
26 * Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
27 * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
28 * States. Use of a copyright notice is precautionary only and does not
29 * imply publication or disclosure.
31 * This software contains confidential information and trade secrets of HaL
32 * Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
33 * without the prior express written permission of HaL Computer Systems, Inc.
35 * RESTRICTED RIGHTS LEGEND
36 * Use, duplication, or disclosure by the Government is subject to
37 * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
38 * Technical Data and Computer Software clause at DFARS 252.227-7013.
39 * HaL Computer Systems, Inc.
40 * 1315 Dell Avenue, Campbell, CA 95008
45 #include "storage/page.h"
48 /////////////////////////////////////////////////////////////
49 // SLOT_HEADER_SIZE is defined for these fields:
50 //(sizeof(fwd_ptr) + sizeof(header.int_view) + sizeof(int))
52 // Note: the last int field is not used. It is here for
53 // backward compatibility. qfc 12-13-95
54 /////////////////////////////////////////////////////////////
56 #define SLOT_HEADER_SIZE (sizeof(mmdb_pos_t) + sizeof(unsigned int) + sizeof(int))
58 spointer_t::spointer_t(char* page_base, int slot): swapped(false)
60 page_image = page_base + sizeof(count_t) + (slot-1)*SLOT_HEADER_SIZE;
62 memcpy((char*)&fwd_ptr, page_image, sizeof(fwd_ptr));
64 (char*)&header.int_view,
65 page_image+sizeof(fwd_ptr),
66 sizeof(header.int_view)
69 MESSAGE(cerr, "spointer_t::spointer_t() [1]");
71 debug(cerr, (int)(void*)page_base);
72 debug(cerr, (int)(void*)page_image);
77 spointer_t::spointer_t(char* page_base, int slot_num, int ofst, int len) :
78 fwd_ptr(0), swapped(false)
80 header.bit_view.spointer = ofst;
81 header.bit_view.length = len;
83 set_mode(DELETED, false);
84 set_mode(IS_OBJECT, false);
86 set_mode(UPDATED, true);
88 page_image = page_base + sizeof(count_t) + (slot_num-1) * SLOT_HEADER_SIZE;
91 spointer_t::~spointer_t()
94 //MESSAGE(cerr, "spointer_t::~spointer_t()");
95 //debug(cerr, header.bit_view.spointer);
97 if ( swapped == true || get_mode(UPDATED) == true ) {
98 memcpy(page_image, (char*)&fwd_ptr, sizeof(fwd_ptr));
99 memcpy(page_image+sizeof(fwd_ptr),
100 (char*)&(header.int_view),
101 sizeof(header.int_view)
106 void spointer_t::set_mode(spointer_mode m, Boolean b)
110 header.bit_view.is_object = ( b == true ) ? 1 : 0;
111 header.bit_view.updated = 1;
114 header.bit_view.first_recd = ( b == true ) ? 1 : 0;
115 header.bit_view.updated = 1;
118 header.bit_view.deleted = ( b == true ) ? 1 : 0;
119 header.bit_view.updated = 1;
122 header.bit_view.updated = ( b == true ) ? 1 : 0;
125 MESSAGE(cerr, "page::set_mode(): invalid mode");
126 throw( intException((int)m) );
132 Boolean spointer_t::get_mode(spointer_mode m)
136 return ( header.bit_view.is_object == 1 ) ? true : false;
138 return ( header.bit_view.first_recd == 1 ) ? true : false;
140 return ( header.bit_view.deleted == 1 ) ? true : false;
142 return ( header.bit_view.updated == 1 ) ? true : false;
144 MESSAGE(cerr, "page::get_mode(): invalid mode");
145 throw( intException((int)m) );
151 static int align_offset;
153 page::page(int buf_sz, int pid, Boolean swap_order) :
154 buffer( buf_sz ), pageid(pid), dirty(false), num_locks(0),
155 v_swap_order(swap_order)
157 v_memalign_offset = align_offset;
163 align_offset = v_memalign_offset;
167 /***************************/
169 /***************************/
170 void page::clean_all()
172 v_eptr = v_base + buf_sz();
175 //////////////////////////////////////////
176 // use spointer_t's dstr to write slot info to page.
177 //////////////////////////////////////////
178 spointer_t x(v_base, 1,
179 buf_sz(), buf_sz()-sizeof(count_t)-2*SLOT_HEADER_SIZE
184 /*************************************
185 * Get the ith string pointer from the
187 **************************************/
188 spointer_t* page::get_spointer(int slot_num) const
190 if ( !INRANGE(slot_num, 1, count()) ) {
191 throw( boundaryException(1, count(), slot_num));
194 return new spointer_t(v_base, slot_num);
198 //////////////////////////////
199 // Get a string from the page.
200 //////////////////////////////
202 page::get( int slot_num, buffer& target,
203 int offset, int bytes_to_read
208 MESSAGE(cerr, "in page::get()");
209 debug(cerr, slot_num);
211 debug(cerr, bytes_to_read);
214 if ( ! INRANGE(slot_num, 1, count()-1) )
215 throw( boundaryException(1, count()-1, slot_num) );
218 spointer_t slot_info(v_base, slot_num);
220 if ( slot_info.get_mode(spointer_t::DELETED) == true ) {
221 MESSAGE(cerr, "page::get(): get a deleted slot");
225 int string_len = slot_info.string_leng();
226 //debug(cerr, string_len);
228 if ( bytes_to_read == 0 )
229 bytes_to_read = string_len;
231 //debug(cerr, bytes_to_read);
233 if ( bytes_to_read + offset > slot_info.string_leng() ) {
234 MESSAGE(cerr, "page::get(): too many bytes to read");
235 throw( boundaryException(0, slot_info.string_leng(),
236 bytes_to_read + offset)
240 offset += slot_info.string_ofst();
244 MESSAGE(cerr, "page::get()");
246 debug(cerr, long(v_base + offset));
247 debug(cerr, bytes_to_read);
249 for (int ki=0; ki<bytes_to_read; ki++)
250 cerr << int(v_base[offset+ki]) << " ";
255 target.put(v_base + offset, bytes_to_read);
259 /*************************************/
260 // Put a string on the page.
261 // slot_num: slot number to be returned
263 /**************************************/
265 page::put(int& slot_num, buffer& source)
268 MESSAGE(cerr, "page::put()");
269 debug(cerr, free_bytes());
272 int source_len = source.content_sz();
276 alloc_slot( slot_num, source_len, target );
279 MESSAGE(cerr, "AAA");
280 debug(cerr, slot_num);
281 debug(cerr, free_bytes());
284 memcpy(target, source.get_base(), source_len);
287 debug(cerr, (int)(void*)target);
288 debug(cerr, source_len);
289 MESSAGE(cerr, "BBB");
290 debug(cerr, free_bytes());
293 spointer_t slot_info(v_base, slot_num) ;
294 slot_info.set_mode(spointer_t::DELETED, false);
295 slot_info.set_string_leng(source_len);
298 MESSAGE(cerr, "CCC");
299 debug(cerr, free_bytes());
300 MESSAGE(cerr, "page::put() done");
307 Boolean page::del_slot(int slot_num)
309 if ( ! INRANGE(slot_num, 1, count()-1) )
310 throw(boundaryException( 1, count()-1, slot_num));
312 spointer_t deleted_slot_info(v_base, slot_num);
314 deleted_slot_info.set_mode(spointer_t::DELETED, true);
316 spointer_t manage_slot_info(v_base, count());
318 deleted_slot_info.set_forward_ptr(
319 (int)(manage_slot_info.forward_ptr())
322 manage_slot_info.set_forward_ptr( slot_num );
329 Boolean page::update_slot( int slot_num, buffer& source, int offset )
332 MESSAGE(cerr, "page::update_slot()");
333 debug(cerr, slot_num);
336 if ( ! INRANGE(slot_num, 1, count()-1) )
337 throw(boundaryException( 1, count()-1, slot_num));
340 spointer_t slot_info(v_base, slot_num) ;
342 int ofst = slot_info.string_ofst() + offset;
343 int leng = MIN(slot_info.string_leng(), source.content_sz());
349 memcpy(v_base + ofst, source.get_base(), leng);
355 ///////////////////////////////
356 // Allocate a slot on the page
357 ///////////////////////////////
358 Boolean page::alloc_slot( int& slot_num, int size, char*& str_ptr )
366 int prev_slot_num = 0;
368 while ( slot_num != 0 &&
369 ( ok = _alloc_slot( slot_num, size, str_ptr )) == false ) {
370 prev_slot_num = slot_num;
372 spointer_t slot_info(v_base, slot_num);
373 slot_num = (int)slot_info.forward_ptr();
376 if ( prev_slot_num && slot_num ) {
378 spointer_t slot_info(v_base, slot_num);
380 int next_slot_num = (int)slot_info.forward_ptr();
382 spointer_t prev_slot_info(v_base, prev_slot_num);
384 prev_slot_info.set_forward_ptr(next_slot_num);
387 debug(cerr, free_bytes());
388 MESSAGE(cerr, " page::alloc_slot done");
394 Boolean page::_alloc_slot( int slot_num, int size, char*& str_ptr )
396 //MESSAGE(cerr, "_alloc_slot");
398 spointer_t* slot_info = new spointer_t(v_base, slot_num);
400 /*************************************************************/
401 // make sure that the new string starts at an aligned position
402 /*************************************************************/
404 int end_ptr = slot_info -> string_ofst() - size;
408 int left_shift_delta = end_ptr % 4;
409 end_ptr -= left_shift_delta;
410 size += left_shift_delta;
414 int new_blank_len = slot_info -> string_leng() ;
416 if ( new_blank_len < size ) {
421 slot_info -> set_string_ofst( end_ptr );
422 slot_info -> set_string_leng( size );
423 slot_info -> set_mode(spointer_t::DELETED, false);
424 slot_info -> set_forward_ptr(0);
428 if ( slot_num == count() ) {
430 //MESSAGE(cerr, "slot_num == count() case:");
432 new_blank_len -= size;
433 //debug(cerr, new_blank_len);
435 if ( new_blank_len < (int)(2*SLOT_HEADER_SIZE + 10) )
438 new_blank_len -= SLOT_HEADER_SIZE; // space allocated for new
441 //debug(cerr, new_blank_len);
445 MESSAGE(cerr, "in page::alloc");
447 debug(cerr, i_th -> string_leng());
448 debug(cerr, i_th -> string_ofst());
449 debug(cerr, new_blank_len);
452 ///////////////////////////////
453 // append a new slot to the end
454 ///////////////////////////////
455 set_count(count()+1);
456 spointer_t* z = new spointer_t(v_base, count(), end_ptr, new_blank_len);
459 //debug(cerr, free_bytes());
460 //MESSAGE(cerr, "page::alloc done");
463 MESSAGE(cerr, "in page::alloc");
464 debug(cerr, end_ptr);
470 str_ptr = v_base + end_ptr;
472 //debug(cerr, int(base));
473 //debug(cerr, i_th -> string_ofst());
475 //debug(cerr, slot_num);
476 //debug(cerr, long(str_ptr));
477 //debug(cerr, long(v_base));
478 //debug(cerr, end_ptr);
480 //if ( count() >= 1 ) {
481 //spointer_t first_slot(v_base, 1);
482 //debug(cerr, first_slot.string_ofst());
483 //debug(cerr, first_slot.string_leng());
492 Boolean page::get_str_ptr( int slot_num, char*& str, int& len )
494 if ( ! INRANGE(slot_num, 1, count()-1) )
495 throw(boundaryException( 1, count()-1, slot_num));
497 spointer_t slot_info(v_base, slot_num);
499 str = slot_info.string_ofst() + v_base;
500 len = slot_info.string_leng();
503 MESSAGE(cerr, "page::get_str_ptr(), result:");
504 debug(cerr, slot_info.string_ofst());
505 debug(cerr, slot_info.string_leng());
511 // return number of free bytes on the page
512 int page::free_bytes() const
514 spointer_t slot_info(v_base, count());
515 return slot_info.string_leng() - SLOT_HEADER_SIZE - 10;
518 int page::free_slots() const // return number of free slots on the page
525 x = new spointer_t(v_base, ind);
527 if ( x -> get_mode(spointer_t::DELETED) == true )
537 void page::next(int& ind) const // return next index relative to 'ind'
539 if ( ind >= count()-1 )
545 void page::prev(int& ind) const // return prev index relative to 'ind'
553 void page::_swap_order(Boolean swap_count_field_first)
555 if ( v_swap_order == true ) {
557 MESSAGE(cerr, "page::_swap_order()");
561 int& x = *((count_t*)v_base); // use this version to point at
565 if ( swap_count_field_first == true ) {
566 ORDER_SWAP_UINT(x); // swap the count field first
567 //MESSAGE(cerr, "swap earlier");
571 for ( int i=1; i<=x; i++ ) {
573 spointer_t slot_info(v_base, i);
574 //debug(cerr, hex(slot_info.header.int_view));
575 //debug(cerr, slot_info.string_ofst());
576 slot_info.swap_order();
577 //debug(cerr, hex(slot_info.header.int_view));
578 //debug(cerr, slot_info.string_ofst());
581 if ( swap_count_field_first == false ) {
582 ORDER_SWAP_UINT(x); // swap the count field second
583 //MESSAGE(cerr, "swap later");
590 ostream& operator<<(ostream&s, page& p)
593 debug(s, int(p.dirty));
596 debug(s, p.free_bytes());
598 debug(s, long(p.v_base));
599 debug(s, long(p.v_eptr));
605 if ( p.get(ind, lbuf, 0) == true ) {
614 void* page::operator new( size_t sz )
616 int alignment_overhead = sizeof(char*);
618 char* p = ::new char[alignment_overhead+sz];
621 align_offset = int(alignment_overhead - long(p) % alignment_overhead);
622 return (void*)(p + align_offset);
624 MESSAGE(cerr, "page::new() memalign call failed");
625 throw(systemException(errno));
629 void page::operator delete( void* p, size_t )
632 free((char*)((char*)p - align_offset));
636 int page::cdr_sizeof()
638 return sizeof(pageid) + v_bufsz;
641 io_status page::cdrIn(buffer& buf)
648 io_status page::cdrOut(buffer& buf)