dtinfo: Fix coverity warning related to using delete not delete []
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / storage / page.C
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 librararies 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.cc /main/6 1996/08/15 14:14:45 cde-hal $
25  *
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.
30  * 
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.
34  * 
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
41  * 
42  */
43
44
45 #include "storage/page.h"
46
47
48 /////////////////////////////////////////////////////////////
49 // SLOT_HEADER_SIZE is defined for these fields:
50 //(sizeof(fwd_ptr) + sizeof(header.int_view) + sizeof(int))
51 //
52 // Note: the last int field is not used. It is here for
53 //       backward compatibility.  qfc 12-13-95
54 /////////////////////////////////////////////////////////////
55
56 #define SLOT_HEADER_SIZE (sizeof(mmdb_pos_t) + sizeof(unsigned int) + sizeof(int))
57
58 spointer_t::spointer_t(char* page_base, int slot): swapped(false)
59 {
60    page_image = page_base + sizeof(count_t) + (slot-1)*SLOT_HEADER_SIZE;
61
62    memcpy((char*)&fwd_ptr, page_image, sizeof(fwd_ptr));
63    memcpy(
64           (char*)&header.int_view, 
65           page_image+sizeof(fwd_ptr), 
66           sizeof(header.int_view)
67          );
68 #ifdef PAGE_DEBUG
69 MESSAGE(cerr, "spointer_t::spointer_t() [1]");
70 debug(cerr, slot);
71 debug(cerr, (int)(void*)page_base);
72 debug(cerr, (int)(void*)page_image);
73 #endif
74
75 }
76
77 spointer_t::spointer_t(char* page_base, int slot_num, int ofst, int len) : 
78    fwd_ptr(0), swapped(false)
79 {
80    header.bit_view.spointer = ofst;
81    header.bit_view.length = len;
82
83    set_mode(DELETED, false);
84    set_mode(IS_OBJECT, false);
85
86    set_mode(UPDATED, true);
87
88    page_image = page_base + sizeof(count_t) + (slot_num-1) * SLOT_HEADER_SIZE;
89 }
90
91 spointer_t::~spointer_t() 
92 {
93
94 //MESSAGE(cerr, "spointer_t::~spointer_t()");
95 //debug(cerr, header.bit_view.spointer);
96
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)
102             );
103    }
104 }
105
106 void spointer_t::set_mode(spointer_mode m, Boolean b)
107 {
108    switch ( m ) {
109      case IS_OBJECT:
110         header.bit_view.is_object = ( b == true ) ? 1 : 0;
111         header.bit_view.updated = 1;
112         break;
113      case FIRST_RECD:
114         header.bit_view.first_recd = ( b == true ) ? 1 : 0;
115         header.bit_view.updated = 1;
116         break;
117      case DELETED:
118         header.bit_view.deleted = ( b == true ) ? 1 : 0;
119         header.bit_view.updated = 1;
120         break;
121      case UPDATED:
122         header.bit_view.updated = ( b == true ) ? 1 : 0;
123         break;
124      default:
125         MESSAGE(cerr, "page::set_mode(): invalid mode");
126         throw( intException((int)m) );
127         break;
128    }
129
130 }
131
132 Boolean spointer_t::get_mode(spointer_mode m)
133 {
134    switch ( m ) {
135      case IS_OBJECT:
136         return ( header.bit_view.is_object == 1 ) ? true : false;
137      case FIRST_RECD:
138         return ( header.bit_view.first_recd == 1 ) ? true : false;
139      case DELETED:
140         return ( header.bit_view.deleted == 1 ) ? true : false;
141      case UPDATED:
142         return ( header.bit_view.updated == 1 ) ? true : false;
143      default:
144         MESSAGE(cerr, "page::get_mode(): invalid mode");
145         throw( intException((int)m) );
146         break;
147    }
148 }
149
150    
151 static int align_offset;
152
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)
156 {
157    v_memalign_offset = align_offset;
158    clean_all();
159 }
160
161 page::~page()
162 {
163    align_offset = v_memalign_offset;
164 }
165
166
167 /***************************/
168 //
169 /***************************/
170 void page::clean_all()
171 {
172    v_eptr = v_base + buf_sz();
173    set_count(1);
174
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
180                );
181 }
182
183
184 /*************************************
185 * Get the ith string pointer from the 
186 * page.
187 **************************************/
188 spointer_t* page::get_spointer(int slot_num) const
189
190    if ( !INRANGE(slot_num, 1, count()) ) {
191       throw( boundaryException(1, count(), slot_num));
192    }
193
194    return new spointer_t(v_base, slot_num);
195 }
196
197
198 //////////////////////////////
199 // Get a string from the page.
200 //////////////////////////////
201 Boolean 
202 page::get( int slot_num, buffer& target, 
203            int offset, int bytes_to_read
204          ) const
205 {
206
207 /*
208 MESSAGE(cerr, "in page::get()");
209 debug(cerr, slot_num);
210 debug(cerr, offset);
211 debug(cerr, bytes_to_read);
212 */
213
214    if ( ! INRANGE(slot_num, 1, count()-1) ) 
215       throw( boundaryException(1, count()-1, slot_num) );
216
217
218    spointer_t slot_info(v_base, slot_num); 
219
220    if ( slot_info.get_mode(spointer_t::DELETED) == true ) {
221       MESSAGE(cerr, "page::get(): get a deleted slot");
222       return false;
223    }
224
225    int string_len = slot_info.string_leng();
226 //debug(cerr, string_len);
227
228    if ( bytes_to_read == 0 )
229       bytes_to_read = string_len;
230
231 //debug(cerr, bytes_to_read);
232       
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)
237             );
238    }
239
240    offset += slot_info.string_ofst();
241
242
243 /*
244 MESSAGE(cerr, "page::get()");
245 debug(cerr, offset);
246 debug(cerr, long(v_base + offset));
247 debug(cerr, bytes_to_read);
248
249 for (int ki=0; ki<bytes_to_read; ki++)
250    cerr << int(v_base[offset+ki]) << " ";
251 cerr << "\n";
252 */
253
254
255    target.put(v_base + offset, bytes_to_read);
256    return true;
257 }
258
259 /*************************************/
260 // Put a string on the page.
261 // slot_num: slot number to be returned 
262 // buf: string 
263 /**************************************/
264 Boolean 
265 page::put(int& slot_num, buffer& source)
266 {
267 #ifdef PAGE_DEBUG
268 MESSAGE(cerr, "page::put()");
269 debug(cerr, free_bytes());
270 #endif
271
272    int source_len = source.content_sz();
273
274    char* target = 0;
275
276    alloc_slot( slot_num, source_len, target );
277
278 #ifdef PAGE_DEBUG
279 MESSAGE(cerr, "AAA");
280 debug(cerr, slot_num);
281 debug(cerr, free_bytes());
282 #endif
283
284    memcpy(target, source.get_base(), source_len);
285
286 #ifdef PAGE_DEBUG
287 debug(cerr, (int)(void*)target);
288 debug(cerr, source_len);
289 MESSAGE(cerr, "BBB");
290 debug(cerr, free_bytes());
291 #endif
292
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);
296
297 #ifdef PAGE_DEBUG
298 MESSAGE(cerr, "CCC");
299 debug(cerr, free_bytes());
300 MESSAGE(cerr, "page::put() done");
301 #endif
302
303    dirty = true;
304    return true;
305 }
306
307 Boolean page::del_slot(int slot_num)
308 {
309    if ( ! INRANGE(slot_num, 1, count()-1) ) 
310       throw(boundaryException( 1, count()-1, slot_num));
311
312    spointer_t deleted_slot_info(v_base, slot_num);
313
314    deleted_slot_info.set_mode(spointer_t::DELETED, true);
315
316    spointer_t manage_slot_info(v_base, count());
317
318    deleted_slot_info.set_forward_ptr(
319                           (int)(manage_slot_info.forward_ptr())
320                                     );
321          
322    manage_slot_info.set_forward_ptr( slot_num );
323
324    dirty = true;
325
326    return true;
327 }
328
329 Boolean page::update_slot( int slot_num, buffer& source, int offset )
330 {
331 /*
332 MESSAGE(cerr, "page::update_slot()");
333 debug(cerr, slot_num);
334 */
335
336    if ( ! INRANGE(slot_num, 1, count()-1) ) 
337       throw(boundaryException( 1, count()-1, slot_num));
338
339
340    spointer_t slot_info(v_base, slot_num) ;
341
342    int ofst = slot_info.string_ofst() + offset;
343    int leng = MIN(slot_info.string_leng(), source.content_sz());
344 /*
345 debug(cerr, ofst);
346 debug(cerr, leng);
347 */
348
349    memcpy(v_base + ofst, source.get_base(), leng);
350    dirty = true;
351
352    return true;
353 }
354
355 ///////////////////////////////
356 // Allocate a slot on the page 
357 ///////////////////////////////
358 Boolean page::alloc_slot( int& slot_num, int size, char*& str_ptr )
359 {
360 #ifdef PAGE_DEBUG
361 debug(cerr, size);
362 #endif
363
364    Boolean ok = false;
365    slot_num = count();
366    int prev_slot_num = 0;
367    
368    while ( slot_num != 0 && 
369            ( ok = _alloc_slot( slot_num, size, str_ptr )) == false ) {
370      prev_slot_num = slot_num;
371
372      spointer_t slot_info(v_base, slot_num);
373      slot_num = (int)slot_info.forward_ptr();
374    }
375
376    if ( prev_slot_num && slot_num ) {
377
378        spointer_t slot_info(v_base, slot_num);
379        
380        int next_slot_num = (int)slot_info.forward_ptr();
381
382        spointer_t prev_slot_info(v_base, prev_slot_num);
383
384        prev_slot_info.set_forward_ptr(next_slot_num);
385    }
386 #ifdef PAGE_DEBUG
387 debug(cerr, free_bytes());
388 MESSAGE(cerr, " page::alloc_slot done");
389 #endif
390
391    return ok;
392 }
393
394 Boolean page::_alloc_slot( int slot_num, int size, char*& str_ptr )
395 {
396 //MESSAGE(cerr, "_alloc_slot");
397
398     spointer_t* slot_info = new spointer_t(v_base, slot_num);
399
400 /*************************************************************/
401 // make sure that the new string starts at an aligned position
402 /*************************************************************/
403
404     int end_ptr = slot_info -> string_ofst() - size;
405
406
407 #ifdef NO_COPY
408     int left_shift_delta = end_ptr % 4;
409     end_ptr -= left_shift_delta;
410     size += left_shift_delta; 
411 #endif
412
413
414     int new_blank_len = slot_info -> string_leng() ;
415
416     if ( new_blank_len < size ) {
417         delete slot_info;
418         return false;
419     }
420
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);
425
426     delete slot_info;
427
428     if ( slot_num == count() ) {
429
430 //MESSAGE(cerr, "slot_num == count() case:");
431
432        new_blank_len -= size;
433 //debug(cerr, new_blank_len);
434    
435        if ( new_blank_len < (int)(2*SLOT_HEADER_SIZE + 10) )
436           new_blank_len = 0;
437        else
438           new_blank_len -= SLOT_HEADER_SIZE; // space allocated for new
439                                              // free space slot
440
441 //debug(cerr, new_blank_len);
442
443    
444    /*
445    MESSAGE(cerr, "in page::alloc");
446    debug(cerr, size);
447    debug(cerr, i_th -> string_leng());
448    debug(cerr, i_th -> string_ofst());
449    debug(cerr, new_blank_len);
450    */
451    
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);
457        delete z;
458
459 //debug(cerr, free_bytes());
460 //MESSAGE(cerr, "page::alloc done");
461    
462    /*
463    MESSAGE(cerr, "in page::alloc");
464    debug(cerr, end_ptr);
465    debug(cerr, size);
466    */
467    
468     }
469
470   str_ptr = v_base + end_ptr;
471
472 //debug(cerr, int(base));
473 //debug(cerr, i_th -> string_ofst());
474
475 //debug(cerr, slot_num);
476 //debug(cerr, long(str_ptr));
477 //debug(cerr, long(v_base));
478 //debug(cerr, end_ptr);
479
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());
484 //}
485
486   dirty = true;
487
488   return true;
489 }
490
491
492 Boolean page::get_str_ptr( int slot_num, char*& str, int& len )
493 {
494    if ( ! INRANGE(slot_num, 1, count()-1) ) 
495       throw(boundaryException( 1, count()-1, slot_num));
496
497    spointer_t slot_info(v_base, slot_num);
498
499    str = slot_info.string_ofst() + v_base;
500    len = slot_info.string_leng();
501
502 /*
503 MESSAGE(cerr, "page::get_str_ptr(), result:");
504 debug(cerr, slot_info.string_ofst());
505 debug(cerr, slot_info.string_leng());
506 */
507
508    return true;
509 }
510
511 // return number of free bytes on the page
512 int page::free_bytes() const  
513 {
514    spointer_t slot_info(v_base, count());
515    return slot_info.string_leng() - SLOT_HEADER_SIZE - 10;
516 }
517
518 int page::free_slots() const  // return number of free slots on the page
519 {
520    spointer_t *x;
521    int sum = 0;
522    int ind = first();
523    while ( ind ) {
524
525       x = new spointer_t(v_base, ind);
526
527       if ( x -> get_mode(spointer_t::DELETED) == true )
528          sum++;
529
530       delete x;
531
532       next(ind);
533    }
534    return sum;
535 }
536
537 void page::next(int& ind) const // return next index relative to 'ind'
538 {
539    if ( ind >= count()-1 )
540       ind = 0;
541    else
542       ind ++;
543 }
544
545 void page::prev(int& ind) const // return prev index relative to 'ind'
546 {
547    if ( ind == 1 )
548       ind = 0;
549    else
550       ind --;
551 }
552
553 void page::_swap_order(Boolean swap_count_field_first)
554 {
555    if ( v_swap_order == true ) {
556 /*
557 MESSAGE(cerr, "page::_swap_order()");
558 debug(cerr, pageid);
559 */
560
561       int& x = *((count_t*)v_base);  // use this version to point at
562                                      // the count field
563
564 //debug(cerr, x);
565       if ( swap_count_field_first == true ) {
566          ORDER_SWAP_UINT(x); // swap the count field first
567 //MESSAGE(cerr, "swap earlier");
568 //debug(cerr, x);
569       }
570
571       for ( int i=1; i<=x; i++ ) {
572 //debug(cerr, 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());
579       }
580    
581       if ( swap_count_field_first == false ) {
582          ORDER_SWAP_UINT(x); // swap the count field second
583 //MESSAGE(cerr, "swap later");
584 //debug(cerr, x);
585       }
586       
587    }
588 }
589
590 ostream& operator<<(ostream&s, page& p)
591 {
592    buffer lbuf;
593    debug(s, int(p.dirty));
594    debug(s, p.count());
595    debug(s, p.pageid);
596    debug(s, p.free_bytes());
597
598    debug(s, long(p.v_base));
599    debug(s, long(p.v_eptr));
600
601    int ind = p.first();
602    while ( ind ) {
603       debug(s, int(ind));
604       lbuf.reset();
605       if ( p.get(ind, lbuf, 0) == true ) {
606          s << lbuf;
607          s << "\n";
608       }
609       p.next(ind);
610    } 
611    return s;
612 }
613
614 void* page::operator new( size_t sz )
615 {
616    int alignment_overhead = sizeof(char*);
617
618    char* p = ::new char[alignment_overhead+sz];
619
620    if ( p ) {
621        align_offset = int(alignment_overhead - long(p) % alignment_overhead);
622        return (void*)(p + align_offset);
623    } else {
624       MESSAGE(cerr, "page::new() memalign call failed");
625       throw(systemException(errno));
626    }
627 }
628
629 void page::operator delete( void* p, size_t )
630 {
631    if ( p ) 
632       free((char*)((char*)p - align_offset));
633 }
634
635 /*
636 int page::cdr_sizeof()
637 {
638    return sizeof(pageid) + v_bufsz;
639 }
640
641 io_status page::cdrIn(buffer& buf)
642 {
643    buf.put(pageid);
644    buffer::cdrIn(buf);
645    return done;
646 }
647
648 io_status page::cdrOut(buffer& buf)
649 {
650    buf.get(pageid);
651    buffer::cdrOut(buf);
652    return done;
653 }
654 */