FreeCalypso > hg > tcs211-l1-reconst
comparison g23m/condat/ms/src/aci/db.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:509db1a7b7b8 |
---|---|
1 /* | |
2 +----------------------------------------------------------------------------- | |
3 | Project : PHB | |
4 | Modul : DBM | |
5 +----------------------------------------------------------------------------- | |
6 | Copyright 2005 Texas Instruments Berlin, AG | |
7 | All rights reserved. | |
8 | | |
9 | This file is confidential and a trade secret of Texas | |
10 | Instruments Berlin, AG | |
11 | The receipt of or possession of this file does not convey | |
12 | any rights to reproduce or disclose its contents or to | |
13 | manufacture, use, or sell anything it may describe, in | |
14 | whole, or in part, without the specific written consent of | |
15 | Texas Instruments Berlin, AG. | |
16 +----------------------------------------------------------------------------- | |
17 | Purpose : Implementation of DBM functions | |
18 +----------------------------------------------------------------------------- | |
19 */ | |
20 | |
21 #ifdef TI_PS_FFS_PHB | |
22 | |
23 #include "db_int.h" | |
24 #include <string.h> | |
25 | |
26 /* For DB Testing */ | |
27 | |
28 /* Check if we are closing FFS files properly */ | |
29 #define DB_TEST | |
30 | |
31 /* A simple check to make sure that all allocated | |
32 memory is freed to avoid memory leak */ | |
33 #define DB_MEMORY_CHECK | |
34 | |
35 /* if dir is not empty during deletion, we do not | |
36 raise the error, rather we go ahead and remove | |
37 all the contents and then delete the dir */ | |
38 #define FORCED_DIR_REMOVAL | |
39 | |
40 /************************** | |
41 D E F I N I T I O N S & | |
42 D E C L A R A T I O N S | |
43 **************************/ | |
44 | |
45 | |
46 GLOBAL UBYTE UsedDBs; /* Number of existing databases */ | |
47 GLOBAL int LastFFS_ReturnCode; /* Last FFS return code */ | |
48 GLOBAL T_DBM_MASTERRECORD DbmMaster [MAX_DBs]; /* Database Master */ | |
49 GLOBAL T_DBM_STATE DBM_State = DBM_NOT_INITIALISED; /* DBM State */ | |
50 GLOBAL T_DB_CHANGED DB_History_log; /* History log */ | |
51 | |
52 #ifdef FFS_CLOSE_BEFORE_OPEN | |
53 | |
54 T_FFS_FD Dummy_FFSFileHandle = NULL; | |
55 #define INVALID_FLD_CTR 0xFF | |
56 #define NOT_OPENED 0x00 | |
57 #define OPENED_FOR_READ 0x01 | |
58 #define OPENED_FOR_WRITE 0x02 | |
59 | |
60 #endif | |
61 | |
62 #ifdef DB_TEST | |
63 | |
64 S8 db_test_ffs_open_ctr = 0; | |
65 T_FFS_SIZE db_test_ffs_ret_code = EFFS_OK; | |
66 | |
67 #define DB_FFS_OPEN( ret, file, flag ) \ | |
68 { \ | |
69 ret = ffs_open( file, flag ); \ | |
70 \ | |
71 if( ret >= EFFS_OK ) \ | |
72 { \ | |
73 ++db_test_ffs_open_ctr; \ | |
74 TRACE_EVENT_P1( "DB_FFS_OPEN:db_test_ffs_open_ctr:%d", db_test_ffs_open_ctr ); \ | |
75 } else { \ | |
76 TRACE_EVENT_P1( "DB_FFS_OPEN:FFS ERROR:%d", ret ); \ | |
77 } \ | |
78 } | |
79 | |
80 | |
81 #define DB_FFS_CLOSE( fd ) \ | |
82 { \ | |
83 T_FFS_SIZE db_test_ffs_ret_code = ffs_close( fd ); \ | |
84 \ | |
85 if( db_test_ffs_ret_code >= EFFS_OK ) \ | |
86 { \ | |
87 --db_test_ffs_open_ctr; \ | |
88 TRACE_EVENT_P1( "DB_FFS_CLOSE:db_test_ffs_open_ctr:%d", db_test_ffs_open_ctr ); \ | |
89 } else { \ | |
90 TRACE_EVENT_P1( "DB_FFS_CLOSE:FFS ERROR:%d", db_test_ffs_ret_code ); \ | |
91 } \ | |
92 \ | |
93 fd = NULL; \ | |
94 } | |
95 | |
96 #define DB_RETURN( ret ) \ | |
97 { \ | |
98 TRACE_EVENT_P1( "DB_RETURN:ret:%d", ret ); \ | |
99 return ret; \ | |
100 } | |
101 | |
102 #define DB_VALUE_RETURN( ret ) \ | |
103 { \ | |
104 TRACE_EVENT_P1( "DB_VALUE_RETURN:ret:%d", ret ); \ | |
105 return ret; \ | |
106 } | |
107 | |
108 #else | |
109 | |
110 #define DB_FFS_OPEN( ret, file, flag ) ret = ffs_open( file, flag ) | |
111 #define DB_FFS_CLOSE( fd ) { ffs_close( fd ); fd = NULL; } | |
112 #define DB_RETURN( ret ) return ret | |
113 #define DB_VALUE_RETURN( ret ) return ret | |
114 | |
115 #endif | |
116 | |
117 #ifdef DB_MEMORY_CHECK | |
118 | |
119 UBYTE alloc_ctr = 0; | |
120 | |
121 #define DB_MALLOC( ptr, num_of_bytes ) \ | |
122 { \ | |
123 ++alloc_ctr; \ | |
124 TRACE_EVENT_P1( "DB Memory Alloc:%d", alloc_ctr ); \ | |
125 ACI_MALLOC( ptr, num_of_bytes ); \ | |
126 } | |
127 | |
128 #define DB_MFREE( ptr ) \ | |
129 { \ | |
130 --alloc_ctr; \ | |
131 TRACE_EVENT_P1( "DB Memory Free:%d", alloc_ctr ); \ | |
132 ACI_MFREE( ptr ); \ | |
133 } | |
134 | |
135 #else | |
136 | |
137 #define DB_MALLOC( ptr, num_of_bytes ) ACI_MALLOC( ptr, num_of_bytes ) | |
138 #define DB_MFREE( ptr ) ACI_MFREE( ptr ) | |
139 | |
140 #endif | |
141 | |
142 | |
143 #ifdef _SIMULATION_ | |
144 #define DB_DIR "/dbm" | |
145 #define DB_MASTER_FILE "/dbm/DD_master" | |
146 #else | |
147 #define DB_DIR "/gsm/dbm" | |
148 #define DB_MASTER_FILE "/gsm/dbm/DD_master" | |
149 #endif | |
150 | |
151 #define FILENAME_LEN 40 | |
152 | |
153 #define T_DB_MASTER_RECORD_SIZE 18 | |
154 /* DBM master record | |
155 File: DB_DIR/DD_master | |
156 Data: | |
157 1) DBDirectory (16 bytes, based on MAX_LEN_DIRECTORY=16) | |
158 2) NumOfFiles (1 byte, based on MAX_NUM_FILES=255) | |
159 3) Tracked (1 byte) | |
160 */ | |
161 | |
162 | |
163 #define T_DB_FIELD_RECORD_SIZE 43 | |
164 /* Based on the following data written into FFS | |
165 File: DB_DIR/DD_<DBDirectory> | |
166 Data: | |
167 1) FieldID (2 bytes, given in Interface) | |
168 2) DBType (1 byte) | |
169 3) RecordSize (2 bytes, based on MAX_RECORD_SIZE=65kb) | |
170 4) NumOfRecords (1 byte, based on MAX_NUM_RECORDS=255) | |
171 5) SortIndexes (MAX_NUM_OF_SORT_INDEXS bytes, 1 byte for each index ) | |
172 6) RecordBitMap (32 bytes, as of now based on MAX_NUM_RECORDS=255) | |
173 7) Clean (1 byte, this can be clubbed with DBType ) | |
174 */ | |
175 | |
176 #define RecordBitMap_OFFSET 10 /* depending on structure in DB_DIR/DD_<DBDirectory> */ | |
177 | |
178 #define SortIndexList_OFFSET 6 /* depending on structure in DB_DIR/DD_<DBDirectory> */ | |
179 | |
180 #define QuickSort_BufferStackSize 8 /* For Non recursive quick sort, | |
181 allows sorting of 2 ^ 8 = 256 elements */ | |
182 | |
183 #define SEARCH_FAILED -1 | |
184 | |
185 #define MAX_BIT_POS 8 | |
186 | |
187 #define BITMAP_INDEX( num ) ( ( num - 1 ) / MAX_BIT_POS ) | |
188 #define BIT_POS( num ) ( ( num - 1 ) % MAX_BIT_POS ) | |
189 | |
190 /* For RAM strctures */ | |
191 #define TRACKED_AND_CLEAN 0x03 | |
192 | |
193 #define TRACKED 0x02 | |
194 | |
195 #define CLEAN 0x01 | |
196 | |
197 #define NOT_CLEAN 0x00 | |
198 | |
199 /* For FFS strctures */ | |
200 #define FFS_TRACKED 0x01 | |
201 | |
202 #define FFS_NOT_TRACKED 0x00 | |
203 | |
204 #define NOT ! | |
205 | |
206 #define INVALID_RECORD_NUM 0xFF | |
207 | |
208 /* | |
209 Internal function to initialize RAM structures with FFS | |
210 */ | |
211 T_DB_CODE init_RAM_with_FFS ( void ); | |
212 | |
213 #define DBM_State_check \ | |
214 if ( DBM_State EQ DBM_NOT_INITIALISED ) DB_RETURN( DB_NOT_INITIALISED ); | |
215 | |
216 T_DB_CODE db_handle_check ( int db_handle ); | |
217 | |
218 UBYTE field_id_search ( int db_handle, | |
219 USHORT field_id ); | |
220 | |
221 T_DB_CODE update_history_log ( int db_handle, | |
222 USHORT field_id, | |
223 USHORT record_num ); | |
224 | |
225 /* functions swap and parition are required for sorting */ | |
226 void swap ( UBYTE* sort_list, | |
227 UBYTE low, | |
228 UBYTE high ); | |
229 | |
230 UBYTE split_list ( UBYTE* sort_list, | |
231 UBYTE low, | |
232 UBYTE high, | |
233 T_COMP_FUNC compare_function, | |
234 ULONG flags, | |
235 int db_handle, | |
236 USHORT field_id ); | |
237 | |
238 void quick_sort ( UBYTE* sort_list, | |
239 UBYTE num_of_elements, | |
240 T_COMP_FUNC compare_function, | |
241 ULONG flags, | |
242 int db_handle, | |
243 USHORT field_id ); | |
244 | |
245 UBYTE search_clear_bit_in_bitmap ( UBYTE* bitmap, | |
246 UBYTE bitmap_size ); | |
247 | |
248 void set_bit_in_bitmap ( UBYTE* bitmap, | |
249 UBYTE bitmap_size, | |
250 UBYTE bit_num ); | |
251 | |
252 void reset_bit_in_bitmap ( UBYTE* bitmap, | |
253 UBYTE bitmap_size, | |
254 UBYTE bit_num ); | |
255 | |
256 T_DB_CODE populate_sorted_list_from_FFS ( | |
257 | |
258 #ifdef FFS_CLOSE_BEFORE_OPEN | |
259 UBYTE db_ctr, | |
260 #endif | |
261 char* sort_file, | |
262 UBYTE num_of_elements, | |
263 UBYTE** sort_list_ptr ); | |
264 | |
265 T_DB_CODE write_sorted_list_to_FFS ( | |
266 | |
267 #ifdef FFS_CLOSE_BEFORE_OPEN | |
268 UBYTE db_ctr, | |
269 #endif | |
270 char* sort_file, | |
271 UBYTE num_of_elements, | |
272 UBYTE* sort_list ); | |
273 | |
274 int search ( UBYTE* sort_list, | |
275 UBYTE num_of_elements, | |
276 UBYTE* order_num, | |
277 T_SEARCH_FUNC search_function, | |
278 ULONG flags, | |
279 const UBYTE* search_tag, | |
280 int db_handle, | |
281 USHORT field_id ); | |
282 | |
283 T_DB_CODE update_field_data_in_FFS ( const char* field_file, | |
284 T_FFS_FD* filehandle, | |
285 #ifdef FFS_CLOSE_BEFORE_OPEN | |
286 UBYTE db_ctr, | |
287 #endif | |
288 UBYTE fld_ctr, | |
289 UBYTE field_data_max_size, | |
290 UBYTE* field_data, | |
291 USHORT offset, | |
292 USHORT length ); | |
293 | |
294 UBYTE cal_NextRecordNum ( const char* DBDirectory, | |
295 USHORT FieldID, | |
296 USHORT RecordSize ); | |
297 | |
298 T_DB_CODE read_user_record_from_FFS ( const char* user_field_file, | |
299 | |
300 #ifdef FFS_CLOSE_BEFORE_OPEN | |
301 UBYTE db_ctr, | |
302 UBYTE fld_ctr, | |
303 #endif | |
304 T_FFS_FD* filehandle, | |
305 UBYTE record_num, | |
306 USHORT record_size, | |
307 USHORT offset, | |
308 USHORT length, | |
309 UBYTE* record_buffer ); | |
310 | |
311 T_DB_CODE write_user_record_to_FFS ( const char* user_field_file, | |
312 | |
313 #ifdef FFS_CLOSE_BEFORE_OPEN | |
314 UBYTE db_ctr, | |
315 UBYTE fld_ctr, | |
316 #endif | |
317 T_FFS_FD* filehandle, | |
318 UBYTE record_num, | |
319 USHORT record_size, | |
320 USHORT offset, | |
321 USHORT length, | |
322 UBYTE* record_buffer ); | |
323 | |
324 T_DB_CODE delete_file_dir_from_FFS ( const char* filename ); | |
325 | |
326 T_DB_CODE update_dbm_data_in_FFS ( const char* filename, | |
327 UBYTE db_ctr, | |
328 UBYTE db_data_max_size, | |
329 UBYTE* db_data, | |
330 USHORT offset, | |
331 USHORT length ); | |
332 | |
333 T_DB_CODE remove_field_from_FFS ( UBYTE db_ctr, | |
334 UBYTE fld_ctr ); | |
335 | |
336 | |
337 #ifdef FFS_CLOSE_BEFORE_OPEN | |
338 | |
339 T_FFS_FD db_open_user_field_file ( UBYTE db_ctr, | |
340 UBYTE fld_ctr, | |
341 const char* user_field_file, | |
342 T_FFS_OPEN_FLAGS open_option ); | |
343 | |
344 | |
345 void db_close_user_field_files ( UBYTE db_ctr ); | |
346 | |
347 BOOL db_open_full_for_read ( UBYTE db_ctr ); | |
348 | |
349 BOOL db_open_full_for_write ( UBYTE db_ctr ); | |
350 | |
351 void db_close_for_write ( UBYTE db_ctr ); | |
352 | |
353 void db_close_for_read ( UBYTE db_ctr ); | |
354 | |
355 UBYTE db_status_user_field_file ( UBYTE db_ctr, | |
356 UBYTE fld_ctr ); | |
357 | |
358 | |
359 #endif /* FFS_CLOSE_BEFORE_OPEN */ | |
360 | |
361 | |
362 #ifdef FORCED_DIR_REMOVAL | |
363 | |
364 T_DB_CODE delete_dir_forced ( const char* filename ); | |
365 | |
366 #endif /* FORCED_DIR_REMOVAL */ | |
367 | |
368 #ifdef INSERTION_SORT | |
369 | |
370 void get_sort_lists_from_FFS ( UBYTE db_ctr, | |
371 UBYTE fld_ctr ); | |
372 | |
373 void new_in_sort_lists ( UBYTE db_ctr, | |
374 UBYTE fld_ctr, | |
375 UBYTE record_num ); | |
376 | |
377 void update_in_sort_lists ( UBYTE db_ctr, | |
378 UBYTE fld_ctr, | |
379 UBYTE record_num ); | |
380 | |
381 void delete_in_sort_lists ( UBYTE db_ctr, | |
382 UBYTE fld_ctr, | |
383 UBYTE record_num ); | |
384 | |
385 void insertion_sort ( UBYTE* sort_list, | |
386 UBYTE num_of_elements, | |
387 T_COMP_FUNC compare_function, | |
388 ULONG flags, | |
389 int db_handle, | |
390 USHORT field_id ); | |
391 | |
392 void insert_element ( UBYTE* sort_list, | |
393 UBYTE num_of_elements, | |
394 UBYTE bottom, | |
395 UBYTE top, | |
396 UBYTE record_num, | |
397 T_COMP_FUNC compare_function, | |
398 ULONG flags, | |
399 int db_handle, | |
400 USHORT field_id ); | |
401 | |
402 #endif /* INSERTION_SORT */ | |
403 | |
404 T_DB_CODE internal_db_sort ( int db_handle, | |
405 USHORT field_id, | |
406 UBYTE sort_index, | |
407 T_COMP_FUNC compare_function, | |
408 ULONG flags, | |
409 T_DB_SORT sort_type ); | |
410 | |
411 | |
412 | |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | |
423 | |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | |
430 | |
431 | |
432 | |
433 | |
434 | |
435 /****************************** | |
436 I M P L E M E N T A T I O N | |
437 ******************************/ | |
438 | |
439 /**********************/ | |
440 /* INTERNAL FUNCTIONS */ | |
441 /**********************/ | |
442 | |
443 /* | |
444 +--------------------------------------------------------------------+ | |
445 | PROJECT: PHB MODULE: DBM | | |
446 | ROUINE: db_handle_check | | |
447 +--------------------------------------------------------------------+ | |
448 | |
449 PURPOSE : DB Handle checks | |
450 */ | |
451 | |
452 T_DB_CODE db_handle_check ( int db_handle ) | |
453 { | |
454 /* Check for db_handle range */ | |
455 if( db_handle >= MAX_DBs ) | |
456 return DB_INVALID_DB; | |
457 | |
458 /* Check for DBState of db_handle is CLOSED or UNUSED_ENTRY | |
459 If yes, return DB_INVALID_DB */ | |
460 | |
461 if( ( DbmMaster[db_handle].DBState EQ CLOSED ) OR | |
462 ( DbmMaster[db_handle].DBState EQ UNUSED_ENTRY ) ) | |
463 return DB_INVALID_DB; | |
464 | |
465 return DB_OK; | |
466 } | |
467 | |
468 /* | |
469 +--------------------------------------------------------------------+ | |
470 | PROJECT: PHB MODULE: DBM | | |
471 | ROUINE: field_id_search | | |
472 +--------------------------------------------------------------------+ | |
473 | |
474 PURPOSE : checks for the existence of field id in RAM | |
475 */ | |
476 UBYTE field_id_search ( int db_handle, | |
477 USHORT field_id ) | |
478 { | |
479 UBYTE fld_ctr; | |
480 | |
481 for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr ) | |
482 { | |
483 if( DbmMaster[db_handle].ptrFieldRecord[fld_ctr].FieldID EQ field_id ) | |
484 { | |
485 return fld_ctr; | |
486 } | |
487 } | |
488 return fld_ctr; | |
489 } | |
490 | |
491 | |
492 /* | |
493 +--------------------------------------------------------------------+ | |
494 | PROJECT: PHB MODULE: DBM | | |
495 | ROUINE: update_history_log | | |
496 +--------------------------------------------------------------------+ | |
497 | |
498 PURPOSE : Updating history log | |
499 */ | |
500 T_DB_CODE update_history_log ( int db_handle, | |
501 USHORT field_id, | |
502 USHORT record_num ) | |
503 { | |
504 UBYTE i; | |
505 | |
506 /* Check if database is tracked */ | |
507 if( NOT ( DbmMaster[db_handle].Tracked_Clean & TRACKED ) ) /* if db is NOT tracked */ | |
508 return DB_OK; | |
509 | |
510 /* Search history log if the record is present | |
511 If present, return DB_OK */ | |
512 for( i = 0; i < DB_History_log.entries; ++i ) | |
513 { | |
514 if( DB_History_log.field_id[i] EQ field_id ) | |
515 if( DB_History_log.record[i] EQ record_num ) | |
516 return DB_OK; | |
517 } | |
518 | |
519 /* If the number of existing logs in history is reached limit, DB_MAX_AFFECTED, | |
520 return error "DB_HISTORY_FULL". */ | |
521 if( DB_History_log.entries EQ DB_MAX_AFFECTED ) | |
522 return DB_HISTORY_FULL; | |
523 | |
524 /* Add new entry */ | |
525 DB_History_log.field_id [DB_History_log.entries] = field_id; | |
526 DB_History_log.record [DB_History_log.entries] = record_num; | |
527 ++DB_History_log.entries; | |
528 | |
529 return DB_OK; | |
530 | |
531 } | |
532 | |
533 /* | |
534 +--------------------------------------------------------------------+ | |
535 | PROJECT: PHB MODULE: DBM | | |
536 | ROUINE: swap | | |
537 +--------------------------------------------------------------------+ | |
538 | |
539 PURPOSE : Swaps the data | |
540 */ | |
541 void swap ( UBYTE* sort_list, | |
542 UBYTE low, | |
543 UBYTE high ) | |
544 { | |
545 UBYTE tmp = sort_list[low - 1]; | |
546 | |
547 sort_list[low - 1] = sort_list[high - 1]; | |
548 sort_list[high - 1] = tmp; | |
549 | |
550 return; | |
551 | |
552 } | |
553 | |
554 /* | |
555 +--------------------------------------------------------------------+ | |
556 | PROJECT: PHB MODULE: DBM | | |
557 | ROUINE: split_list | | |
558 +--------------------------------------------------------------------+ | |
559 | |
560 PURPOSE : | |
561 */ | |
562 UBYTE split_list ( UBYTE* sort_list, | |
563 UBYTE low, | |
564 UBYTE high, | |
565 T_COMP_FUNC compare_function, | |
566 ULONG flags, | |
567 int db_handle, | |
568 USHORT field_id ) | |
569 { | |
570 UBYTE i, | |
571 pivot_loc; | |
572 | |
573 /* put pivot at first position */ | |
574 swap( sort_list, low, (UBYTE)((low + high)/2)); | |
575 | |
576 pivot_loc = low; | |
577 | |
578 for( i = low + 1; i <= high; ++i ) | |
579 { | |
580 if( compare_function( db_handle, | |
581 field_id, | |
582 sort_list[i - 1], | |
583 sort_list[low - 1], | |
584 flags ) | |
585 < 0 ) | |
586 { | |
587 ++pivot_loc; | |
588 swap( sort_list, pivot_loc, i ); | |
589 } | |
590 } | |
591 | |
592 swap( sort_list, low, pivot_loc ); | |
593 | |
594 return pivot_loc; | |
595 } | |
596 | |
597 | |
598 /* | |
599 +--------------------------------------------------------------------+ | |
600 | PROJECT: PHB MODULE: DBM | | |
601 | ROUINE: quick_sort | | |
602 +--------------------------------------------------------------------+ | |
603 | |
604 PURPOSE : Sorts the user data records in FFS based | |
605 on non-recursive qsort method | |
606 */ | |
607 void quick_sort ( UBYTE* sort_list, | |
608 UBYTE num_of_elements, | |
609 T_COMP_FUNC compare_function, | |
610 ULONG flags, | |
611 int db_handle, | |
612 USHORT field_id ) | |
613 { | |
614 /* This is non-recursive version of QuickSort | |
615 | |
616 - It requires additional storage of (2 * QuickSort_BufferStackSize) bytes | |
617 compared to recursive version of quick sort | |
618 | |
619 - It supports sorting of 2 ^ QuickSort_BufferStackSize elements. */ | |
620 | |
621 /* It is assumed that MAX_NUM_RECORDS = 254;if we want to support the | |
622 sorting of list bigger than 254 elements, change following UBYTE | |
623 to U16, U32 etc. and update QuickSort_BufferStackSize accordingly ! */ | |
624 | |
625 UBYTE low, | |
626 high, | |
627 pivot_loc, | |
628 buff_stack_ctr = 0, | |
629 buffer_low[QuickSort_BufferStackSize], | |
630 buffer_high[QuickSort_BufferStackSize]; | |
631 | |
632 low = 1; | |
633 high = num_of_elements; | |
634 | |
635 do | |
636 { | |
637 if( buff_stack_ctr > 0 ) | |
638 { | |
639 --buff_stack_ctr; | |
640 low = buffer_low[buff_stack_ctr]; | |
641 high = buffer_high[buff_stack_ctr]; | |
642 } | |
643 | |
644 while( low < high ) | |
645 { | |
646 pivot_loc = split_list( sort_list, | |
647 low, | |
648 high, | |
649 compare_function, | |
650 flags, | |
651 db_handle, | |
652 field_id ); | |
653 | |
654 if( buff_stack_ctr >= QuickSort_BufferStackSize ) | |
655 { | |
656 /* This should never happen ! */ | |
657 TRACE_ERROR( "Value set for QuickSort_BufferStackSize is small !"); | |
658 return; | |
659 } | |
660 | |
661 /* Remember larger sublist, and process smaller */ | |
662 | |
663 if( (pivot_loc - low) < (high - pivot_loc) ) | |
664 { | |
665 /* right list is bigger */ | |
666 buffer_low[buff_stack_ctr] = pivot_loc + 1; | |
667 buffer_high[buff_stack_ctr] = high; | |
668 ++buff_stack_ctr; | |
669 high = pivot_loc - 1; | |
670 | |
671 } else { | |
672 /* left list is bigger */ | |
673 buffer_low[buff_stack_ctr] = low; | |
674 buffer_high[buff_stack_ctr] = pivot_loc - 1; | |
675 ++buff_stack_ctr; | |
676 low = pivot_loc + 1; | |
677 | |
678 } | |
679 } | |
680 } while( buff_stack_ctr != 0 ); | |
681 | |
682 return; | |
683 } | |
684 | |
685 /* | |
686 +-------------------------------------------------------------------------------+ | |
687 | PROJECT: PHB MODULE: DBM | | |
688 | ROUINE: search_clear_bit_in_bitmap | | |
689 +-------------------------------------------------------------------------------+ | |
690 | |
691 PURPOSE : Searches for the bit not set in record bitmap which | |
692 indicates free record | |
693 */ | |
694 UBYTE search_clear_bit_in_bitmap ( UBYTE* bitmap, | |
695 UBYTE bitmap_size ) | |
696 { | |
697 UBYTE* tmp_byte_ptr = bitmap + bitmap_size - 1 ; | |
698 UBYTE bitmap_num = 0, | |
699 bit_num, | |
700 tmp_byte; | |
701 | |
702 /* we will go byte by byte */ | |
703 while( bitmap_num < ( bitmap_size * MAX_BIT_POS ) ) | |
704 { | |
705 tmp_byte = *tmp_byte_ptr; | |
706 | |
707 for( bit_num = 0; bit_num < MAX_BIT_POS; ++bit_num ) | |
708 { | |
709 if( NOT (tmp_byte & 0x01) ) | |
710 { | |
711 return bitmap_num; | |
712 } | |
713 tmp_byte >>= 1; | |
714 ++bitmap_num; | |
715 } | |
716 | |
717 --tmp_byte_ptr; | |
718 } | |
719 | |
720 return bitmap_num; | |
721 | |
722 } | |
723 | |
724 /* | |
725 +--------------------------------------------------------------------+ | |
726 | PROJECT: PHB MODULE: DBM | | |
727 | ROUINE: set_bit_in_bitmap | | |
728 +--------------------------------------------------------------------+ | |
729 | |
730 PURPOSE : Sets a bit in record bitmap | |
731 */ | |
732 void set_bit_in_bitmap ( UBYTE* bitmap, | |
733 UBYTE bitmap_size, | |
734 UBYTE bit_num ) | |
735 { | |
736 bitmap[ bitmap_size - BITMAP_INDEX(bit_num) - 1 ] |= (0x01 << BIT_POS(bit_num) ); | |
737 } | |
738 | |
739 /* | |
740 +------------------------------------------------------------------------+ | |
741 | PROJECT: PHB MODULE: DBM | | |
742 | ROUINE: reset_bit_in_bitmap | | |
743 +------------------------------------------------------------------------+ | |
744 | |
745 PURPOSE : resets a bit in record bitmap | |
746 */ | |
747 void reset_bit_in_bitmap ( UBYTE* bitmap, | |
748 UBYTE bitmap_size, | |
749 UBYTE bit_num ) | |
750 { | |
751 bitmap[ bitmap_size - BITMAP_INDEX(bit_num) - 1 ] &= ~ (0x01 << BIT_POS(bit_num)); | |
752 } | |
753 | |
754 /* | |
755 +----------------------------------------------------------------------------------+ | |
756 | PROJECT: PHB MODULE: DBM | | |
757 | ROUINE: populate_sorted_list_from_FFS | | |
758 +----------------------------------------------------------------------------------+ | |
759 | |
760 PURPOSE : Reads the sorted list from FFS | |
761 */ | |
762 T_DB_CODE populate_sorted_list_from_FFS ( | |
763 | |
764 #ifdef FFS_CLOSE_BEFORE_OPEN | |
765 UBYTE db_ctr, | |
766 #endif | |
767 char* sort_file, | |
768 UBYTE num_of_elements, | |
769 UBYTE** sort_list_ptr ) | |
770 { | |
771 T_FFS_FD ffs_fd_sort_file; | |
772 T_FFS_SIZE ffs_ret_code; | |
773 UBYTE* sort_list; | |
774 | |
775 #ifdef FFS_CLOSE_BEFORE_OPEN | |
776 /* READ */ | |
777 if( db_open_full_for_read( db_ctr ) ) | |
778 { | |
779 db_close_for_read( db_ctr ); | |
780 } | |
781 #endif | |
782 | |
783 DB_FFS_OPEN( ffs_fd_sort_file, sort_file, FFS_O_RDONLY ); | |
784 | |
785 if( (ffs_fd_sort_file EQ EFFS_NAMETOOLONG ) OR | |
786 (ffs_fd_sort_file EQ EFFS_BADNAME ) OR | |
787 (ffs_fd_sort_file EQ EFFS_NOTFOUND ) OR | |
788 (ffs_fd_sort_file EQ EFFS_INVALID ) OR | |
789 (ffs_fd_sort_file EQ EFFS_LOCKED ) ) | |
790 | |
791 { | |
792 TRACE_EVENT_P1( "populate_sorted_list_from_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file ); | |
793 return DB_FAIL; | |
794 } | |
795 | |
796 if( ffs_fd_sort_file < EFFS_OK ) | |
797 { | |
798 LastFFS_ReturnCode = ffs_fd_sort_file; | |
799 TRACE_EVENT_P1( "populate_sorted_list_from_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file ); | |
800 return DB_FAIL_FS; | |
801 } | |
802 | |
803 /* This seek is not required as file pointer will be at start of file, | |
804 but ffs guide doesn't say so ! This needs to be clarified and | |
805 accordingly all ffs_seek at start of file after opening the file | |
806 can be removed ! */ | |
807 ffs_ret_code = ffs_seek( ffs_fd_sort_file, 0, FFS_SEEK_SET ); | |
808 | |
809 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
810 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
811 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
812 { | |
813 DB_FFS_CLOSE( ffs_fd_sort_file ); | |
814 TRACE_EVENT_P1( "populate_sorted_list_from_FFS:ffs_seek %d", ffs_ret_code ); | |
815 return DB_FAIL; | |
816 } | |
817 | |
818 | |
819 #ifndef INSERTION_SORT | |
820 | |
821 DB_MALLOC( sort_list, num_of_elements ); | |
822 memset( sort_list, INVALID_RECORD_NUM, num_of_elements ); | |
823 | |
824 #else /* INSERTION_SORT */ | |
825 | |
826 DB_MALLOC( sort_list, num_of_elements + 1 ); | |
827 memset( sort_list, INVALID_RECORD_NUM, num_of_elements + 1 ); | |
828 | |
829 #endif /* INSERTION_SORT */ | |
830 | |
831 ffs_ret_code = ffs_read( ffs_fd_sort_file, | |
832 sort_list, | |
833 num_of_elements ); | |
834 | |
835 if( (ffs_ret_code EQ EFFS_BADFD ) OR | |
836 (ffs_ret_code EQ EFFS_BADOP ) ) | |
837 { | |
838 DB_MFREE( sort_list ); | |
839 DB_FFS_CLOSE( ffs_fd_sort_file ); | |
840 TRACE_EVENT_P1( "populate_sorted_list_from_FFS:ffs_read %d", ffs_ret_code ); | |
841 return DB_FAIL; | |
842 } | |
843 | |
844 if( ffs_ret_code < EFFS_OK ) | |
845 { | |
846 LastFFS_ReturnCode = ffs_fd_sort_file; | |
847 DB_MFREE( sort_list ); | |
848 TRACE_EVENT_P1( "populate_sorted_list_from_FFS:ffs_read %d", ffs_ret_code ); | |
849 DB_FFS_CLOSE( ffs_fd_sort_file ); | |
850 return DB_FAIL_FS; | |
851 } | |
852 | |
853 DB_FFS_CLOSE( ffs_fd_sort_file ); | |
854 | |
855 /* to avoid memory leak */ | |
856 if( *sort_list_ptr NEQ NULL ) | |
857 DB_MFREE( *sort_list_ptr ); | |
858 | |
859 *sort_list_ptr = sort_list; | |
860 | |
861 return DB_OK; | |
862 } | |
863 | |
864 /* | |
865 +-----------------------------------------------------------------------------+ | |
866 | PROJECT: PHB MODULE: DBM | | |
867 | ROUINE: write_sorted_list_to_FFS | | |
868 +-----------------------------------------------------------------------------+ | |
869 | |
870 PURPOSE : Writes the sorted list into FFS | |
871 */ | |
872 T_DB_CODE write_sorted_list_to_FFS ( | |
873 | |
874 #ifdef FFS_CLOSE_BEFORE_OPEN | |
875 UBYTE db_ctr, | |
876 #endif | |
877 char* sort_file, | |
878 UBYTE num_of_elements, | |
879 UBYTE* sort_list ) | |
880 { | |
881 T_FFS_FD ffs_fd_sort_file; | |
882 T_FFS_SIZE ffs_ret_code; | |
883 | |
884 #ifdef FFS_CLOSE_BEFORE_OPEN | |
885 /* WRITE */ | |
886 if( db_open_full_for_write( db_ctr ) ) | |
887 { | |
888 db_close_for_write( db_ctr ); | |
889 } | |
890 #endif | |
891 | |
892 /* FFS_O_TRUNC => If file already exists and it is opened for writing, its | |
893 length is truncated to zero. */ | |
894 | |
895 DB_FFS_OPEN( ffs_fd_sort_file, sort_file, FFS_O_CREATE | FFS_O_WRONLY | FFS_O_TRUNC ); | |
896 | |
897 if( (ffs_fd_sort_file EQ EFFS_NAMETOOLONG ) OR | |
898 (ffs_fd_sort_file EQ EFFS_BADNAME ) ) | |
899 { | |
900 TRACE_EVENT_P1( "write_sorted_list_to_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file ); | |
901 return DB_FAIL; | |
902 } | |
903 | |
904 if( ffs_fd_sort_file < EFFS_OK ) | |
905 { | |
906 TRACE_EVENT_P1( "write_sorted_list_to_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file ); | |
907 LastFFS_ReturnCode = ffs_fd_sort_file; | |
908 return DB_FAIL_FS; | |
909 } | |
910 | |
911 | |
912 ffs_ret_code = ffs_seek( ffs_fd_sort_file, 0, FFS_SEEK_SET ); | |
913 | |
914 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
915 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
916 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
917 { | |
918 TRACE_EVENT_P1( "write_sorted_list_to_FFS:ffs_seek %d", ffs_ret_code ); | |
919 DB_FFS_CLOSE( ffs_fd_sort_file ); | |
920 return DB_FAIL; | |
921 } | |
922 | |
923 ffs_ret_code = ffs_write( ffs_fd_sort_file, | |
924 sort_list, | |
925 num_of_elements ); | |
926 | |
927 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
928 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
929 { | |
930 DB_FFS_CLOSE( ffs_fd_sort_file ); | |
931 ffs_ret_code = ffs_remove( sort_file ); | |
932 TRACE_EVENT_P1( "write_sorted_list_to_FFS:ffs_write %d", ffs_ret_code ); | |
933 return DB_FAIL; | |
934 } | |
935 | |
936 if( ffs_ret_code < EFFS_OK ) | |
937 { | |
938 LastFFS_ReturnCode = ffs_ret_code; | |
939 DB_FFS_CLOSE( ffs_fd_sort_file ); | |
940 ffs_ret_code = ffs_remove( sort_file ); | |
941 TRACE_EVENT_P1( "write_sorted_list_to_FFS:ffs_write %d", ffs_ret_code ); | |
942 return DB_FAIL_FS; | |
943 } | |
944 | |
945 DB_FFS_CLOSE( ffs_fd_sort_file ); /* yeah, we close it here ! */ | |
946 | |
947 return DB_OK; | |
948 | |
949 } | |
950 | |
951 /* | |
952 +--------------------------------------------------------------------+ | |
953 | PROJECT: PHB MODULE: DBM | | |
954 | ROUINE: search | | |
955 +--------------------------------------------------------------------+ | |
956 | |
957 PURPOSE : Searches for the record; uses binary search and compare | |
958 function is passed as a parameter. | |
959 */ | |
960 int search ( UBYTE* sort_list, | |
961 UBYTE num_of_elements, | |
962 UBYTE* order_num, | |
963 T_SEARCH_FUNC search_function, | |
964 ULONG flags, | |
965 const UBYTE* search_tag, | |
966 int db_handle, | |
967 USHORT field_id ) | |
968 { | |
969 /* Binary search is used */ | |
970 UBYTE top, | |
971 bottom, | |
972 middle; | |
973 | |
974 S8 result; | |
975 | |
976 /* Strictly speaking, this check is not required, but | |
977 it would save some processing time */ | |
978 if( num_of_elements EQ 0 ) | |
979 return SEARCH_FAILED; | |
980 | |
981 if( (*order_num) EQ 0 ) | |
982 { | |
983 /* Complete list search */ | |
984 top = num_of_elements - 1; | |
985 bottom = 0; | |
986 | |
987 } else { | |
988 | |
989 /* Strictly speaking, this check is not required, but | |
990 it would save some processing time */ | |
991 if( *order_num >= num_of_elements ) | |
992 return SEARCH_FAILED; | |
993 | |
994 /* Give the next element in sort list if matching */ | |
995 if( search_function( flags, | |
996 search_tag, | |
997 db_handle, | |
998 field_id, | |
999 sort_list[ (*order_num) ] ) | |
1000 EQ 0 ) | |
1001 { | |
1002 *order_num += 1; | |
1003 return *order_num; | |
1004 } | |
1005 | |
1006 return SEARCH_FAILED; | |
1007 } | |
1008 | |
1009 if( num_of_elements EQ 2 ) | |
1010 { | |
1011 /* Special case of two elements */ | |
1012 | |
1013 if( search_function( flags, | |
1014 search_tag, | |
1015 db_handle, | |
1016 field_id, | |
1017 sort_list[ 0 ] ) | |
1018 EQ 0 ) | |
1019 { | |
1020 *order_num = 1; | |
1021 return 1; | |
1022 } | |
1023 | |
1024 if( search_function( flags, | |
1025 search_tag, | |
1026 db_handle, | |
1027 field_id, | |
1028 sort_list[ 1 ] ) | |
1029 EQ 0 ) | |
1030 { | |
1031 *order_num = 2; | |
1032 return 2; | |
1033 } | |
1034 | |
1035 return SEARCH_FAILED; | |
1036 } | |
1037 | |
1038 /* basic concept is here is to get first matching element in sort list and | |
1039 so we need to compare bottom_th element for returning */ | |
1040 | |
1041 while( top >= bottom ) | |
1042 { | |
1043 /* if bottom_th element match, return PASS */ | |
1044 if( search_function( flags, | |
1045 search_tag, | |
1046 db_handle, | |
1047 field_id, | |
1048 sort_list[ bottom ] ) | |
1049 EQ 0 ) | |
1050 { | |
1051 *order_num = bottom + 1; | |
1052 return *order_num; | |
1053 } | |
1054 | |
1055 /* end of list */ | |
1056 if( bottom EQ top ) | |
1057 return SEARCH_FAILED; | |
1058 | |
1059 /* now binary search comes into play */ | |
1060 | |
1061 middle = (top + bottom) / 2; | |
1062 | |
1063 result = search_function( flags, | |
1064 search_tag, | |
1065 db_handle, | |
1066 field_id, | |
1067 sort_list[ middle ] ); | |
1068 | |
1069 if( result EQ 0 ) | |
1070 { | |
1071 ++bottom; | |
1072 | |
1073 if( bottom EQ middle ) | |
1074 { | |
1075 /* middle has already matched so, | |
1076 instead of going to next loop, we return PASS here ! */ | |
1077 *order_num = bottom + 1; | |
1078 return *order_num; | |
1079 } | |
1080 | |
1081 top = middle; | |
1082 | |
1083 } else { | |
1084 | |
1085 if( result > 0 ) | |
1086 { | |
1087 ++bottom; | |
1088 | |
1089 } else { | |
1090 | |
1091 bottom = middle + 1; | |
1092 | |
1093 } | |
1094 | |
1095 } /* result EQ 0 */ | |
1096 | |
1097 } /* while top >= bottom */ | |
1098 | |
1099 return SEARCH_FAILED; | |
1100 | |
1101 } | |
1102 | |
1103 | |
1104 /* | |
1105 +-----------------------------------------------------------------------------+ | |
1106 | PROJECT: PHB MODULE: DBM | | |
1107 | ROUINE: update_field_data_in_FFS | | |
1108 +-----------------------------------------------------------------------------+ | |
1109 | |
1110 PURPOSE : Updates elementary file data in FFS | |
1111 */ | |
1112 T_DB_CODE update_field_data_in_FFS ( const char* field_file, | |
1113 T_FFS_FD* filehandle, | |
1114 #ifdef FFS_CLOSE_BEFORE_OPEN | |
1115 UBYTE db_ctr, | |
1116 #endif | |
1117 UBYTE fld_ctr, | |
1118 UBYTE field_data_max_size, | |
1119 UBYTE* field_data, | |
1120 USHORT offset, | |
1121 USHORT length ) | |
1122 { | |
1123 T_FFS_FD ffs_fd = *filehandle; | |
1124 T_FFS_SIZE ffs_ret_code; | |
1125 | |
1126 /* Updating field data in FFS in file "field_file" */ | |
1127 | |
1128 if( ffs_fd EQ NULL ) | |
1129 { | |
1130 DB_FFS_OPEN( ffs_fd, field_file, FFS_O_WRONLY ); | |
1131 | |
1132 if( ( ffs_fd EQ EFFS_NOTFOUND ) OR | |
1133 ( ffs_fd EQ EFFS_NAMETOOLONG ) OR | |
1134 ( ffs_fd EQ EFFS_BADNAME ) OR | |
1135 ( ffs_fd EQ EFFS_INVALID ) ) | |
1136 { | |
1137 TRACE_EVENT_P1( "update_field_data_in_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1138 return DB_FAIL; | |
1139 } | |
1140 | |
1141 if( ffs_fd < EFFS_OK ) | |
1142 { | |
1143 LastFFS_ReturnCode = ffs_fd; | |
1144 TRACE_EVENT_P1( "update_field_data_in_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1145 return DB_FAIL_FS; | |
1146 } | |
1147 | |
1148 *filehandle = ffs_fd; | |
1149 | |
1150 } /* filehandle EQ NULL ? */ | |
1151 | |
1152 /* Seek the file to fld_ctr position to update the entry */ | |
1153 ffs_ret_code = ffs_seek( ffs_fd, | |
1154 ( fld_ctr * field_data_max_size ) + offset, | |
1155 FFS_SEEK_SET ); | |
1156 | |
1157 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
1158 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
1159 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
1160 { | |
1161 TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_seek %d", ffs_ret_code ); | |
1162 DB_FFS_CLOSE( ffs_fd ); | |
1163 *filehandle = NULL; | |
1164 return DB_FAIL; | |
1165 } | |
1166 | |
1167 if( ffs_ret_code < EFFS_OK ) | |
1168 { | |
1169 TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_seek %d", ffs_ret_code ); | |
1170 LastFFS_ReturnCode = ffs_ret_code; | |
1171 DB_FFS_CLOSE( ffs_fd ); | |
1172 *filehandle = NULL; | |
1173 return DB_FAIL_FS; | |
1174 } | |
1175 | |
1176 /* clean is reset in memset, so no processing for it | |
1177 (in case of non-tracked database, anyway we ignore it ! */ | |
1178 | |
1179 ffs_ret_code = ffs_write( ffs_fd, | |
1180 field_data, | |
1181 length ); | |
1182 | |
1183 if( (ffs_ret_code EQ EFFS_BADFD ) OR | |
1184 (ffs_ret_code EQ EFFS_BADOP ) ) | |
1185 { | |
1186 TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_write %d", ffs_ret_code ); | |
1187 DB_FFS_CLOSE( ffs_fd ); | |
1188 *filehandle = NULL; | |
1189 return DB_FAIL; | |
1190 } | |
1191 | |
1192 if( ffs_ret_code < EFFS_OK ) | |
1193 { | |
1194 TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_write %d", ffs_ret_code ); | |
1195 DB_FFS_CLOSE ( ffs_fd ); | |
1196 *filehandle = NULL; | |
1197 LastFFS_ReturnCode = ffs_ret_code; | |
1198 return DB_FAIL_FS; | |
1199 } | |
1200 | |
1201 /* DB_FFS_CLOSE( ffs_fd ); we will do it in db_flush */ | |
1202 /* updation is over */ | |
1203 | |
1204 #ifdef FFS_OPEN_PROBLEM_PATCH | |
1205 DB_FFS_CLOSE( ffs_fd ); | |
1206 *filehandle = NULL; | |
1207 #endif | |
1208 | |
1209 #ifndef FFS_CLOSE_BEFORE_OPEN | |
1210 /* this is db file, but we do not close it */ | |
1211 #endif | |
1212 | |
1213 return DB_OK; | |
1214 | |
1215 } | |
1216 | |
1217 /* | |
1218 +--------------------------------------------------------------------+ | |
1219 | PROJECT: PHB MODULE: DBM | | |
1220 | ROUINE: cal_NextRecordNum | | |
1221 +--------------------------------------------------------------------+ | |
1222 | |
1223 PURPOSE : Reads the status of the file and returns | |
1224 the next available record (position) | |
1225 */ | |
1226 UBYTE cal_NextRecordNum ( const char* db_directory, | |
1227 USHORT field_id, | |
1228 USHORT record_size ) | |
1229 { | |
1230 char user_field_file[FILENAME_LEN]; | |
1231 | |
1232 T_FFS_SIZE ffs_ret_code; | |
1233 T_FFS_STAT ffs_file_stat; | |
1234 | |
1235 sprintf( user_field_file, | |
1236 "%s/UD_%d", | |
1237 db_directory, | |
1238 field_id ); | |
1239 | |
1240 ffs_ret_code = ffs_stat( user_field_file, &ffs_file_stat ); | |
1241 | |
1242 if( ffs_ret_code EQ EFFS_OK ) | |
1243 { | |
1244 return ( (ffs_file_stat.size / record_size) + 1); | |
1245 } | |
1246 | |
1247 if( ffs_ret_code EQ EFFS_NOTFOUND ) | |
1248 { | |
1249 TRACE_EVENT( "cal_NextRecordNum:ffs_stat:FILE NOT FOUND" ); | |
1250 return 1; | |
1251 } | |
1252 | |
1253 /* this is a problem with user_field_file, raise an error and | |
1254 return 0 */ | |
1255 | |
1256 TRACE_ERROR( "cal_NextRecordNum: PROBLEM with user_field_file" ); | |
1257 TRACE_EVENT_P1( "cal_NextRecordNum:ffs_stat %d", ffs_ret_code ); | |
1258 return 1; | |
1259 | |
1260 } | |
1261 | |
1262 | |
1263 /* | |
1264 +------------------------------------------------------------------------------+ | |
1265 | PROJECT: PHB MODULE: DBM | | |
1266 | ROUINE: read_user_record_from_FFS | | |
1267 +------------------------------------------------------------------------------+ | |
1268 | |
1269 PURPOSE : Reads a user record from FFS | |
1270 */ | |
1271 T_DB_CODE read_user_record_from_FFS ( const char* user_field_file, | |
1272 | |
1273 #ifdef FFS_CLOSE_BEFORE_OPEN | |
1274 UBYTE db_ctr, | |
1275 UBYTE fld_ctr, | |
1276 #endif | |
1277 T_FFS_FD* filehandle, | |
1278 UBYTE record_num, | |
1279 USHORT record_size, | |
1280 USHORT offset, | |
1281 USHORT length, | |
1282 UBYTE* record_buffer ) | |
1283 { | |
1284 T_FFS_FD ffs_fd = NULL; | |
1285 T_FFS_SIZE ffs_ret_code; | |
1286 | |
1287 /* See if file already opened, | |
1288 if not open it and update the file handle */ | |
1289 | |
1290 #ifndef FFS_CLOSE_BEFORE_OPEN | |
1291 ffs_fd = *filehandle; | |
1292 | |
1293 if( ffs_fd EQ NULL ) | |
1294 { | |
1295 DB_FFS_OPEN( ffs_fd, user_field_file, FFS_O_RDONLY ); | |
1296 | |
1297 if( (ffs_fd EQ EFFS_NOTFOUND) OR | |
1298 (ffs_fd EQ EFFS_NAMETOOLONG) OR | |
1299 (ffs_fd EQ EFFS_BADNAME) OR | |
1300 (ffs_fd EQ EFFS_INVALID) OR | |
1301 (ffs_fd EQ EFFS_LOCKED) ) | |
1302 { | |
1303 TRACE_EVENT_P1( "read_user_record_from_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1304 return DB_FAIL; | |
1305 } | |
1306 | |
1307 if( ffs_fd < EFFS_OK ) | |
1308 { | |
1309 TRACE_EVENT_P1( "read_user_record_from_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1310 LastFFS_ReturnCode = ffs_fd; | |
1311 return DB_FAIL_FS; | |
1312 } | |
1313 | |
1314 *filehandle = ffs_fd; | |
1315 } | |
1316 | |
1317 #else /* FFS_CLOSE_BEFORE_OPEN */ | |
1318 | |
1319 ffs_fd = db_open_user_field_file( db_ctr, fld_ctr, user_field_file, FFS_O_RDONLY ); | |
1320 | |
1321 #endif /* FFS_CLOSE_BEFORE_OPEN */ | |
1322 | |
1323 ffs_ret_code = ffs_seek( ffs_fd, | |
1324 ( (record_num - 1) * (record_size) + offset), | |
1325 FFS_SEEK_SET ); | |
1326 | |
1327 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
1328 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
1329 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
1330 { | |
1331 TRACE_EVENT_P1( "read_user_record_from_FFS:ffs_seek %d", ffs_ret_code ); | |
1332 DB_FFS_CLOSE( ffs_fd ); | |
1333 *filehandle = NULL; | |
1334 return DB_FAIL; | |
1335 } | |
1336 | |
1337 if( ffs_ret_code < EFFS_OK ) | |
1338 { | |
1339 TRACE_EVENT_P1( "read_user_record_from_FFS:ffs_seek %d", ffs_ret_code ); | |
1340 LastFFS_ReturnCode = ffs_ret_code; | |
1341 DB_FFS_CLOSE( ffs_fd ); | |
1342 *filehandle = NULL; | |
1343 return DB_FAIL_FS; | |
1344 } | |
1345 | |
1346 ffs_ret_code = ffs_read( ffs_fd, | |
1347 record_buffer, | |
1348 length ); | |
1349 | |
1350 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
1351 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
1352 { | |
1353 TRACE_EVENT_P1( "read_user_record_from_FFS:ffs_read %d", ffs_ret_code ); | |
1354 DB_FFS_CLOSE( ffs_fd ); | |
1355 *filehandle = NULL; | |
1356 return DB_FAIL; | |
1357 } | |
1358 | |
1359 if( ffs_ret_code < EFFS_OK ) | |
1360 { | |
1361 TRACE_EVENT_P1( "read_user_record_from_FFS:ffs_read %d", ffs_ret_code ); | |
1362 LastFFS_ReturnCode = ffs_ret_code; | |
1363 DB_FFS_CLOSE( ffs_fd ); | |
1364 *filehandle = NULL; | |
1365 return DB_FAIL_FS; | |
1366 } | |
1367 | |
1368 /* DB_FFS_CLOSE( ffs_fd ); we will do it in db_flush */ | |
1369 | |
1370 #ifdef FFS_OPEN_PROBLEM_PATCH | |
1371 DB_FFS_CLOSE( ffs_fd ); | |
1372 *filehandle = NULL; | |
1373 #endif | |
1374 | |
1375 return DB_OK; | |
1376 } | |
1377 | |
1378 /* | |
1379 +-------------------------------------------------------------------------------+ | |
1380 | PROJECT: PHB MODULE: DBM | | |
1381 | ROUINE: write_user_record_to_FFS | | |
1382 +-------------------------------------------------------------------------------+ | |
1383 | |
1384 PURPOSE : Writes user record into FFS | |
1385 */ | |
1386 T_DB_CODE write_user_record_to_FFS ( const char* user_field_file, | |
1387 | |
1388 #ifdef FFS_CLOSE_BEFORE_OPEN | |
1389 UBYTE db_ctr, | |
1390 UBYTE fld_ctr, | |
1391 #endif | |
1392 T_FFS_FD* filehandle, | |
1393 UBYTE record_num, | |
1394 USHORT record_size, | |
1395 USHORT offset, | |
1396 USHORT length, | |
1397 UBYTE* record_buffer ) | |
1398 { | |
1399 T_FFS_FD ffs_fd = NULL; | |
1400 T_FFS_SIZE ffs_ret_code; | |
1401 | |
1402 /* See if file already opened, | |
1403 if not open it and update the file handle */ | |
1404 | |
1405 #ifndef FFS_CLOSE_BEFORE_OPEN | |
1406 ffs_fd = *filehandle; | |
1407 | |
1408 if( ffs_fd EQ NULL ) | |
1409 { | |
1410 DB_FFS_OPEN( ffs_fd, user_field_file, FFS_O_RDWR ); | |
1411 | |
1412 if( (ffs_fd EQ EFFS_NOTFOUND) OR | |
1413 (ffs_fd EQ EFFS_NAMETOOLONG) OR | |
1414 (ffs_fd EQ EFFS_BADNAME) OR | |
1415 (ffs_fd EQ EFFS_INVALID) OR | |
1416 (ffs_fd EQ EFFS_LOCKED) ) | |
1417 { | |
1418 TRACE_EVENT_P1( "write_user_record_to_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1419 return DB_FAIL; | |
1420 } | |
1421 | |
1422 if( ffs_fd < EFFS_OK ) | |
1423 { | |
1424 TRACE_EVENT_P1( "write_user_record_to_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1425 LastFFS_ReturnCode = ffs_fd; | |
1426 return DB_FAIL_FS; | |
1427 } | |
1428 | |
1429 *filehandle = ffs_fd; | |
1430 } | |
1431 | |
1432 #else /* FFS_CLOSE_BEFORE_OPEN */ | |
1433 | |
1434 ffs_fd = db_open_user_field_file( db_ctr, fld_ctr, user_field_file, FFS_O_RDWR ); | |
1435 | |
1436 #endif /* FFS_CLOSE_BEFORE_OPEN */ | |
1437 | |
1438 ffs_ret_code = ffs_seek( ffs_fd, | |
1439 ( (record_num - 1) * (record_size) + offset), | |
1440 FFS_SEEK_SET ); | |
1441 | |
1442 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
1443 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
1444 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
1445 { | |
1446 TRACE_EVENT_P1( "write_user_record_to_FFS:ffs_seek %d", ffs_ret_code ); | |
1447 DB_FFS_CLOSE( ffs_fd ); | |
1448 *filehandle = NULL; | |
1449 return DB_FAIL; | |
1450 } | |
1451 | |
1452 if( ffs_ret_code < EFFS_OK ) | |
1453 { | |
1454 TRACE_EVENT_P1( "write_user_record_to_FFS:ffs_seek %d", ffs_ret_code ); | |
1455 LastFFS_ReturnCode = ffs_ret_code; | |
1456 DB_FFS_CLOSE( ffs_fd ); | |
1457 *filehandle = NULL; | |
1458 return DB_FAIL_FS; | |
1459 } | |
1460 | |
1461 ffs_ret_code = ffs_write( ffs_fd, | |
1462 record_buffer, | |
1463 length ); | |
1464 | |
1465 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
1466 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
1467 { | |
1468 TRACE_EVENT_P1( "write_user_record_to_FFS:ffs_write %d", ffs_ret_code ); | |
1469 DB_FFS_CLOSE( ffs_fd ); | |
1470 *filehandle = NULL; | |
1471 return DB_FAIL; | |
1472 } | |
1473 | |
1474 if( ffs_ret_code < EFFS_OK ) | |
1475 { | |
1476 TRACE_EVENT_P1( "write_user_record_to_FFS:ffs_write %d", ffs_ret_code ); | |
1477 LastFFS_ReturnCode = ffs_ret_code; | |
1478 DB_FFS_CLOSE( ffs_fd ); | |
1479 *filehandle = NULL; | |
1480 return DB_FAIL_FS; | |
1481 } | |
1482 | |
1483 /* DB_FFS_CLOSE( ffs_fd ); we will do it in db_flush */ | |
1484 | |
1485 #ifdef FFS_OPEN_PROBLEM_PATCH | |
1486 DB_FFS_CLOSE( ffs_fd ); | |
1487 *filehandle = NULL; | |
1488 #endif | |
1489 | |
1490 return DB_OK; | |
1491 } | |
1492 | |
1493 /* | |
1494 +-----------------------------------------------------------------------------+ | |
1495 | PROJECT: PHB MODULE: DBM | | |
1496 | ROUINE: delete_file_dir_from_FFS | | |
1497 +-----------------------------------------------------------------------------+ | |
1498 | |
1499 PURPOSE : Deletes a file from FFS | |
1500 */ | |
1501 T_DB_CODE delete_file_dir_from_FFS ( const char* filename ) | |
1502 { | |
1503 T_FFS_SIZE ffs_ret_code; | |
1504 | |
1505 TRACE_EVENT_P1( "delete_file_dir_from_FFS %s", filename ); | |
1506 | |
1507 ffs_ret_code = ffs_remove( filename ); | |
1508 | |
1509 #ifdef FORCED_DIR_REMOVAL | |
1510 | |
1511 if( ffs_ret_code EQ EFFS_DIRNOTEMPTY ) | |
1512 { | |
1513 TRACE_EVENT( "Inconsistency; going for delete_dir_forced" ); | |
1514 return delete_dir_forced( filename ); | |
1515 } | |
1516 | |
1517 #endif | |
1518 | |
1519 if( ffs_ret_code EQ EFFS_NOTFOUND ) | |
1520 { | |
1521 TRACE_EVENT( "delete_file_dir_from_FFS:ffs_remove:FILE NOT FOUND" ); | |
1522 return DB_OK; | |
1523 } | |
1524 | |
1525 if( ( ffs_ret_code EQ EFFS_ACCESS ) OR | |
1526 ( ffs_ret_code EQ EFFS_LOCKED ) ) | |
1527 { | |
1528 TRACE_EVENT_P1( "delete_file_dir_from_FFS:ffs_remove %d", ffs_ret_code ); | |
1529 return DB_FAIL; | |
1530 } | |
1531 | |
1532 if( ffs_ret_code < EFFS_OK ) | |
1533 { | |
1534 TRACE_EVENT_P1( "delete_file_dir_from_FFS:ffs_remove %d", ffs_ret_code ); | |
1535 LastFFS_ReturnCode = ffs_ret_code; | |
1536 return DB_FAIL_FS; | |
1537 } | |
1538 | |
1539 return DB_OK; | |
1540 | |
1541 } | |
1542 | |
1543 /* | |
1544 +---------------------------------------------------------------------------+ | |
1545 | PROJECT: PHB MODULE: DBM | | |
1546 | ROUINE: update_dbm_data_in_FFS | | |
1547 +---------------------------------------------------------------------------+ | |
1548 | |
1549 PURPOSE : Updates the database manager information of a | |
1550 particular database | |
1551 */ | |
1552 T_DB_CODE update_dbm_data_in_FFS ( const char* filename, | |
1553 UBYTE db_ctr, | |
1554 UBYTE db_data_max_size, | |
1555 UBYTE* db_data, | |
1556 USHORT offset, | |
1557 USHORT length ) | |
1558 { | |
1559 T_FFS_FD ffs_fd = NULL; | |
1560 T_FFS_SIZE ffs_ret_code; | |
1561 | |
1562 /* See if file already opened, | |
1563 if not open it and update the file handle */ | |
1564 | |
1565 #ifdef FFS_CLOSE_BEFORE_OPEN | |
1566 /* WRITE */ | |
1567 if( db_open_full_for_write( db_ctr ) ) | |
1568 { | |
1569 db_close_for_write( db_ctr ); | |
1570 } | |
1571 #endif | |
1572 | |
1573 DB_FFS_OPEN( ffs_fd, filename, FFS_O_WRONLY ); | |
1574 | |
1575 if( ( ffs_fd EQ EFFS_NAMETOOLONG ) OR | |
1576 ( ffs_fd EQ EFFS_BADNAME ) OR | |
1577 ( ffs_fd EQ EFFS_NOTFOUND ) OR | |
1578 ( ffs_fd EQ EFFS_INVALID ) OR | |
1579 ( ffs_fd EQ EFFS_LOCKED ) ) | |
1580 { | |
1581 TRACE_EVENT_P1( "update_dbm_data_in_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1582 return DB_FAIL; | |
1583 } | |
1584 | |
1585 if( ffs_fd < EFFS_OK ) | |
1586 { | |
1587 TRACE_EVENT_P1( "update_dbm_data_in_FFS:DB_FFS_OPEN %d", ffs_fd ); | |
1588 LastFFS_ReturnCode = ffs_fd; | |
1589 return DB_FAIL_FS; | |
1590 } | |
1591 | |
1592 ffs_ret_code = ffs_seek( ffs_fd, db_ctr * db_data_max_size, FFS_SEEK_SET ); | |
1593 | |
1594 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
1595 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
1596 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
1597 { | |
1598 TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_seek %d", ffs_ret_code ); | |
1599 DB_FFS_CLOSE( ffs_fd ); | |
1600 return DB_FAIL; | |
1601 } | |
1602 | |
1603 if( ffs_ret_code < EFFS_OK ) | |
1604 { | |
1605 TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_seek %d", ffs_ret_code ); | |
1606 LastFFS_ReturnCode = ffs_ret_code; | |
1607 DB_FFS_CLOSE( ffs_fd ); | |
1608 return DB_FAIL_FS; | |
1609 } | |
1610 | |
1611 ffs_ret_code = ffs_write( ffs_fd, db_data, db_data_max_size ); | |
1612 | |
1613 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
1614 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
1615 { | |
1616 TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_write %d", ffs_ret_code ); | |
1617 DB_FFS_CLOSE( ffs_fd ); | |
1618 return DB_FAIL; | |
1619 } | |
1620 | |
1621 if( ffs_ret_code < EFFS_OK ) | |
1622 { | |
1623 TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_write %d", ffs_ret_code ); | |
1624 DB_FFS_CLOSE( ffs_fd ); | |
1625 LastFFS_ReturnCode = ffs_ret_code; | |
1626 return DB_FAIL_FS; | |
1627 } | |
1628 | |
1629 DB_FFS_CLOSE( ffs_fd ); /* yeah, DB file, so ok to close it here ! */ | |
1630 | |
1631 /* updation of dbm data done */ | |
1632 | |
1633 return DB_OK; | |
1634 } | |
1635 | |
1636 /* | |
1637 +--------------------------------------------------------------------------+ | |
1638 | PROJECT: PHB MODULE: DBM | | |
1639 | ROUINE: remove_field_from_FFS | | |
1640 +--------------------------------------------------------------------------+ | |
1641 | |
1642 PURPOSE : Removes the elementary file and associated Index | |
1643 file from FFS | |
1644 */ | |
1645 T_DB_CODE remove_field_from_FFS ( UBYTE db_ctr, | |
1646 UBYTE fld_ctr ) | |
1647 { | |
1648 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
1649 char user_field_file[FILENAME_LEN], | |
1650 sort_file[FILENAME_LEN]; | |
1651 T_DB_CODE db_ret_code; | |
1652 UBYTE sort_index_ctr; | |
1653 | |
1654 /* Assumed that DBState is not IN_USE */ | |
1655 | |
1656 tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr; | |
1657 | |
1658 if( tmp_ptrFieldRecord -> FieldID EQ INVALID_FIELD_ID ) /* if not valid field id */ | |
1659 return DB_OK; | |
1660 | |
1661 /* Close of user record files not required as DBState is not IN_USE */ | |
1662 | |
1663 /* Delete file "<DBDirectory>/UD_<field_id>" */ | |
1664 | |
1665 sprintf( user_field_file, | |
1666 "%s/UD_%d", | |
1667 DbmMaster[db_ctr].DBDirectory, | |
1668 tmp_ptrFieldRecord -> FieldID ); | |
1669 | |
1670 db_ret_code = delete_file_dir_from_FFS ( user_field_file ); | |
1671 | |
1672 if( db_ret_code NEQ DB_OK ) | |
1673 return db_ret_code; | |
1674 | |
1675 /* For sorted lists */ | |
1676 | |
1677 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
1678 { | |
1679 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX ) | |
1680 { | |
1681 /* Sort file, "<DBDirectory>/UD_<field_id>_sort_<sort_index>" */ | |
1682 | |
1683 sprintf( sort_file, | |
1684 "%s/UD_%d_sort_%d", | |
1685 DbmMaster[db_ctr].DBDirectory, | |
1686 tmp_ptrFieldRecord -> FieldID, | |
1687 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] ); | |
1688 | |
1689 db_ret_code = delete_file_dir_from_FFS ( sort_file ); | |
1690 | |
1691 if( db_ret_code NEQ DB_OK ) | |
1692 return db_ret_code; | |
1693 } | |
1694 } | |
1695 | |
1696 return DB_OK; | |
1697 | |
1698 } | |
1699 | |
1700 | |
1701 | |
1702 #ifdef FFS_CLOSE_BEFORE_OPEN | |
1703 | |
1704 T_FFS_FD db_open_user_field_file ( UBYTE db_ctr, | |
1705 UBYTE fld_ctr, | |
1706 const char* user_field_file, | |
1707 T_FFS_OPEN_FLAGS open_option ) | |
1708 { | |
1709 UBYTE i; | |
1710 FileHandleRecord* tmp_open_fields; | |
1711 UBYTE* tmp_old; | |
1712 UBYTE tmp_max; | |
1713 | |
1714 /* sanity checks not done (db_ctr >= MAX_DBs OR fld_ctr EQ INVALID_FLD_CTR) */ | |
1715 | |
1716 /* note that we store field counters and not field ids */ | |
1717 | |
1718 /* Search in write/read list */ | |
1719 for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i ) | |
1720 { | |
1721 if( DbmMaster[db_ctr].WRITE_OPEN_FIELDS[i].fld_ctr EQ fld_ctr ) | |
1722 return DbmMaster[db_ctr].WRITE_OPEN_FIELDS[i].filehandle; | |
1723 } /* for */ | |
1724 | |
1725 /* Search in read only list */ | |
1726 for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i ) | |
1727 { | |
1728 if( DbmMaster[db_ctr].READ_OPEN_FIELDS[i].fld_ctr EQ fld_ctr ) | |
1729 { | |
1730 if( NOT ( open_option & FFS_O_WRONLY ) ) /* if not opened for writing */ | |
1731 { | |
1732 return DbmMaster[db_ctr].READ_OPEN_FIELDS[i].filehandle; | |
1733 } | |
1734 | |
1735 /* we need to reopen it in write mode */ | |
1736 DB_FFS_CLOSE( DbmMaster[db_ctr].READ_OPEN_FIELDS[i].filehandle ); | |
1737 | |
1738 DbmMaster[db_ctr].READ_OPEN_FIELDS[i].fld_ctr = INVALID_FLD_CTR; | |
1739 | |
1740 break; | |
1741 | |
1742 } | |
1743 } /* for */ | |
1744 | |
1745 /* field is not present in both lists */ | |
1746 | |
1747 if( open_option & FFS_O_WRONLY ) | |
1748 { | |
1749 | |
1750 /* for writing and reading both */ | |
1751 tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS; | |
1752 tmp_old = &(DbmMaster[db_ctr].old_write); | |
1753 tmp_max = MAX_OPEN_WRITE_PER_DB; | |
1754 | |
1755 } else { | |
1756 | |
1757 /* for reading only */ | |
1758 tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS; | |
1759 tmp_old = &(DbmMaster[db_ctr].old_read); | |
1760 tmp_max = MAX_OPEN_READ_PER_DB; | |
1761 } | |
1762 | |
1763 | |
1764 /* search the list */ | |
1765 for( i = 0; i < tmp_max; ++i ) | |
1766 { | |
1767 if( tmp_open_fields[i].fld_ctr EQ INVALID_FLD_CTR ) | |
1768 { | |
1769 DB_FFS_OPEN( tmp_open_fields[i].filehandle, | |
1770 user_field_file, | |
1771 open_option ); | |
1772 | |
1773 tmp_open_fields[i].fld_ctr = fld_ctr; | |
1774 | |
1775 return tmp_open_fields[i].filehandle; | |
1776 } | |
1777 } /* for */ | |
1778 | |
1779 /* we need to close the some file for opening this */ | |
1780 | |
1781 if( *tmp_old >= tmp_max ) | |
1782 *tmp_old = 0; | |
1783 | |
1784 DB_FFS_CLOSE( tmp_open_fields[*tmp_old].filehandle ); | |
1785 | |
1786 DB_FFS_OPEN( tmp_open_fields[*tmp_old].filehandle, | |
1787 user_field_file, | |
1788 open_option ); | |
1789 | |
1790 if( tmp_open_fields[*tmp_old].filehandle >= EFFS_OK ) | |
1791 { | |
1792 tmp_open_fields[*tmp_old].fld_ctr = fld_ctr; | |
1793 ++(*tmp_old); | |
1794 return tmp_open_fields[*tmp_old - 1].filehandle; | |
1795 } | |
1796 | |
1797 tmp_open_fields[*tmp_old].fld_ctr = INVALID_FLD_CTR; | |
1798 | |
1799 return tmp_open_fields[*tmp_old].filehandle; | |
1800 | |
1801 } | |
1802 | |
1803 void db_close_user_field_files ( UBYTE db_ctr ) | |
1804 { | |
1805 UBYTE i; | |
1806 FileHandleRecord* tmp_open_fields; | |
1807 | |
1808 /* sanity check not done */ | |
1809 | |
1810 /* for write list */ | |
1811 | |
1812 tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS; | |
1813 | |
1814 for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i ) | |
1815 { | |
1816 if( tmp_open_fields[i].fld_ctr NEQ INVALID_FLD_CTR ) | |
1817 { | |
1818 DB_FFS_CLOSE( tmp_open_fields[i].filehandle ); | |
1819 tmp_open_fields[i].fld_ctr = INVALID_FLD_CTR; | |
1820 } | |
1821 } | |
1822 | |
1823 /* for read list */ | |
1824 | |
1825 tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS; | |
1826 | |
1827 for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i ) | |
1828 { | |
1829 if( tmp_open_fields[i].fld_ctr NEQ INVALID_FLD_CTR ) | |
1830 { | |
1831 DB_FFS_CLOSE( tmp_open_fields[i].filehandle ); | |
1832 tmp_open_fields[i].fld_ctr = INVALID_FLD_CTR; | |
1833 } | |
1834 } | |
1835 | |
1836 } | |
1837 | |
1838 BOOL db_open_full_for_read ( UBYTE db_ctr ) | |
1839 { | |
1840 UBYTE i; | |
1841 FileHandleRecord* tmp_open_fields; | |
1842 | |
1843 /* sanity check not done */ | |
1844 | |
1845 /* for read list */ | |
1846 | |
1847 tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS; | |
1848 | |
1849 for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i ) | |
1850 { | |
1851 if( tmp_open_fields[i].fld_ctr EQ INVALID_FLD_CTR ) | |
1852 return FALSE; | |
1853 } | |
1854 | |
1855 return TRUE; | |
1856 } | |
1857 | |
1858 BOOL db_open_full_for_write ( UBYTE db_ctr ) | |
1859 { | |
1860 UBYTE i; | |
1861 FileHandleRecord* tmp_open_fields; | |
1862 | |
1863 /* sanity check not done */ | |
1864 | |
1865 /* for write list */ | |
1866 | |
1867 tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS; | |
1868 | |
1869 for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i ) | |
1870 { | |
1871 if( tmp_open_fields[i].fld_ctr EQ INVALID_FLD_CTR ) | |
1872 return FALSE; | |
1873 } | |
1874 | |
1875 return TRUE; | |
1876 } | |
1877 | |
1878 void db_close_for_read ( UBYTE db_ctr ) | |
1879 { | |
1880 FileHandleRecord* tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS; | |
1881 UBYTE *tmp_old = &(DbmMaster[db_ctr].old_read); | |
1882 | |
1883 /* sanity check not done */ | |
1884 | |
1885 /* for read list */ | |
1886 | |
1887 if( *tmp_old >= MAX_OPEN_READ_PER_DB ) | |
1888 *tmp_old = 0; | |
1889 | |
1890 DB_FFS_CLOSE( tmp_open_fields[*tmp_old].filehandle ); | |
1891 | |
1892 tmp_open_fields[*tmp_old].fld_ctr = INVALID_FLD_CTR; | |
1893 | |
1894 ++(*tmp_old); | |
1895 | |
1896 return; | |
1897 | |
1898 } | |
1899 | |
1900 void db_close_for_write ( UBYTE db_ctr ) | |
1901 { | |
1902 FileHandleRecord* tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS; | |
1903 UBYTE *tmp_old = &(DbmMaster[db_ctr].old_write); | |
1904 | |
1905 /* sanity check not done */ | |
1906 | |
1907 /* for read list */ | |
1908 | |
1909 if( *tmp_old >= MAX_OPEN_WRITE_PER_DB ) | |
1910 *tmp_old = 0; | |
1911 | |
1912 DB_FFS_CLOSE( tmp_open_fields[*tmp_old].filehandle ); | |
1913 | |
1914 tmp_open_fields[*tmp_old].fld_ctr = INVALID_FLD_CTR; | |
1915 | |
1916 ++(*tmp_old); | |
1917 | |
1918 return; | |
1919 | |
1920 } | |
1921 | |
1922 UBYTE db_status_user_field_file ( UBYTE db_ctr, | |
1923 UBYTE fld_ctr ) | |
1924 { | |
1925 UBYTE i; | |
1926 FileHandleRecord* tmp_open_fields; | |
1927 | |
1928 /* sanity check not done */ | |
1929 | |
1930 /* for write list */ | |
1931 | |
1932 tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS; | |
1933 | |
1934 for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i ) | |
1935 { | |
1936 if( tmp_open_fields[i].fld_ctr EQ fld_ctr ) | |
1937 return OPENED_FOR_WRITE; | |
1938 } | |
1939 | |
1940 /* for read list */ | |
1941 | |
1942 tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS; | |
1943 | |
1944 for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i ) | |
1945 { | |
1946 if( tmp_open_fields[i].fld_ctr EQ fld_ctr ) | |
1947 return OPENED_FOR_READ; | |
1948 } | |
1949 | |
1950 return NOT_OPENED; | |
1951 | |
1952 } | |
1953 | |
1954 #endif /* FFS_CLOSE_BEFORE_OPEN */ | |
1955 | |
1956 | |
1957 #ifdef FORCED_DIR_REMOVAL | |
1958 | |
1959 /* | |
1960 +-----------------------------------------------------------------------------+ | |
1961 | PROJECT: PHB MODULE: DBM | | |
1962 | ROUINE: delete_dir_forced | | |
1963 +-----------------------------------------------------------------------------+ | |
1964 | |
1965 PURPOSE : Removes contents of dir and then delete the dir | |
1966 (it uses recursion) | |
1967 */ | |
1968 T_DB_CODE delete_dir_forced ( const char* dir ) | |
1969 { | |
1970 T_FFS_SIZE ffs_ret_code; | |
1971 T_FFS_DIR ffs_dir; | |
1972 T_FFS_STAT tmp_ffs_stat; | |
1973 | |
1974 char pathname[FILENAME_LEN]; | |
1975 UBYTE dir_len; | |
1976 | |
1977 /* Open dir, if does not exist, just return DB_OK */ | |
1978 | |
1979 ffs_ret_code = ffs_opendir (dir, &ffs_dir); | |
1980 | |
1981 if( ffs_ret_code EQ EFFS_NOTFOUND ) | |
1982 DB_RETURN( DB_OK ); | |
1983 | |
1984 if( ffs_ret_code < EFFS_OK ) | |
1985 { | |
1986 TRACE_EVENT_P2( "delete_dir_forced:ffs_remove %d, %s", ffs_ret_code, dir ); | |
1987 LastFFS_ReturnCode = ffs_ret_code; | |
1988 DB_RETURN( DB_FAIL_FS ); | |
1989 } | |
1990 | |
1991 /* read dir recursively */ | |
1992 sprintf( pathname, | |
1993 "%s/", | |
1994 dir ); | |
1995 | |
1996 dir_len = strlen( pathname ); | |
1997 | |
1998 while( 1 ) | |
1999 { | |
2000 /* filename inside the directory would be copied at pathname + dirlen */ | |
2001 | |
2002 ffs_ret_code = ffs_readdir( &ffs_dir, | |
2003 pathname + dir_len, | |
2004 FILENAME_LEN - dir_len - 1 ); | |
2005 | |
2006 if( ffs_ret_code EQ 0 ) /* dir is empty now */ | |
2007 { | |
2008 break; | |
2009 } | |
2010 | |
2011 if( ffs_ret_code < EFFS_OK ) | |
2012 { | |
2013 TRACE_EVENT_P2( "delete_dir_forced:ffs_readdir:%d, %s", ffs_ret_code, dir ); | |
2014 LastFFS_ReturnCode = ffs_ret_code; | |
2015 DB_RETURN( DB_FAIL_FS ); | |
2016 } | |
2017 | |
2018 ffs_ret_code = ffs_stat( pathname, &tmp_ffs_stat ); | |
2019 | |
2020 if( ffs_ret_code < EFFS_OK ) | |
2021 { | |
2022 TRACE_EVENT_P2( "delete_dir_forced:ffs_stat:%d, %s", ffs_ret_code, pathname); | |
2023 LastFFS_ReturnCode = ffs_ret_code; | |
2024 DB_RETURN( DB_FAIL_FS ); | |
2025 } | |
2026 | |
2027 if( tmp_ffs_stat.type EQ OT_DIR ) | |
2028 { | |
2029 /* Directory !! */ | |
2030 | |
2031 T_DB_CODE db_code; | |
2032 | |
2033 TRACE_EVENT_P1( "Warning: directory %s", pathname ); | |
2034 | |
2035 /* Recursion */ | |
2036 db_code = delete_dir_forced( pathname ); | |
2037 | |
2038 if( db_code NEQ DB_OK ) | |
2039 DB_RETURN( db_code ); | |
2040 | |
2041 } else { | |
2042 | |
2043 /* normal file (OT_FILE) or symbolic link (OT_LINK) */ | |
2044 | |
2045 ffs_ret_code = ffs_remove( pathname ); | |
2046 | |
2047 if( ffs_ret_code < EFFS_OK ) | |
2048 { | |
2049 TRACE_EVENT_P2( "delete_dir_forced:ffs_remove:%d, %s", ffs_ret_code, pathname ); | |
2050 LastFFS_ReturnCode = ffs_ret_code; | |
2051 DB_RETURN( DB_FAIL_FS ); | |
2052 } | |
2053 | |
2054 } /* if( tmp_ffs_stat.type EQ OT_DIR ) */ | |
2055 | |
2056 } /* while( 1 ) */ | |
2057 | |
2058 /* now delete the directory */ | |
2059 ffs_ret_code = ffs_remove( dir ); | |
2060 | |
2061 if( ffs_ret_code < EFFS_OK ) | |
2062 { | |
2063 TRACE_EVENT_P2( "delete_dir_forced:ffs_remove:%d, %s", ffs_ret_code, dir ); | |
2064 LastFFS_ReturnCode = ffs_ret_code; | |
2065 DB_RETURN( DB_FAIL_FS ); | |
2066 } | |
2067 | |
2068 DB_RETURN( DB_OK ); | |
2069 } | |
2070 | |
2071 | |
2072 #endif /* FORCED_DIR_REMOVAL */ | |
2073 | |
2074 | |
2075 #ifdef INSERTION_SORT | |
2076 | |
2077 void get_sort_lists_from_FFS ( UBYTE db_ctr, | |
2078 UBYTE fld_ctr ) | |
2079 { | |
2080 UBYTE sort_index_ctr; | |
2081 | |
2082 T_DB_CODE db_ret_code; | |
2083 | |
2084 char sort_file[FILENAME_LEN]; | |
2085 | |
2086 T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr; | |
2087 | |
2088 /* for all existing sort indexes */ | |
2089 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
2090 { | |
2091 /* valid index ? */ | |
2092 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX ) | |
2093 { | |
2094 /* Check if we already have sorted list in RAM structure SortedLists */ | |
2095 | |
2096 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] EQ NULL ) | |
2097 { | |
2098 /* If no, populate the sorted list from file, | |
2099 "<DBDirectory>/UD_<field_id>_sort_<sort_index>". | |
2100 Sorted lists are freed in db_flush */ | |
2101 | |
2102 sprintf( sort_file, | |
2103 "%s/UD_%d_sort_%d", | |
2104 DbmMaster[db_ctr].DBDirectory, | |
2105 tmp_ptrFieldRecord -> FieldID, | |
2106 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] ); | |
2107 | |
2108 db_ret_code = | |
2109 populate_sorted_list_from_FFS ( | |
2110 #ifdef FFS_CLOSE_BEFORE_OPEN | |
2111 db_ctr, | |
2112 #endif | |
2113 sort_file, | |
2114 tmp_ptrFieldRecord -> NumOfRecords, | |
2115 &(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]) ); | |
2116 if( db_ret_code NEQ DB_OK ) | |
2117 { | |
2118 /* Failure, still we can continue as later during actual sorting, | |
2119 FFS would be retried */ | |
2120 | |
2121 TRACE_EVENT( "Warning: populate_sorted_list_from_FFS failed" ); | |
2122 TRACE_EVENT_P3( "db_ctr %d field_id %d sort_index %d", | |
2123 db_ctr, | |
2124 tmp_ptrFieldRecord -> FieldID, | |
2125 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] ); | |
2126 | |
2127 continue; | |
2128 } | |
2129 | |
2130 } /* if we have sort list */ | |
2131 | |
2132 } /* if valid index */ | |
2133 | |
2134 } /* for all sort indexes */ | |
2135 | |
2136 return; | |
2137 | |
2138 } | |
2139 | |
2140 void new_in_sort_lists ( UBYTE db_ctr, | |
2141 UBYTE fld_ctr, | |
2142 UBYTE record_num ) | |
2143 { | |
2144 UBYTE sort_index_ctr; | |
2145 | |
2146 T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr; | |
2147 | |
2148 /* make a note that this record needs to be sorted */ | |
2149 | |
2150 /* for all existing sort indexes */ | |
2151 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
2152 { | |
2153 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX ) | |
2154 { | |
2155 /* add it at the end like all sorted records + INVALID RECORD + .... */ | |
2156 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] | |
2157 = record_num; | |
2158 } | |
2159 } | |
2160 | |
2161 return; | |
2162 | |
2163 } | |
2164 | |
2165 void update_in_sort_lists ( UBYTE db_ctr, | |
2166 UBYTE fld_ctr, | |
2167 UBYTE record_num ) | |
2168 { | |
2169 UBYTE sort_index_ctr, | |
2170 rec_ctr; | |
2171 | |
2172 T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr; | |
2173 | |
2174 /* make a note that this record needs to be sorted */ | |
2175 | |
2176 /* for all existing sort indexes */ | |
2177 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
2178 { | |
2179 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX ) | |
2180 { | |
2181 /* search entry in sorted records */ | |
2182 rec_ctr = 0; | |
2183 while( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM ) | |
2184 { | |
2185 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] EQ record_num ) | |
2186 { | |
2187 /* found in sorted records, | |
2188 now delete this entry */ | |
2189 | |
2190 memmove( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr, /* dest */ | |
2191 (const char*)(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr + 1), /* source */ | |
2192 tmp_ptrFieldRecord -> UsedRecords - rec_ctr ); /* size */ | |
2193 | |
2194 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] | |
2195 = record_num; | |
2196 | |
2197 break; | |
2198 } | |
2199 | |
2200 ++rec_ctr; | |
2201 } | |
2202 | |
2203 } /* NEQ INVALID_SORT_INDEX */ | |
2204 | |
2205 } /* for sort_index_ctr */ | |
2206 | |
2207 return; | |
2208 } | |
2209 | |
2210 void delete_in_sort_lists ( UBYTE db_ctr, | |
2211 UBYTE fld_ctr, | |
2212 UBYTE record_num ) | |
2213 { | |
2214 UBYTE sort_index_ctr, | |
2215 rec_ctr; | |
2216 | |
2217 T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr; | |
2218 | |
2219 /* make a note that this record needs to be sorted */ | |
2220 | |
2221 /* for all existing sort indexes */ | |
2222 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
2223 { | |
2224 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX ) | |
2225 { | |
2226 /* search entry in sorted records */ | |
2227 rec_ctr = 0; | |
2228 while( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM ) | |
2229 { | |
2230 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] EQ record_num ) | |
2231 break; | |
2232 | |
2233 ++rec_ctr; | |
2234 } | |
2235 | |
2236 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM ) | |
2237 { | |
2238 /* found in sorted records, | |
2239 now delete this entry */ | |
2240 | |
2241 memmove( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr, | |
2242 (const char*)(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr + 1), | |
2243 tmp_ptrFieldRecord -> UsedRecords - rec_ctr ); | |
2244 | |
2245 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] | |
2246 = INVALID_RECORD_NUM; | |
2247 | |
2248 } else { | |
2249 | |
2250 /* search in UN-sorted records */ | |
2251 | |
2252 ++rec_ctr; | |
2253 while( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM ) | |
2254 { | |
2255 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] EQ record_num ) | |
2256 { | |
2257 /* delete this entry */ | |
2258 memmove( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr, | |
2259 (const char*)(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr + 1), | |
2260 tmp_ptrFieldRecord -> UsedRecords - rec_ctr ); | |
2261 | |
2262 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] | |
2263 = INVALID_RECORD_NUM; | |
2264 | |
2265 break; | |
2266 } | |
2267 ++rec_ctr; | |
2268 } | |
2269 | |
2270 } | |
2271 | |
2272 } /* NEQ INVALID_SORT_INDEX */ | |
2273 | |
2274 } /* for sort_index_ctr */ | |
2275 | |
2276 return; | |
2277 } | |
2278 | |
2279 /* | |
2280 +--------------------------------------------------------------------+ | |
2281 | PROJECT: PHB MODULE: DBM | | |
2282 | ROUINE: insertion_sort | | |
2283 +--------------------------------------------------------------------+ | |
2284 | |
2285 PURPOSE : Sorts the user data records in FFS based on insertion sort method | |
2286 */ | |
2287 void insertion_sort ( UBYTE* sort_list, | |
2288 UBYTE num_of_elements, | |
2289 T_COMP_FUNC compare_function, | |
2290 ULONG flags, | |
2291 int db_handle, | |
2292 USHORT field_id ) | |
2293 { | |
2294 UBYTE rec_ctr; | |
2295 | |
2296 /* sanity check */ | |
2297 if( num_of_elements EQ 0 ) | |
2298 return; | |
2299 | |
2300 if( sort_list[0] EQ INVALID_RECORD_NUM ) | |
2301 { | |
2302 /* This is beginning of new sort list, | |
2303 Let's add first element */ | |
2304 sort_list[0] = sort_list[1]; | |
2305 sort_list[1] = INVALID_RECORD_NUM; | |
2306 } | |
2307 | |
2308 | |
2309 /* So now here we have list something like this | |
2310 { Sorted records } + INVALID_RECORD_NUM + { UNsorted records } | |
2311 */ | |
2312 | |
2313 /* let's get to Unsorted records */ | |
2314 rec_ctr = 1; | |
2315 while( sort_list[rec_ctr] NEQ INVALID_RECORD_NUM ) | |
2316 { | |
2317 ++rec_ctr; | |
2318 } | |
2319 ++rec_ctr; | |
2320 | |
2321 /* rec_ctr is now pointing at UNsorted records */ | |
2322 | |
2323 /* now add UNsorted records one by one */ | |
2324 | |
2325 /* Not required "( sort_list[rec_ctr] NEQ INVALID_RECORD_NUM )", right ? */ | |
2326 | |
2327 while( rec_ctr <= num_of_elements ) | |
2328 { | |
2329 insert_element( sort_list, | |
2330 rec_ctr, /* num_of_elements */ | |
2331 0, /* bottom */ | |
2332 rec_ctr - 2, /* top */ | |
2333 sort_list[rec_ctr], /* record_num to be inserted */ | |
2334 compare_function, | |
2335 flags, | |
2336 db_handle, | |
2337 field_id ); | |
2338 | |
2339 ++rec_ctr; | |
2340 } | |
2341 | |
2342 /* done ! */ | |
2343 return; | |
2344 } | |
2345 | |
2346 void insert_element ( UBYTE* sort_list, | |
2347 UBYTE num_of_elements, | |
2348 UBYTE bottom, | |
2349 UBYTE top, | |
2350 UBYTE record_num, | |
2351 T_COMP_FUNC compare_function, | |
2352 ULONG flags, | |
2353 int db_handle, | |
2354 USHORT field_id ) | |
2355 { | |
2356 UBYTE middle = ( top + bottom ) / 2; | |
2357 | |
2358 /* use binary algorithm to find the right place for insertion */ | |
2359 while( middle NEQ bottom ) | |
2360 { | |
2361 if( compare_function( db_handle, | |
2362 field_id, | |
2363 sort_list[middle], | |
2364 record_num, | |
2365 flags ) | |
2366 < 0 ) | |
2367 { | |
2368 bottom = middle; | |
2369 } else { | |
2370 top = middle; | |
2371 } | |
2372 middle = ( top + bottom ) / 2; | |
2373 | |
2374 } /* while( middle NEQ bottom ) */ | |
2375 | |
2376 if( compare_function( db_handle, | |
2377 field_id, | |
2378 sort_list[bottom], | |
2379 record_num, | |
2380 flags ) | |
2381 < 0 ) | |
2382 { | |
2383 | |
2384 if( compare_function( db_handle, | |
2385 field_id, | |
2386 sort_list[top], | |
2387 record_num, | |
2388 flags ) | |
2389 < 0 ) | |
2390 { | |
2391 /* insert at top + 1 */ | |
2392 memmove( sort_list + top + 2, /* dest */ | |
2393 sort_list + top + 1, /* source */ | |
2394 num_of_elements - (top + 1) ); /* size */ | |
2395 | |
2396 sort_list[top + 1] = record_num; | |
2397 | |
2398 } else { | |
2399 | |
2400 /* insert at bottom + 1 */ | |
2401 memmove( sort_list + bottom + 2, /* dest */ | |
2402 sort_list + bottom + 1, /* source */ | |
2403 num_of_elements - (bottom + 1) ); /* size */ | |
2404 | |
2405 sort_list[bottom + 1] = record_num; | |
2406 | |
2407 } /* if top_th < insert_th */ | |
2408 | |
2409 } else { | |
2410 | |
2411 /* insert at bottom */ | |
2412 memmove( sort_list + bottom + 1, /* dest */ | |
2413 sort_list + bottom, /* source */ | |
2414 num_of_elements - bottom ); /* size */ | |
2415 | |
2416 sort_list[bottom] = record_num; | |
2417 | |
2418 } /* if bottom_th < insert_th */ | |
2419 | |
2420 return; | |
2421 } | |
2422 | |
2423 #endif /* INSERTION_SORT */ | |
2424 | |
2425 | |
2426 /* | |
2427 +--------------------------------------------------------------------+ | |
2428 | PROJECT: PHB MODULE: DBM | | |
2429 | ROUINE: internal_db_sort | | |
2430 +--------------------------------------------------------------------+ | |
2431 | |
2432 PURPOSE : (Internal) Creates or updates a sort index for | |
2433 a given (database, field) | |
2434 */ | |
2435 T_DB_CODE internal_db_sort ( int db_handle, | |
2436 USHORT field_id, | |
2437 UBYTE sort_index, | |
2438 T_COMP_FUNC compare_function, | |
2439 ULONG flags, | |
2440 T_DB_SORT sort_type ) | |
2441 { | |
2442 UBYTE fld_ctr, | |
2443 sort_index_ctr, | |
2444 remb_sort_index_ctr, | |
2445 tmp_byte, | |
2446 bit_num, | |
2447 record_num; | |
2448 | |
2449 UBYTE* sort_list; | |
2450 UBYTE* copy_sort_list; | |
2451 | |
2452 UBYTE* tmp_byte_ptr; | |
2453 | |
2454 T_DB_CODE db_ret_code; | |
2455 | |
2456 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
2457 | |
2458 UBYTE* field_data; | |
2459 UBYTE field_file[FILENAME_LEN]; | |
2460 | |
2461 TRACE_FUNCTION("internal_db_sort()"); | |
2462 | |
2463 /* DBM_State check */ | |
2464 DBM_State_check; | |
2465 | |
2466 /* db_handle check */ | |
2467 db_ret_code = db_handle_check( db_handle ); | |
2468 if( db_ret_code NEQ DB_OK ) | |
2469 DB_RETURN( db_ret_code ); | |
2470 | |
2471 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
2472 fld_ctr = field_id_search( db_handle, field_id ); | |
2473 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
2474 DB_RETURN( DB_INVALID_FIELD ); | |
2475 | |
2476 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
2477 | |
2478 /* Check if this is existing sort index */ | |
2479 remb_sort_index_ctr = MAX_NUM_OF_SORT_INDEXS; | |
2480 | |
2481 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
2482 { | |
2483 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index ) | |
2484 break; | |
2485 | |
2486 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ INVALID_SORT_INDEX ) | |
2487 remb_sort_index_ctr = sort_index_ctr; | |
2488 | |
2489 } | |
2490 | |
2491 if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS ) | |
2492 { | |
2493 /* ok, this is new index, so | |
2494 Check if limit for sort list corresponding to field_id (for a given database) | |
2495 has reached limit, MAX_NUM_OF_SORT_INDEXS. If so, return DB_FULL. */ | |
2496 | |
2497 if( remb_sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS ) | |
2498 DB_RETURN( DB_FULL ); | |
2499 | |
2500 sort_index_ctr = remb_sort_index_ctr; | |
2501 | |
2502 /* update file , "~/dbm/DD_<db_handle>" for SortIndexes. */ | |
2503 | |
2504 /* create the field data that is to be written */ | |
2505 | |
2506 DB_MALLOC( field_data, MAX_NUM_OF_SORT_INDEXS ); | |
2507 memcpy( field_data, tmp_ptrFieldRecord -> SortIndexList, MAX_NUM_OF_SORT_INDEXS ); | |
2508 | |
2509 field_data[sort_index_ctr] = sort_index; | |
2510 | |
2511 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle ); | |
2512 | |
2513 db_ret_code = | |
2514 update_field_data_in_FFS ( (const char*)field_file, | |
2515 &DbmMaster[db_handle].FFSFileHandle, | |
2516 #ifdef FFS_CLOSE_BEFORE_OPEN | |
2517 db_handle, | |
2518 #endif | |
2519 fld_ctr, | |
2520 T_DB_FIELD_RECORD_SIZE, | |
2521 field_data, | |
2522 SortIndexList_OFFSET, | |
2523 MAX_NUM_OF_SORT_INDEXS ); | |
2524 if( db_ret_code NEQ DB_OK ) | |
2525 { | |
2526 DB_MFREE( field_data ); | |
2527 DB_RETURN( db_ret_code ); | |
2528 } | |
2529 | |
2530 DB_MFREE( field_data ); | |
2531 /* updation of DD_<db_handle> is over */ | |
2532 } | |
2533 | |
2534 if( ( sort_type EQ QUICK_SORT ) AND | |
2535 ( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] NEQ NULL ) ) | |
2536 { | |
2537 /* free earlier list */ | |
2538 DB_MFREE( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] ); | |
2539 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] = NULL; | |
2540 } | |
2541 | |
2542 /* create sort list (if not there) */ | |
2543 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] NEQ NULL ) | |
2544 { | |
2545 sort_list = tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]; | |
2546 } else { | |
2547 | |
2548 #ifndef INSERTION_SORT | |
2549 DB_MALLOC( sort_list, tmp_ptrFieldRecord -> NumOfRecords ); | |
2550 memset( sort_list, INVALID_RECORD_NUM, tmp_ptrFieldRecord -> NumOfRecords ); | |
2551 | |
2552 copy_sort_list = sort_list; | |
2553 #else | |
2554 DB_MALLOC( sort_list, tmp_ptrFieldRecord -> NumOfRecords + 1 ); | |
2555 memset( sort_list, INVALID_RECORD_NUM, tmp_ptrFieldRecord -> NumOfRecords + 1 ); | |
2556 | |
2557 if( sort_type EQ INCREMENTAL_SORT ) | |
2558 { | |
2559 /* the first element would be INVALID_RECORD_NUM (0xFF) */ | |
2560 copy_sort_list = sort_list + 1; | |
2561 | |
2562 } else { | |
2563 | |
2564 copy_sort_list = sort_list; | |
2565 } | |
2566 #endif /* INSERTION_SORT */ | |
2567 | |
2568 /* The list of available records is prepared from RecordBitMap */ | |
2569 | |
2570 tmp_byte_ptr = tmp_ptrFieldRecord -> RecordBitMap + RECORD_BITMAP_SIZE - 1; | |
2571 record_num = 0; | |
2572 | |
2573 while( record_num < tmp_ptrFieldRecord -> NumOfRecords ) | |
2574 { | |
2575 tmp_byte = *tmp_byte_ptr; | |
2576 for( bit_num = 0; bit_num < MAX_BIT_POS; ++bit_num ) | |
2577 { | |
2578 ++record_num; | |
2579 | |
2580 if( record_num > tmp_ptrFieldRecord -> NumOfRecords ) | |
2581 break; | |
2582 | |
2583 if( tmp_byte & 0x01 ) | |
2584 { | |
2585 *copy_sort_list = record_num; | |
2586 ++copy_sort_list; | |
2587 } | |
2588 | |
2589 | |
2590 tmp_byte >>= 1; | |
2591 } | |
2592 --tmp_byte_ptr; | |
2593 | |
2594 } /* population of records */ | |
2595 | |
2596 } /* sort_list is NULL */ | |
2597 | |
2598 /* Sort the records with given "comparison_function" (it takes record numbers, | |
2599 field_id and db_handle). Note that the sorted list would be kept in RAM | |
2600 (structure SortedLists, part of field record) till db_flush is called and | |
2601 cleared in db_flush. */ | |
2602 | |
2603 if( sort_type EQ QUICK_SORT ) | |
2604 { | |
2605 quick_sort( sort_list, | |
2606 tmp_ptrFieldRecord -> UsedRecords, /* only used records */ | |
2607 compare_function, | |
2608 flags, | |
2609 db_handle, | |
2610 field_id ); | |
2611 } | |
2612 | |
2613 #ifdef INSERTION_SORT | |
2614 | |
2615 if( sort_type EQ INCREMENTAL_SORT ) | |
2616 { | |
2617 insertion_sort( sort_list, | |
2618 tmp_ptrFieldRecord -> UsedRecords, /* only used records */ | |
2619 compare_function, | |
2620 flags, | |
2621 db_handle, | |
2622 field_id ); | |
2623 } | |
2624 | |
2625 #endif /* INSERTION_SORT */ | |
2626 | |
2627 /* writing sorted list to FFS would be done in db_flush */ | |
2628 | |
2629 /* Update corresponding field SortIndexList in RAM structures. */ | |
2630 | |
2631 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] = sort_index; | |
2632 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] = sort_list; | |
2633 | |
2634 DB_RETURN( DB_OK ); | |
2635 } | |
2636 | |
2637 | |
2638 | |
2639 | |
2640 | |
2641 | |
2642 | |
2643 | |
2644 | |
2645 | |
2646 | |
2647 | |
2648 | |
2649 | |
2650 | |
2651 | |
2652 | |
2653 | |
2654 | |
2655 | |
2656 | |
2657 | |
2658 | |
2659 | |
2660 | |
2661 /***********************/ | |
2662 /* INTERFACE FUNCTIONS */ | |
2663 /***********************/ | |
2664 | |
2665 | |
2666 /* | |
2667 +--------------------------------------------------------------------+ | |
2668 | PROJECT: PHB MODULE: DBM | | |
2669 | ROUINE: db_init | | |
2670 +--------------------------------------------------------------------+ | |
2671 | |
2672 PURPOSE : Initialises database manager | |
2673 */ | |
2674 void db_init ( void ) | |
2675 { | |
2676 UBYTE db_ctr; | |
2677 | |
2678 #ifdef FFS_CLOSE_BEFORE_OPEN | |
2679 UBYTE fld_ctr; | |
2680 #endif | |
2681 | |
2682 TRACE_FUNCTION("db_init()"); | |
2683 | |
2684 /* 1) Check DBM_State and if already initialized, return DB_OK */ | |
2685 if ( DBM_State EQ DBM_INITIALISED ) | |
2686 return; | |
2687 | |
2688 /* 2) Initialize DbmMaster structure */ | |
2689 for ( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr ) | |
2690 { | |
2691 DbmMaster[db_ctr].DBState = UNUSED_ENTRY; | |
2692 | |
2693 #ifdef FFS_CLOSE_BEFORE_OPEN | |
2694 | |
2695 for( fld_ctr = 0; fld_ctr < MAX_OPEN_READ_PER_DB; ++fld_ctr ) | |
2696 { | |
2697 DbmMaster[db_ctr].READ_OPEN_FIELDS[fld_ctr].fld_ctr = INVALID_FLD_CTR; | |
2698 } | |
2699 for( fld_ctr = 0; fld_ctr < MAX_OPEN_WRITE_PER_DB; ++fld_ctr ) | |
2700 { | |
2701 DbmMaster[db_ctr].WRITE_OPEN_FIELDS[fld_ctr].fld_ctr = INVALID_FLD_CTR; | |
2702 } | |
2703 DbmMaster[db_ctr].old_read = 0; | |
2704 DbmMaster[db_ctr].old_write = 0; | |
2705 | |
2706 #endif | |
2707 | |
2708 } | |
2709 | |
2710 UsedDBs = 0; | |
2711 | |
2712 #ifdef _SIMULATION_ | |
2713 { | |
2714 T_FFS_SIZE ffs_ret_code = ffs_init(); | |
2715 | |
2716 TRACE_EVENT_P1("Initialization of FFS Simulation %d", ffs_ret_code ); | |
2717 | |
2718 /* Delete existing database */ | |
2719 init_RAM_with_FFS(); | |
2720 | |
2721 for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr ) | |
2722 { | |
2723 if( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY ) | |
2724 db_remove( DbmMaster[db_ctr].DBDirectory ); | |
2725 } | |
2726 | |
2727 db_exit(); | |
2728 } | |
2729 #endif | |
2730 | |
2731 return; | |
2732 } | |
2733 | |
2734 /* | |
2735 +--------------------------------------------------------------------+ | |
2736 | PROJECT: PHB MODULE: DBM | | |
2737 | ROUINE: init_RAM_with_FFS | | |
2738 +--------------------------------------------------------------------+ | |
2739 | |
2740 PURPOSE : Initialise DBM RAM structures with FFS data | |
2741 */ | |
2742 T_DB_CODE init_RAM_with_FFS ( void ) | |
2743 { | |
2744 /* Initializing "DBM related data" in RAM from FFS */ | |
2745 | |
2746 T_FFS_FD ffs_dbm_fd; | |
2747 T_FFS_SIZE ffs_ret_code; | |
2748 T_FFS_STAT ffs_dir_stat; | |
2749 UBYTE* db_buffer; | |
2750 UBYTE* remb_db_buffer; | |
2751 UBYTE* tmp_byte_ptr; | |
2752 UBYTE* field_buffer; | |
2753 UBYTE* remb_field_buffer; | |
2754 UBYTE db_ctr, | |
2755 fld_ctr, | |
2756 sort_index_ctr, | |
2757 tmp_byte, | |
2758 tmp_num_records, | |
2759 bit_num, | |
2760 record_num; | |
2761 char field_file[FILENAME_LEN]; | |
2762 char* field_file_ptr = field_file; | |
2763 char* dbm_file = DB_MASTER_FILE; | |
2764 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
2765 | |
2766 | |
2767 TRACE_FUNCTION("init_RAM_with_FFS()"); | |
2768 | |
2769 /* Check the presence of FFS directory DB_DIR */ | |
2770 ffs_ret_code = ffs_stat( DB_DIR, &ffs_dir_stat ); | |
2771 | |
2772 TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_stat %d", ffs_ret_code ); | |
2773 /* error values of ffs_ret_code are handled later */ | |
2774 | |
2775 if( ffs_ret_code >= EFFS_OK ) | |
2776 { | |
2777 /* Directory is present */ | |
2778 | |
2779 /* Synchronize DB related data between FFS and RAM | |
2780 i.e. structures DbmMasterRecord and corresponding DbmFieldRecord. */ | |
2781 | |
2782 /* For DbmMaster */ | |
2783 | |
2784 DB_FFS_OPEN( ffs_dbm_fd, dbm_file, FFS_O_RDONLY ); | |
2785 | |
2786 if( (ffs_dbm_fd EQ EFFS_NAMETOOLONG ) OR | |
2787 (ffs_dbm_fd EQ EFFS_BADNAME ) OR | |
2788 (ffs_dbm_fd EQ EFFS_NOTFOUND ) OR | |
2789 (ffs_dbm_fd EQ EFFS_INVALID ) OR | |
2790 (ffs_dbm_fd EQ EFFS_LOCKED ) ) | |
2791 | |
2792 { | |
2793 TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd ); | |
2794 return DB_FAIL; | |
2795 } | |
2796 | |
2797 if( ffs_dbm_fd < EFFS_OK ) | |
2798 { | |
2799 TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd ); | |
2800 LastFFS_ReturnCode = ffs_dbm_fd; | |
2801 return DB_FAIL_FS; | |
2802 } | |
2803 | |
2804 ffs_ret_code = ffs_seek( ffs_dbm_fd, 0, FFS_SEEK_SET ); | |
2805 | |
2806 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
2807 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
2808 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
2809 { | |
2810 TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_seek %d", ffs_ret_code ); | |
2811 DB_FFS_CLOSE( ffs_dbm_fd ); | |
2812 return DB_FAIL; | |
2813 } | |
2814 | |
2815 /* buffer for master records */ | |
2816 DB_MALLOC( db_buffer, T_DB_MASTER_RECORD_SIZE ); | |
2817 remb_db_buffer = db_buffer; | |
2818 | |
2819 for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr ) | |
2820 { | |
2821 db_buffer = remb_db_buffer; | |
2822 ffs_ret_code = ffs_read( ffs_dbm_fd, db_buffer, T_DB_MASTER_RECORD_SIZE ); | |
2823 | |
2824 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
2825 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
2826 { | |
2827 TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_read %d", ffs_ret_code ); | |
2828 DB_FFS_CLOSE( ffs_dbm_fd ); | |
2829 DB_MFREE( db_buffer ); | |
2830 return DB_FAIL; | |
2831 } | |
2832 | |
2833 if( ffs_ret_code EQ 0 ) /* number of bytes read EQ 0 */ | |
2834 break; | |
2835 | |
2836 if( *db_buffer EQ 0xFF ) /* if invalid database */ | |
2837 continue; | |
2838 | |
2839 memcpy( DbmMaster[db_ctr].DBDirectory, db_buffer, MAX_LEN_DIRECTORY ); | |
2840 db_buffer += MAX_LEN_DIRECTORY; | |
2841 | |
2842 DbmMaster[db_ctr].NumOfFiles = *db_buffer; | |
2843 ++db_buffer; | |
2844 | |
2845 DbmMaster[db_ctr].Tracked_Clean = ( *db_buffer ) ? TRACKED_AND_CLEAN : CLEAN; | |
2846 ++db_buffer; | |
2847 | |
2848 DbmMaster[db_ctr].UsedFiles = 0; | |
2849 | |
2850 DbmMaster[db_ctr].DBState = CLOSED; | |
2851 | |
2852 ++UsedDBs; | |
2853 | |
2854 /* we need not "seek" here file pointer would have moved to next */ | |
2855 } | |
2856 | |
2857 DB_FFS_CLOSE( ffs_dbm_fd ); | |
2858 DB_MFREE( remb_db_buffer ); /* freeing db_buffer */ | |
2859 | |
2860 /* For FieldRecords */ | |
2861 | |
2862 /* buffer for field records */ | |
2863 DB_MALLOC( field_buffer, T_DB_FIELD_RECORD_SIZE ); | |
2864 remb_field_buffer = field_buffer; | |
2865 | |
2866 for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr ) | |
2867 { | |
2868 | |
2869 if( DbmMaster[db_ctr].DBState EQ UNUSED_ENTRY ) | |
2870 continue; | |
2871 | |
2872 /* Field file = DD_<pos. in DD_master> */ | |
2873 | |
2874 sprintf( field_file, "%s/DD_%d", DB_DIR, db_ctr); | |
2875 | |
2876 DB_FFS_OPEN( ffs_dbm_fd, field_file_ptr, FFS_O_RDONLY ); | |
2877 | |
2878 if( ( ffs_dbm_fd EQ EFFS_NOTFOUND ) OR /* Field file not found */ | |
2879 ( ffs_dbm_fd EQ EFFS_NUMFD ) OR /* FFS specific errors */ | |
2880 ( ffs_dbm_fd EQ EFFS_LOCKED) ) | |
2881 { | |
2882 TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd ); | |
2883 DB_MFREE( field_buffer ); | |
2884 return DB_FAIL; | |
2885 } | |
2886 | |
2887 ffs_ret_code = ffs_seek( ffs_dbm_fd, 0, FFS_SEEK_SET ); | |
2888 | |
2889 if( ( ffs_ret_code EQ EFFS_BADFD ) OR | |
2890 ( ffs_ret_code EQ EFFS_INVALID ) OR | |
2891 ( ffs_ret_code EQ EFFS_BADOP ) ) | |
2892 { | |
2893 TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_seek %d", ffs_ret_code ); | |
2894 DB_FFS_CLOSE( ffs_dbm_fd ); | |
2895 DB_MFREE( field_buffer ); | |
2896 return DB_FAIL; | |
2897 } | |
2898 | |
2899 /* Allocate memory for field records */ | |
2900 DB_MALLOC( DbmMaster[db_ctr].ptrFieldRecord, | |
2901 DbmMaster[db_ctr].NumOfFiles * sizeof(T_DBM_FIELDRECORD) ); | |
2902 | |
2903 tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord; | |
2904 | |
2905 for( fld_ctr = 0; fld_ctr < DbmMaster[db_ctr].NumOfFiles; ++fld_ctr ) | |
2906 { | |
2907 field_buffer = remb_field_buffer; | |
2908 | |
2909 ffs_ret_code = ffs_read( ffs_dbm_fd, field_buffer, T_DB_FIELD_RECORD_SIZE ); | |
2910 | |
2911 if( (ffs_ret_code EQ EFFS_BADFD ) OR | |
2912 (ffs_ret_code EQ EFFS_BADOP ) ) | |
2913 { | |
2914 TRACE_EVENT_P2( "init_RAM_with_FFS:ffs_seek %d, fld_ctr %d", ffs_ret_code, fld_ctr ); | |
2915 DB_FFS_CLOSE ( ffs_dbm_fd ); | |
2916 DB_MFREE( field_buffer ); | |
2917 DB_MFREE( DbmMaster[db_ctr].ptrFieldRecord ); | |
2918 return DB_FAIL; | |
2919 } | |
2920 | |
2921 if( ffs_ret_code EQ 0 ) /* number of bytes read EQ 0 */ | |
2922 { | |
2923 /* we need not go further, just make rest of field ids as invalid (not existing) */ | |
2924 for( ; fld_ctr < DbmMaster[db_ctr].NumOfFiles; ++fld_ctr ) | |
2925 { | |
2926 tmp_ptrFieldRecord -> FieldID = INVALID_FIELD_ID; | |
2927 ++tmp_ptrFieldRecord; | |
2928 } | |
2929 break; | |
2930 } | |
2931 | |
2932 /* Syncing of field records */ | |
2933 | |
2934 tmp_ptrFieldRecord -> FieldID = *field_buffer; | |
2935 tmp_ptrFieldRecord -> FieldID <<= MAX_BIT_POS; | |
2936 ++field_buffer; | |
2937 tmp_ptrFieldRecord -> FieldID |= *field_buffer; | |
2938 ++field_buffer; | |
2939 | |
2940 if ( tmp_ptrFieldRecord -> FieldID NEQ INVALID_FIELD_ID ) | |
2941 { | |
2942 tmp_ptrFieldRecord -> DBType = *field_buffer; | |
2943 ++field_buffer; | |
2944 | |
2945 tmp_ptrFieldRecord -> RecordSize = *field_buffer; | |
2946 tmp_ptrFieldRecord -> RecordSize <<= MAX_BIT_POS; | |
2947 ++field_buffer; | |
2948 tmp_ptrFieldRecord -> RecordSize |= *field_buffer; | |
2949 ++field_buffer; | |
2950 | |
2951 tmp_ptrFieldRecord -> NumOfRecords = *field_buffer; | |
2952 ++field_buffer; | |
2953 | |
2954 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
2955 { | |
2956 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] = *field_buffer; | |
2957 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] = NULL; | |
2958 ++field_buffer; | |
2959 } | |
2960 | |
2961 memcpy( tmp_ptrFieldRecord -> RecordBitMap, field_buffer, RECORD_BITMAP_SIZE ); | |
2962 field_buffer += RECORD_BITMAP_SIZE; | |
2963 | |
2964 tmp_ptrFieldRecord -> Clean = *field_buffer; | |
2965 | |
2966 #ifndef FFS_CLOSE_BEFORE_OPEN | |
2967 tmp_ptrFieldRecord -> FFSFileHandle = NULL; | |
2968 #endif | |
2969 /* we need to get size of user file <DBDirectory>/UD_<field_id> | |
2970 NextRecordNum = (size of user file) / record size */ | |
2971 tmp_ptrFieldRecord -> NextRecordNum = | |
2972 cal_NextRecordNum ( (const char*)DbmMaster[db_ctr].DBDirectory, | |
2973 tmp_ptrFieldRecord -> FieldID, | |
2974 tmp_ptrFieldRecord -> RecordSize ); | |
2975 | |
2976 /* Update database records for UsedFiles, Clean, and UsedRecords */ | |
2977 | |
2978 DbmMaster[db_ctr].UsedFiles += 1; | |
2979 | |
2980 if( DbmMaster[db_ctr].Tracked_Clean & TRACKED ) /* if db is tracked */ | |
2981 if( NOT tmp_ptrFieldRecord -> Clean ) /* if field is not clean */ | |
2982 DbmMaster[db_ctr].Tracked_Clean &= ~ CLEAN ; /* make db as not clean */ | |
2983 | |
2984 | |
2985 /* For calculating UsedRecords */ | |
2986 | |
2987 tmp_byte_ptr = tmp_ptrFieldRecord -> RecordBitMap + RECORD_BITMAP_SIZE - 1; | |
2988 tmp_num_records = 0; | |
2989 record_num = 0; | |
2990 | |
2991 while( record_num < tmp_ptrFieldRecord -> NumOfRecords ) | |
2992 { | |
2993 tmp_byte = *tmp_byte_ptr; | |
2994 | |
2995 for( bit_num = 0; bit_num < MAX_BIT_POS; ++bit_num ) | |
2996 { | |
2997 ++record_num; | |
2998 | |
2999 if( record_num > tmp_ptrFieldRecord -> NumOfRecords ) | |
3000 break; | |
3001 | |
3002 if( tmp_byte & 0x01 ) | |
3003 ++tmp_num_records; | |
3004 | |
3005 tmp_byte >>= 1; | |
3006 } | |
3007 | |
3008 --tmp_byte_ptr; | |
3009 } | |
3010 | |
3011 tmp_ptrFieldRecord -> UsedRecords = tmp_num_records; | |
3012 | |
3013 } /* FieldID NEQ INVALID_FIELD_ID */ | |
3014 | |
3015 /* go to next field record */ | |
3016 | |
3017 /* seek is not required here ! */ | |
3018 | |
3019 ++tmp_ptrFieldRecord; /* next field */ | |
3020 | |
3021 } /* for( fld_ctr ) ... all fields */ | |
3022 | |
3023 /* close the DD_<db_handle> file */ | |
3024 DB_FFS_CLOSE( ffs_dbm_fd ); | |
3025 | |
3026 } /* ffs_ret_code >= EFFS_OK */ | |
3027 | |
3028 DB_MFREE( remb_field_buffer ); /* freeing field buffer */ | |
3029 | |
3030 DBM_State = DBM_INITIALISED; | |
3031 | |
3032 return DB_OK; | |
3033 | |
3034 } /* if( ffs_ret_code >= EFFS_OK ) */ | |
3035 | |
3036 /* Directory not present */ | |
3037 if( ffs_ret_code EQ EFFS_NOTFOUND ) | |
3038 { | |
3039 /* Create DBM directory */ | |
3040 ffs_ret_code = ffs_mkdir( DB_DIR ); | |
3041 | |
3042 if( (ffs_ret_code EQ EFFS_NAMETOOLONG ) OR | |
3043 (ffs_ret_code EQ EFFS_BADNAME ) ) | |
3044 { | |
3045 TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_mkdir %d", ffs_ret_code ); | |
3046 return DB_FAIL; | |
3047 } | |
3048 | |
3049 if( ffs_ret_code < EFFS_OK ) | |
3050 { | |
3051 TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_mkdir %d", ffs_ret_code ); | |
3052 LastFFS_ReturnCode = ffs_ret_code; | |
3053 return DB_FAIL_FS; | |
3054 } | |
3055 | |
3056 /* Create empty file DD_master | |
3057 FFS_O_EXCL => Generate error if FFS_O_CREATE is also specified and | |
3058 the file already exists. */ | |
3059 | |
3060 DB_FFS_OPEN( ffs_dbm_fd, dbm_file, FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL ); | |
3061 | |
3062 if( (ffs_dbm_fd EQ EFFS_NAMETOOLONG ) OR | |
3063 (ffs_dbm_fd EQ EFFS_BADNAME ) ) | |
3064 { | |
3065 TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd ); | |
3066 ffs_ret_code = ffs_remove( DB_DIR ); /* undo creating of DBM directory */ | |
3067 return DB_FAIL; | |
3068 } | |
3069 | |
3070 if( ffs_dbm_fd < EFFS_OK ) | |
3071 { | |
3072 TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd ); | |
3073 LastFFS_ReturnCode = ffs_dbm_fd; | |
3074 ffs_ret_code = ffs_remove( DB_DIR ); /* undo creating of DBM directory */ | |
3075 return DB_FAIL_FS; | |
3076 } | |
3077 | |
3078 DB_FFS_CLOSE( ffs_dbm_fd ); | |
3079 | |
3080 DBM_State = DBM_INITIALISED; | |
3081 | |
3082 return DB_OK; | |
3083 } | |
3084 | |
3085 /* Unexpected error: Not a directory */ | |
3086 return DB_FAIL; | |
3087 | |
3088 } | |
3089 | |
3090 /* | |
3091 +--------------------------------------------------------------------+ | |
3092 | PROJECT: PHB MODULE: DBM | | |
3093 | ROUINE: db_create | | |
3094 +--------------------------------------------------------------------+ | |
3095 | |
3096 PURPOSE : Create a new database in the given directory of the FFS. | |
3097 The directory must not to exist yet, it will be created. | |
3098 */ | |
3099 int db_create ( const char* directory, | |
3100 UBYTE num_of_fields, | |
3101 BOOL tracked ) | |
3102 { | |
3103 int db_handle; | |
3104 T_DB_CODE db_ret_code; | |
3105 UBYTE fld_ctr; | |
3106 S8 db_ctr; | |
3107 T_FFS_SIZE ffs_ret_code; | |
3108 T_FFS_FD ffs_fd; | |
3109 char field_file[FILENAME_LEN]; | |
3110 char* field_file_ptr = field_file; | |
3111 UBYTE* dbm_data; | |
3112 UBYTE* remb_dbm_data; | |
3113 | |
3114 TRACE_FUNCTION("db_create()"); | |
3115 | |
3116 /* If DBM is not in initialized state, call init_RAM_with_FFS (). */ | |
3117 if( DBM_State NEQ DBM_INITIALISED ) | |
3118 { | |
3119 T_DB_CODE db_ret_code; | |
3120 | |
3121 db_ret_code = init_RAM_with_FFS(); | |
3122 | |
3123 if( db_ret_code NEQ DB_OK ) | |
3124 DB_RETURN( db_ret_code ); | |
3125 } | |
3126 | |
3127 /* See if you have reached the maximum number of DBs, ? | |
3128 (UsedDBs+1) > MAX_DBs */ | |
3129 | |
3130 if( UsedDBs EQ MAX_DBs ) | |
3131 DB_RETURN( DB_FULL ); | |
3132 | |
3133 | |
3134 /* Check DbmMaster if already database for "directory" exists. | |
3135 If yes, return error "DB_EXISTS" */ | |
3136 | |
3137 for( db_ctr = (MAX_DBs - 1); db_ctr >= 0; --db_ctr ) | |
3138 { | |
3139 if ( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY ) | |
3140 { | |
3141 if( memcmp( DbmMaster[db_ctr].DBDirectory, | |
3142 directory, | |
3143 strlen( directory ) ) EQ 0 ) | |
3144 DB_RETURN( DB_EXISTS ); | |
3145 } else { | |
3146 db_handle = db_ctr; | |
3147 } | |
3148 } | |
3149 | |
3150 /* sanity check */ | |
3151 if( num_of_fields <= 0 ) | |
3152 DB_RETURN( DB_FAIL ); | |
3153 | |
3154 /* Create a directory, "<DBDirectory>" (DBDirectory = directory) */ | |
3155 ffs_ret_code = ffs_mkdir( directory ); | |
3156 | |
3157 if( ffs_ret_code < EFFS_OK ) | |
3158 { | |
3159 TRACE_EVENT_P1( "db_create:ffs_mkdir %d", ffs_ret_code ); | |
3160 LastFFS_ReturnCode = ffs_ret_code; | |
3161 DB_RETURN( DB_FAIL_FS ); | |
3162 } | |
3163 | |
3164 | |
3165 /* Create a empty file, "~/dbm/DD_<position in DD_master = db_handle>"; | |
3166 if this FFS operation fails, we need to delete the directory | |
3167 before returning error. | |
3168 */ | |
3169 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle); | |
3170 | |
3171 TRACE_EVENT_P1( "field_file %s", field_file ); | |
3172 | |
3173 /* FFS_O_EXCL => Generate error if FFS_O_CREATE is also specified and | |
3174 the file already exists. */ | |
3175 DB_FFS_OPEN( ffs_fd, field_file_ptr, FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL ); | |
3176 | |
3177 if( ( ffs_fd EQ EFFS_EXISTS ) OR | |
3178 ( ffs_fd EQ EFFS_NAMETOOLONG ) OR | |
3179 ( ffs_fd EQ EFFS_BADNAME ) OR | |
3180 ( ffs_fd EQ EFFS_INVALID ) ) | |
3181 { | |
3182 TRACE_EVENT_P1( "db_create:DB_FFS_OPEN %d", ffs_fd ); | |
3183 ffs_fd = ffs_remove( directory ); | |
3184 DB_RETURN( DB_FAIL ); | |
3185 } | |
3186 | |
3187 if( ffs_fd < EFFS_OK ) | |
3188 { | |
3189 TRACE_EVENT_P1( "db_create:DB_FFS_OPEN %d", ffs_fd ); | |
3190 LastFFS_ReturnCode = ffs_fd; | |
3191 ffs_ret_code = ffs_remove( directory ); | |
3192 DB_RETURN( DB_FAIL_FS ); | |
3193 } | |
3194 | |
3195 /* DB_FFS_CLOSE( ffs_fd ); we will close it in db_flush */ | |
3196 | |
3197 #ifdef FFS_OPEN_PROBLEM_PATCH | |
3198 DB_FFS_CLOSE( ffs_fd ); | |
3199 #endif | |
3200 | |
3201 #ifdef FFS_CLOSE_BEFORE_OPEN | |
3202 /* no we do not close it */ | |
3203 #endif | |
3204 | |
3205 /* Update FFS data i.e. file, "~/dbm/DD_master". */ | |
3206 | |
3207 /* prepare the dbm data and write */ | |
3208 DB_MALLOC( dbm_data, T_DB_MASTER_RECORD_SIZE ); | |
3209 memset( dbm_data, 0, T_DB_MASTER_RECORD_SIZE ); | |
3210 remb_dbm_data = dbm_data; | |
3211 | |
3212 memcpy( dbm_data, directory, MAX_LEN_DIRECTORY ); | |
3213 dbm_data += MAX_LEN_DIRECTORY; | |
3214 | |
3215 *dbm_data = num_of_fields; | |
3216 ++dbm_data; | |
3217 | |
3218 *dbm_data = ( tracked ) ? FFS_TRACKED : FFS_NOT_TRACKED; | |
3219 | |
3220 dbm_data = remb_dbm_data; | |
3221 | |
3222 db_ret_code = | |
3223 update_dbm_data_in_FFS ( DB_MASTER_FILE, | |
3224 (UBYTE) db_handle, /* to supress warning */ | |
3225 T_DB_MASTER_RECORD_SIZE, | |
3226 dbm_data, | |
3227 0, | |
3228 T_DB_MASTER_RECORD_SIZE ); | |
3229 | |
3230 if( db_ret_code NEQ DB_OK ) | |
3231 { | |
3232 DB_MFREE( dbm_data ); | |
3233 ffs_ret_code = ffs_remove( directory ); | |
3234 DB_FFS_CLOSE( ffs_fd ); | |
3235 ffs_ret_code = ffs_remove( field_file ); | |
3236 DB_RETURN( db_ret_code ); | |
3237 } | |
3238 | |
3239 DB_MFREE( dbm_data ); | |
3240 /* updation of DD_master done | |
3241 now update RAM structures */ | |
3242 | |
3243 memcpy( DbmMaster[db_handle].DBDirectory, | |
3244 directory, | |
3245 strlen(directory) ); | |
3246 | |
3247 DbmMaster[db_handle].NumOfFiles = num_of_fields; | |
3248 DbmMaster[db_handle].UsedFiles = 0; | |
3249 DbmMaster[db_handle].Tracked_Clean = ( tracked ) ? TRACKED_AND_CLEAN : CLEAN; | |
3250 DbmMaster[db_handle].DBState = OPEN; | |
3251 DbmMaster[db_handle].FFSFileHandle = ffs_fd; | |
3252 | |
3253 #ifdef FFS_CLOSE_BEFORE_OPEN | |
3254 | |
3255 /* No files corresponding to fields have been opened | |
3256 This initialization is already done in db_init */ | |
3257 | |
3258 #endif | |
3259 | |
3260 /* Allocate memory for storing field information | |
3261 and initialize the memory with "FF" */ | |
3262 | |
3263 DB_MALLOC( DbmMaster[db_handle].ptrFieldRecord, | |
3264 num_of_fields * sizeof(T_DBM_FIELDRECORD) ); | |
3265 | |
3266 for( fld_ctr = 0; fld_ctr < num_of_fields; ++fld_ctr ) | |
3267 { | |
3268 DbmMaster[db_handle].ptrFieldRecord[fld_ctr].FieldID = INVALID_FIELD_ID; | |
3269 } | |
3270 | |
3271 UsedDBs++; | |
3272 | |
3273 DB_RETURN( db_handle ); | |
3274 | |
3275 } | |
3276 | |
3277 /* | |
3278 +--------------------------------------------------------------------+ | |
3279 | PROJECT: PHB MODULE: DBM | | |
3280 | ROUINE: db_open | | |
3281 +--------------------------------------------------------------------+ | |
3282 | |
3283 PURPOSE : Open an existing database | |
3284 */ | |
3285 int db_open ( const char *directory ) | |
3286 { | |
3287 T_DB_CODE db_ret_code; | |
3288 UBYTE db_ctr; | |
3289 | |
3290 TRACE_FUNCTION("db_open()"); | |
3291 | |
3292 /* If DBM is not in initialized state, call init_RAM_with_FFS (). */ | |
3293 if( DBM_State NEQ DBM_INITIALISED ) | |
3294 { | |
3295 db_ret_code = init_RAM_with_FFS(); | |
3296 | |
3297 if( db_ret_code NEQ DB_OK ) | |
3298 DB_RETURN( db_ret_code ); | |
3299 } | |
3300 | |
3301 /* Search for "directory" in DbmMaster */ | |
3302 for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr ) | |
3303 { | |
3304 if( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY ) | |
3305 { | |
3306 if( memcmp( DbmMaster[db_ctr].DBDirectory, | |
3307 directory, | |
3308 strlen(directory) ) EQ 0 ) | |
3309 break; | |
3310 } | |
3311 } | |
3312 | |
3313 /* If "directory" not found, return DB_FAIL. */ | |
3314 if( db_ctr EQ MAX_DBs ) | |
3315 DB_RETURN( DB_INVALID_DB ); | |
3316 | |
3317 /* Update DBState as "OPEN". */ | |
3318 DbmMaster[db_ctr].DBState = OPEN; | |
3319 | |
3320 /* Return corresponding DBHandle. */ | |
3321 DB_RETURN( db_ctr ); | |
3322 } | |
3323 | |
3324 /* | |
3325 +--------------------------------------------------------------------+ | |
3326 | PROJECT: PHB MODULE: DBM | | |
3327 | ROUINE: db_create_field | | |
3328 +--------------------------------------------------------------------+ | |
3329 | |
3330 PURPOSE : Create a new elementary file of a given type with a given | |
3331 numeric identifier and a given record size. | |
3332 */ | |
3333 T_DB_CODE db_create_field ( int db_handle, | |
3334 T_DB_TYPE db_type, | |
3335 USHORT field_id, | |
3336 USHORT record_size, | |
3337 USHORT num_of_records ) | |
3338 { | |
3339 T_DB_CODE db_ret_code; | |
3340 char user_field_file[FILENAME_LEN], | |
3341 field_file[FILENAME_LEN]; | |
3342 char* user_field_file_ptr = user_field_file; | |
3343 char* field_file_ptr = field_file; | |
3344 UBYTE fld_ctr, | |
3345 sort_index_ctr; | |
3346 T_FFS_SIZE ffs_ret_code; | |
3347 T_FFS_FD ffs_fd_user_field_file; | |
3348 UBYTE* field_data; | |
3349 UBYTE* remb_field_data; | |
3350 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
3351 | |
3352 | |
3353 TRACE_FUNCTION("db_create_field()"); | |
3354 | |
3355 /* DBM_State check */ | |
3356 DBM_State_check; | |
3357 | |
3358 /* db_handle check */ | |
3359 db_ret_code = db_handle_check( db_handle ); | |
3360 if( db_ret_code NEQ DB_OK ) | |
3361 DB_RETURN( db_ret_code ); | |
3362 | |
3363 /* field id search; if field id found, return error DB_FIELD_EXISTS */ | |
3364 if( field_id_search( db_handle, field_id ) NEQ DbmMaster[db_handle].NumOfFiles ) | |
3365 DB_RETURN( DB_FIELD_EXISTS ); | |
3366 | |
3367 /* If limit for number of fields for this DB has been reached, return error DB_FULL. */ | |
3368 if( DbmMaster[db_handle].UsedFiles EQ | |
3369 DbmMaster[db_handle].NumOfFiles ) | |
3370 DB_RETURN( DB_FULL ); | |
3371 | |
3372 /* Search for free field entry in field records corresponding to the database. */ | |
3373 for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr ) | |
3374 { | |
3375 if( DbmMaster[db_handle].ptrFieldRecord[fld_ctr].FieldID EQ INVALID_FIELD_ID ) | |
3376 break; | |
3377 } | |
3378 | |
3379 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
3380 { /* this is "inconsistency"; should never happen */ | |
3381 DB_RETURN( DB_FAIL ); | |
3382 } | |
3383 | |
3384 /* sanity check */ | |
3385 if( ( num_of_records <= 0 ) OR | |
3386 ( record_size <= 0 ) ) | |
3387 { | |
3388 DB_RETURN( DB_FAIL ); | |
3389 } | |
3390 | |
3391 /* Create file "<DBDirectory>/UD_<field_id>" */ | |
3392 sprintf( user_field_file, "%s/UD_%d", DbmMaster[db_handle].DBDirectory, field_id ); | |
3393 | |
3394 /* FFS_O_EXCL => Generate error if FFS_O_CREATE is also specified and | |
3395 the file already exists. */ | |
3396 #ifndef FFS_CLOSE_BEFORE_OPEN | |
3397 | |
3398 DB_FFS_OPEN( ffs_fd_user_field_file, user_field_file_ptr, FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL ); | |
3399 | |
3400 #else | |
3401 | |
3402 ffs_fd_user_field_file = | |
3403 db_open_user_field_file( db_handle, | |
3404 fld_ctr, | |
3405 user_field_file_ptr, | |
3406 FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL ); | |
3407 #endif | |
3408 | |
3409 if( ( ffs_fd_user_field_file EQ EFFS_EXISTS ) OR | |
3410 ( ffs_fd_user_field_file EQ EFFS_NAMETOOLONG ) OR | |
3411 ( ffs_fd_user_field_file EQ EFFS_BADNAME ) OR | |
3412 ( ffs_fd_user_field_file EQ EFFS_INVALID ) ) | |
3413 { | |
3414 TRACE_EVENT_P1( "db_create_field:DB_FFS_OPEN %d", ffs_fd_user_field_file ); | |
3415 DB_RETURN( DB_FAIL ); | |
3416 } | |
3417 | |
3418 if( ffs_fd_user_field_file < EFFS_OK ) | |
3419 { | |
3420 TRACE_EVENT_P1( "db_create_field:DB_FFS_OPEN %d", ffs_fd_user_field_file ); | |
3421 LastFFS_ReturnCode = ffs_fd_user_field_file; | |
3422 DB_RETURN( DB_FAIL_FS ); | |
3423 } | |
3424 | |
3425 /* We will close this file in db_flush */ | |
3426 | |
3427 #ifdef FFS_OPEN_PROBLEM_PATCH | |
3428 DB_FFS_CLOSE( ffs_fd_user_field_file ); | |
3429 #endif | |
3430 | |
3431 | |
3432 /* file "<DBDirectory>/UD_<field_id>" has been created | |
3433 Now, Add new field entry in "~/dbm/DD_<db_handle>" */ | |
3434 | |
3435 /* create the field data that needs to be written */ | |
3436 | |
3437 DB_MALLOC( field_data, T_DB_FIELD_RECORD_SIZE ); | |
3438 memset( field_data, 0, T_DB_FIELD_RECORD_SIZE ); | |
3439 remb_field_data = field_data; | |
3440 | |
3441 *field_data = (UBYTE) ( (field_id & 0xFF00) >> MAX_BIT_POS ); | |
3442 ++field_data; | |
3443 *field_data = (UBYTE) (field_id & 0x00FF); | |
3444 ++field_data; | |
3445 | |
3446 *field_data = db_type; | |
3447 ++field_data; | |
3448 | |
3449 *field_data = (UBYTE) ( (record_size & 0xFF00) >> MAX_BIT_POS ); | |
3450 ++field_data; | |
3451 *field_data = (UBYTE) (record_size & 0x00FF); | |
3452 ++field_data; | |
3453 | |
3454 *field_data = (UBYTE)num_of_records; | |
3455 field_data++; | |
3456 | |
3457 memset( field_data, 0xFF, MAX_NUM_OF_SORT_INDEXS ); | |
3458 field_data += MAX_NUM_OF_SORT_INDEXS; | |
3459 | |
3460 memset( field_data, 0, RECORD_BITMAP_SIZE ); | |
3461 field_data += RECORD_BITMAP_SIZE; | |
3462 | |
3463 *field_data = CLEAN; /* Clean is true */ | |
3464 | |
3465 field_data = remb_field_data; | |
3466 | |
3467 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle ); | |
3468 | |
3469 db_ret_code = | |
3470 update_field_data_in_FFS ( (const char*)field_file, | |
3471 &DbmMaster[db_handle].FFSFileHandle, | |
3472 #ifdef FFS_CLOSE_BEFORE_OPEN | |
3473 db_handle, | |
3474 #endif | |
3475 fld_ctr, | |
3476 T_DB_FIELD_RECORD_SIZE, | |
3477 field_data, | |
3478 0, | |
3479 T_DB_FIELD_RECORD_SIZE ); | |
3480 | |
3481 if( db_ret_code NEQ DB_OK ) | |
3482 { | |
3483 DB_MFREE( field_data ); | |
3484 ffs_ret_code = ffs_remove( user_field_file ); | |
3485 DB_RETURN( db_ret_code ); | |
3486 } | |
3487 | |
3488 DB_MFREE( field_data ); | |
3489 /* updation of DD_<db_handle> is over */ | |
3490 | |
3491 /* Add new field entry in field records in RAM. */ | |
3492 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
3493 | |
3494 tmp_ptrFieldRecord -> FieldID = field_id; | |
3495 tmp_ptrFieldRecord -> DBType = db_type; | |
3496 tmp_ptrFieldRecord -> RecordSize = record_size; | |
3497 tmp_ptrFieldRecord -> NumOfRecords = (UBYTE)num_of_records; | |
3498 tmp_ptrFieldRecord -> UsedRecords = 0; | |
3499 tmp_ptrFieldRecord -> Clean = CLEAN; | |
3500 | |
3501 #ifndef FFS_CLOSE_BEFORE_OPEN | |
3502 tmp_ptrFieldRecord -> FFSFileHandle = ffs_fd_user_field_file; | |
3503 #endif | |
3504 | |
3505 tmp_ptrFieldRecord -> NextRecordNum = 1; | |
3506 | |
3507 memset( tmp_ptrFieldRecord -> RecordBitMap, 0, RECORD_BITMAP_SIZE ); | |
3508 | |
3509 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
3510 { | |
3511 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] = INVALID_SORT_INDEX; | |
3512 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] = NULL; | |
3513 } | |
3514 | |
3515 /* Increment UsedFiles for the particular database in RAM */ | |
3516 DbmMaster[db_handle].UsedFiles += 1; | |
3517 | |
3518 /* everyting ok */ | |
3519 DB_RETURN( DB_OK ); | |
3520 | |
3521 } | |
3522 | |
3523 /* | |
3524 +--------------------------------------------------------------------+ | |
3525 | PROJECT: PHB MODULE: DBM | | |
3526 | ROUINE: db_write_record | | |
3527 +--------------------------------------------------------------------+ | |
3528 | |
3529 PURPOSE : Write length bytes at offset into the given record in | |
3530 (database, field) | |
3531 */ | |
3532 int db_write_record ( int db_handle, | |
3533 USHORT field_id, | |
3534 USHORT record_num, | |
3535 USHORT offset, | |
3536 USHORT length, | |
3537 const UBYTE* buffer ) | |
3538 { | |
3539 T_DB_CODE db_ret_code; | |
3540 | |
3541 UBYTE fld_ctr, | |
3542 tmp_byte, | |
3543 rec_ctr; | |
3544 | |
3545 char user_field_file[FILENAME_LEN], | |
3546 field_file[FILENAME_LEN]; | |
3547 | |
3548 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
3549 | |
3550 UBYTE* record_buffer; | |
3551 UBYTE* field_data; | |
3552 | |
3553 BOOL this_is_new_record = TRUE; | |
3554 | |
3555 TRACE_FUNCTION("db_write_record()"); | |
3556 | |
3557 TRACE_EVENT_P1("field_id %d", field_id); | |
3558 | |
3559 /* DBM_State check */ | |
3560 DBM_State_check; | |
3561 | |
3562 /* db_handle check */ | |
3563 db_ret_code = db_handle_check( db_handle ); | |
3564 if( db_ret_code NEQ DB_OK ) | |
3565 DB_RETURN( db_ret_code ); | |
3566 | |
3567 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
3568 fld_ctr = field_id_search( db_handle, field_id ); | |
3569 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
3570 DB_RETURN( DB_INVALID_FIELD ); | |
3571 | |
3572 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
3573 | |
3574 /* Check if record exceeds the record size (i.e. offset + length > record size); | |
3575 if it exceeds, return error DB_INVALID_SIZE */ | |
3576 if( (offset + length) > | |
3577 tmp_ptrFieldRecord -> RecordSize ) | |
3578 DB_RETURN( DB_INVALID_SIZE ); | |
3579 | |
3580 /* Check if FFS file is already opened using FFSFileHandle, part of field record. | |
3581 If it is not yet opened, open the FFS file and update FFSFileHandle. | |
3582 This is taken care in read_user_record_from_FFS */ | |
3583 | |
3584 /* User data file name is "<DBDirectory>/UD_<field_id>" | |
3585 This would be used below */ | |
3586 | |
3587 sprintf( user_field_file, | |
3588 "%s/UD_%d", | |
3589 DbmMaster[db_handle].DBDirectory, | |
3590 tmp_ptrFieldRecord -> FieldID ); | |
3591 | |
3592 if( record_num EQ 0 ) | |
3593 { | |
3594 /* If given record is equal to zero, | |
3595 o Find a free record using RecordBitMap. | |
3596 o If free record not found, return DB_FULL */ | |
3597 | |
3598 record_num = 1 + search_clear_bit_in_bitmap( tmp_ptrFieldRecord -> RecordBitMap, | |
3599 RECORD_BITMAP_SIZE ); | |
3600 | |
3601 if( record_num > tmp_ptrFieldRecord -> NumOfRecords ) | |
3602 DB_RETURN( DB_FULL ); | |
3603 | |
3604 | |
3605 } else { | |
3606 /* If given record is not equal to zero, | |
3607 o Check if record exists using RecordBitMap; | |
3608 if not found, proceed to writing.. | |
3609 o Read the record from "<DBDirectory>/UD_<field_id>" and | |
3610 compare it with given record (partially if offset > 0). Memcmp would be used. | |
3611 o If record match, return DB_OK. */ | |
3612 | |
3613 /* record_num = bit_pos + (8 * bitmap_idx) + 1; | |
3614 bitmap_idx = (record_num - 1) / MAX_BIT_POS; | |
3615 bit_pos = (record_num - 1) % MAX_BIT_POS; */ | |
3616 | |
3617 tmp_byte = | |
3618 (tmp_ptrFieldRecord -> RecordBitMap)[ RECORD_BITMAP_SIZE - BITMAP_INDEX(record_num) - 1]; | |
3619 | |
3620 if( tmp_byte & ( 0x01 << BIT_POS(record_num) ) ) /* record exists */ | |
3621 { | |
3622 this_is_new_record = FALSE; | |
3623 | |
3624 DB_MALLOC( record_buffer, length); | |
3625 | |
3626 db_ret_code = | |
3627 read_user_record_from_FFS ( user_field_file, | |
3628 | |
3629 #ifndef FFS_CLOSE_BEFORE_OPEN | |
3630 &(tmp_ptrFieldRecord -> FFSFileHandle), | |
3631 #else | |
3632 db_handle, | |
3633 fld_ctr, | |
3634 &Dummy_FFSFileHandle, | |
3635 #endif | |
3636 (UBYTE)record_num, | |
3637 tmp_ptrFieldRecord -> RecordSize, | |
3638 offset, | |
3639 length, | |
3640 record_buffer ); | |
3641 if( db_ret_code NEQ DB_OK ) | |
3642 { | |
3643 DB_MFREE( record_buffer ); | |
3644 DB_RETURN( db_ret_code ); | |
3645 } | |
3646 | |
3647 /* See if there is same data, if so, we need not overwrite */ | |
3648 if( memcmp( record_buffer, buffer, length) EQ 0 ) | |
3649 { /* matching data */ | |
3650 DB_MFREE( record_buffer ); | |
3651 DB_RETURN( DB_OK ); | |
3652 } | |
3653 | |
3654 DB_MFREE( record_buffer ); | |
3655 | |
3656 } /* record exists */ | |
3657 | |
3658 } /* record_num EQ 0 ? */ | |
3659 | |
3660 | |
3661 /* As per the request, write record in FFS in "<DBDirectory>/UD_<field_id>" */ | |
3662 | |
3663 /* in case of new record, we need to create fill unfilled-data with FF */ | |
3664 | |
3665 if( this_is_new_record ) | |
3666 { /* new record */ | |
3667 | |
3668 DB_MALLOC( record_buffer, tmp_ptrFieldRecord -> RecordSize ); | |
3669 memset( record_buffer, 0xFF, tmp_ptrFieldRecord -> RecordSize ) ; | |
3670 | |
3671 /* To take care of non-sequential write | |
3672 For example, initially when file is empty, and say user writes | |
3673 3rd record, 1st and 2nd record should be addded as dummy and then | |
3674 3rd record */ | |
3675 | |
3676 rec_ctr = tmp_ptrFieldRecord -> NextRecordNum; | |
3677 | |
3678 while( rec_ctr < record_num ) | |
3679 { | |
3680 db_ret_code = | |
3681 write_user_record_to_FFS ( user_field_file, | |
3682 | |
3683 #ifndef FFS_CLOSE_BEFORE_OPEN | |
3684 &(tmp_ptrFieldRecord -> FFSFileHandle), | |
3685 #else | |
3686 db_handle, | |
3687 fld_ctr, | |
3688 &Dummy_FFSFileHandle, | |
3689 #endif | |
3690 rec_ctr, | |
3691 tmp_ptrFieldRecord -> RecordSize, | |
3692 0, | |
3693 tmp_ptrFieldRecord -> RecordSize, | |
3694 record_buffer ); | |
3695 if( db_ret_code NEQ DB_OK ) | |
3696 { | |
3697 DB_MFREE( record_buffer ); | |
3698 DB_RETURN( db_ret_code ); | |
3699 } | |
3700 | |
3701 ++rec_ctr; | |
3702 } | |
3703 | |
3704 /* Add the new record */ | |
3705 | |
3706 memcpy( record_buffer + offset, buffer, length ); | |
3707 | |
3708 db_ret_code = | |
3709 write_user_record_to_FFS ( user_field_file, | |
3710 | |
3711 #ifndef FFS_CLOSE_BEFORE_OPEN | |
3712 &(tmp_ptrFieldRecord -> FFSFileHandle), | |
3713 #else | |
3714 db_handle, | |
3715 fld_ctr, | |
3716 &Dummy_FFSFileHandle, | |
3717 #endif | |
3718 (UBYTE)record_num, | |
3719 tmp_ptrFieldRecord -> RecordSize, | |
3720 0, | |
3721 tmp_ptrFieldRecord -> RecordSize, | |
3722 record_buffer ); | |
3723 if( db_ret_code NEQ DB_OK ) | |
3724 { | |
3725 DB_MFREE( record_buffer ); | |
3726 DB_RETURN( db_ret_code ); | |
3727 } | |
3728 | |
3729 DB_MFREE( record_buffer ); | |
3730 | |
3731 /* writing of record is over, update DBState (as IN_USE). */ | |
3732 DbmMaster[db_handle].DBState = IN_USE; | |
3733 | |
3734 } else { | |
3735 /* overwritten record */ | |
3736 | |
3737 db_ret_code = | |
3738 write_user_record_to_FFS ( user_field_file, | |
3739 | |
3740 #ifndef FFS_CLOSE_BEFORE_OPEN | |
3741 &(tmp_ptrFieldRecord -> FFSFileHandle), | |
3742 #else | |
3743 db_handle, | |
3744 fld_ctr, | |
3745 &Dummy_FFSFileHandle, | |
3746 #endif | |
3747 (UBYTE)record_num, | |
3748 tmp_ptrFieldRecord -> RecordSize, | |
3749 offset, | |
3750 length, | |
3751 (UBYTE*)buffer ); /* type casting to suppress warning */ | |
3752 if( db_ret_code NEQ DB_OK ) | |
3753 { | |
3754 DB_RETURN( db_ret_code ); | |
3755 } | |
3756 | |
3757 /* writing of record is over, update DBState (as IN_USE). */ | |
3758 DbmMaster[db_handle].DBState = IN_USE; | |
3759 | |
3760 #ifdef INSERTION_SORT | |
3761 | |
3762 /* get the sort lists in RAM from FFS */ | |
3763 get_sort_lists_from_FFS( (UBYTE)db_handle, fld_ctr ); | |
3764 | |
3765 /* this is updation of record, so need to be re-sorted */ | |
3766 update_in_sort_lists( (UBYTE)db_handle, fld_ctr, (UBYTE)record_num ); | |
3767 | |
3768 #endif | |
3769 | |
3770 /* if database is not tracked, no need to go further for history log writing */ | |
3771 if( NOT ( DbmMaster[db_handle].Tracked_Clean & TRACKED ) ) | |
3772 DB_VALUE_RETURN( record_num ); | |
3773 | |
3774 /* if already Clean has been reset, only history updation */ | |
3775 if( NOT ( DbmMaster[db_handle].Tracked_Clean & CLEAN ) ) | |
3776 { | |
3777 db_ret_code = update_history_log( db_handle, field_id, record_num ); | |
3778 | |
3779 if( db_ret_code NEQ DB_OK ) | |
3780 DB_RETURN( db_ret_code ); | |
3781 | |
3782 DB_VALUE_RETURN( record_num ); | |
3783 } | |
3784 | |
3785 } /* this_is_new_record */ | |
3786 | |
3787 /* Updating RecordBitMap and Clean in FFS, ~/dbm/DD_<db_handle> */ | |
3788 | |
3789 /* create the field data that is to be written */ | |
3790 | |
3791 DB_MALLOC( field_data, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
3792 memset( field_data, 0, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
3793 memcpy( field_data, tmp_ptrFieldRecord -> RecordBitMap, RECORD_BITMAP_SIZE ); | |
3794 | |
3795 if( this_is_new_record ) | |
3796 { /* RecordBitMap to be updated only for new records */ | |
3797 set_bit_in_bitmap( field_data, | |
3798 RECORD_BITMAP_SIZE, | |
3799 (UBYTE)record_num ); | |
3800 } | |
3801 | |
3802 /* clean is reset in memset, so no processing for it | |
3803 (in case of non-tracked database, anyway we ignore it ! */ | |
3804 | |
3805 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle ); | |
3806 | |
3807 db_ret_code = | |
3808 update_field_data_in_FFS ( (const char*)field_file, | |
3809 &DbmMaster[db_handle].FFSFileHandle, | |
3810 #ifdef FFS_CLOSE_BEFORE_OPEN | |
3811 db_handle, | |
3812 #endif | |
3813 fld_ctr, | |
3814 T_DB_FIELD_RECORD_SIZE, | |
3815 field_data, | |
3816 RecordBitMap_OFFSET, | |
3817 ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
3818 | |
3819 | |
3820 if( db_ret_code NEQ DB_OK ) | |
3821 { | |
3822 DB_MFREE( field_data ); | |
3823 DB_RETURN( db_ret_code ); | |
3824 } | |
3825 | |
3826 DB_MFREE( field_data ); | |
3827 /* updation of DD_<db_handle> is over */ | |
3828 | |
3829 /* Updating RAM (both DbmMaster and Field records) strctures */ | |
3830 tmp_ptrFieldRecord -> Clean = NOT_CLEAN; | |
3831 | |
3832 if( this_is_new_record ) | |
3833 { /* RecordBitMap to be updated only for new records */ | |
3834 set_bit_in_bitmap( tmp_ptrFieldRecord -> RecordBitMap, | |
3835 RECORD_BITMAP_SIZE, | |
3836 (UBYTE)record_num ); | |
3837 | |
3838 ++tmp_ptrFieldRecord -> UsedRecords; | |
3839 | |
3840 tmp_ptrFieldRecord -> NextRecordNum = | |
3841 ( (record_num + 1) > tmp_ptrFieldRecord -> NextRecordNum ) ? | |
3842 (record_num + 1) : tmp_ptrFieldRecord -> NextRecordNum ; | |
3843 | |
3844 #ifdef INSERTION_SORT | |
3845 | |
3846 /* get the sort lists in RAM from FFS */ | |
3847 get_sort_lists_from_FFS( (UBYTE)db_handle, fld_ctr ); | |
3848 | |
3849 /* note the record number for sorting later | |
3850 yeah, we call it *after* updating UsedRecords */ | |
3851 new_in_sort_lists( (UBYTE)db_handle, fld_ctr, (UBYTE)record_num ); | |
3852 | |
3853 #endif | |
3854 | |
3855 } | |
3856 | |
3857 DbmMaster[db_handle].Tracked_Clean &= ~(CLEAN); | |
3858 | |
3859 /* history log updation */ | |
3860 | |
3861 db_ret_code = update_history_log( db_handle, field_id, record_num ); | |
3862 | |
3863 if( db_ret_code NEQ DB_OK ) | |
3864 DB_RETURN( db_ret_code ); | |
3865 | |
3866 DB_VALUE_RETURN( record_num ); | |
3867 | |
3868 } | |
3869 | |
3870 /* | |
3871 +--------------------------------------------------------------------+ | |
3872 | PROJECT: PHB MODULE: DBM | | |
3873 | ROUINE: db_create_index | | |
3874 +--------------------------------------------------------------------+ | |
3875 | |
3876 PURPOSE : Creates or updates a sort index for a given (database, field) | |
3877 */ | |
3878 T_DB_CODE db_create_index ( int db_handle, | |
3879 USHORT field_id, | |
3880 UBYTE sort_index, | |
3881 T_COMP_FUNC compare_function, | |
3882 ULONG flags ) | |
3883 { | |
3884 | |
3885 return internal_db_sort( db_handle, | |
3886 field_id, | |
3887 sort_index, | |
3888 compare_function, | |
3889 flags, | |
3890 QUICK_SORT ); | |
3891 } | |
3892 | |
3893 | |
3894 #ifdef INSERTION_SORT | |
3895 /* | |
3896 +--------------------------------------------------------------------+ | |
3897 | PROJECT: PHB MODULE: DBM | | |
3898 | ROUINE: db_update_index | | |
3899 +--------------------------------------------------------------------+ | |
3900 | |
3901 PURPOSE : Sort the list for newly added/deleted records (uses incremental | |
3902 sort i.e. add the element at the right place) | |
3903 */ | |
3904 T_DB_CODE db_update_index ( int db_handle, | |
3905 USHORT field_id, | |
3906 UBYTE sort_index, | |
3907 T_COMP_FUNC compare_function, | |
3908 ULONG flags ) | |
3909 { | |
3910 | |
3911 return internal_db_sort( db_handle, | |
3912 field_id, | |
3913 sort_index, | |
3914 compare_function, | |
3915 flags, | |
3916 INCREMENTAL_SORT ); | |
3917 } | |
3918 #endif /* INSERTION_SORT */ | |
3919 | |
3920 /* | |
3921 +--------------------------------------------------------------------+ | |
3922 | PROJECT: PHB MODULE: DBM | | |
3923 | ROUINE: db_get_phy_from_idx | | |
3924 +--------------------------------------------------------------------+ | |
3925 | |
3926 PURPOSE : Translates a logical entry within a given sort index to the | |
3927 physical record number | |
3928 */ | |
3929 T_DB_CODE db_get_phy_from_idx ( int db_handle, | |
3930 USHORT field_id, | |
3931 UBYTE sort_index, | |
3932 USHORT order_num ) | |
3933 { | |
3934 T_DB_CODE db_ret_code; | |
3935 UBYTE fld_ctr, | |
3936 sort_index_ctr; | |
3937 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
3938 char sort_file[FILENAME_LEN]; | |
3939 | |
3940 | |
3941 TRACE_FUNCTION("db_get_phy_from_idx()"); | |
3942 | |
3943 /* DBM_State check */ | |
3944 DBM_State_check; | |
3945 | |
3946 /* db_handle check */ | |
3947 db_ret_code = db_handle_check( db_handle ); | |
3948 if( db_ret_code NEQ DB_OK ) | |
3949 DB_RETURN( db_ret_code ); | |
3950 | |
3951 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
3952 fld_ctr = field_id_search( db_handle, field_id ); | |
3953 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
3954 DB_RETURN( DB_INVALID_FIELD ); | |
3955 | |
3956 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
3957 | |
3958 /* sanity check on order_num */ | |
3959 if( ( order_num > tmp_ptrFieldRecord -> NumOfRecords ) OR | |
3960 ( order_num EQ 0 ) ) | |
3961 DB_RETURN( DB_FAIL ); /* may be we can return 0xFF => no record for it ! */ | |
3962 | |
3963 /* Search given sort_index in SortIndexList for above field_id; | |
3964 if not found, return DB_INVALID_INDEX. */ | |
3965 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
3966 { | |
3967 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index ) | |
3968 break; | |
3969 } | |
3970 | |
3971 if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS ) | |
3972 DB_RETURN( DB_INVALID_INDEX ); | |
3973 | |
3974 /* Check if we already have sorted list in RAM structure SortedLists */ | |
3975 | |
3976 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] EQ NULL ) | |
3977 { | |
3978 /* If no, populate the sorted list from file, | |
3979 "<DBDirectory>/UD_<field_id>_sort_<sort_index>". | |
3980 Sorted lists are freed in db_flush */ | |
3981 | |
3982 sprintf( sort_file, | |
3983 "%s/UD_%d_sort_%d", | |
3984 DbmMaster[db_handle].DBDirectory, | |
3985 tmp_ptrFieldRecord -> FieldID, | |
3986 sort_index ); | |
3987 | |
3988 db_ret_code = | |
3989 populate_sorted_list_from_FFS ( | |
3990 #ifdef FFS_CLOSE_BEFORE_OPEN | |
3991 db_handle, | |
3992 #endif | |
3993 sort_file, | |
3994 tmp_ptrFieldRecord -> NumOfRecords, | |
3995 &(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]) ); | |
3996 if( db_ret_code NEQ DB_OK ) | |
3997 DB_RETURN( db_ret_code ); | |
3998 | |
3999 } /* if we have sort list */ | |
4000 | |
4001 /* Get (physical) record number for given order_num from sorted list. */ | |
4002 DB_VALUE_RETURN( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][order_num - 1] ); | |
4003 | |
4004 } | |
4005 | |
4006 /* | |
4007 +--------------------------------------------------------------------+ | |
4008 | PROJECT: PHB MODULE: DBM | | |
4009 | ROUINE: db_flush | | |
4010 +--------------------------------------------------------------------+ | |
4011 | |
4012 PURPOSE : Flush all internal data structures of the database described by | |
4013 db_handle | |
4014 */ | |
4015 T_DB_CODE db_flush ( int db_handle) | |
4016 { | |
4017 UBYTE db_ret_code, | |
4018 clean_byte, | |
4019 fld_ctr, | |
4020 i; | |
4021 | |
4022 char field_file[FILENAME_LEN]; | |
4023 | |
4024 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
4025 | |
4026 char sort_file[FILENAME_LEN]; | |
4027 | |
4028 T_FFS_STAT ffs_file_stat; | |
4029 T_FFS_SIZE ffs_ret_code; | |
4030 | |
4031 TRACE_FUNCTION("db_flush()"); | |
4032 | |
4033 /* DBM_State check */ | |
4034 DBM_State_check; | |
4035 | |
4036 /* db_handle check */ | |
4037 db_ret_code = db_handle_check( db_handle ); | |
4038 if( db_ret_code NEQ DB_OK ) | |
4039 DB_RETURN( db_ret_code ); | |
4040 | |
4041 /* Clear "clean" in "~/dbm/DD_<db_handle>" for fields. | |
4042 after ffs updation, update RAM data */ | |
4043 | |
4044 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle ); | |
4045 | |
4046 clean_byte = CLEAN; | |
4047 | |
4048 /* Update the affected field records */ | |
4049 | |
4050 #ifdef FFS_CLOSE_BEFORE_OPEN | |
4051 db_close_user_field_files( db_handle ); | |
4052 #endif; | |
4053 | |
4054 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord; | |
4055 | |
4056 for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr ) | |
4057 { | |
4058 if( tmp_ptrFieldRecord -> FieldID EQ INVALID_FIELD_ID ) /* if not valid field id */ | |
4059 { | |
4060 ++tmp_ptrFieldRecord; /* next field */ | |
4061 continue; | |
4062 } | |
4063 | |
4064 /* Clear file handles */ | |
4065 #ifndef FFS_CLOSE_BEFORE_OPEN | |
4066 | |
4067 if( tmp_ptrFieldRecord -> FFSFileHandle NEQ NULL ) | |
4068 { | |
4069 DB_FFS_CLOSE( tmp_ptrFieldRecord -> FFSFileHandle ); | |
4070 tmp_ptrFieldRecord -> FFSFileHandle = NULL; | |
4071 } | |
4072 | |
4073 #else | |
4074 /* Done it closing before for loop */ | |
4075 #endif | |
4076 | |
4077 /* Write sort lists to FFS and clear (free memory) sort lists */ | |
4078 for( i = 0; i < MAX_NUM_OF_SORT_INDEXS; ++i ) | |
4079 { | |
4080 if( tmp_ptrFieldRecord -> SortedLists[i] NEQ NULL ) | |
4081 { | |
4082 /* currently I am not removing unused entries in sort list */ | |
4083 /* Write sorted lists to "<DBDirectory>/UD_<field_id>_sort_<sort_index>". */ | |
4084 | |
4085 sprintf( sort_file, | |
4086 "%s/UD_%d_sort_%d", | |
4087 DbmMaster[db_handle].DBDirectory, | |
4088 tmp_ptrFieldRecord -> FieldID, | |
4089 tmp_ptrFieldRecord -> SortIndexList[i] ); | |
4090 | |
4091 /* writing sorted lists to FFS s required in two cases | |
4092 1) the field is not clean and/or | |
4093 2) sort file does not exist, but we have sort list (happen during | |
4094 bootup time with zero records) | |
4095 */ | |
4096 | |
4097 ffs_ret_code = ffs_stat( sort_file, &ffs_file_stat ); | |
4098 | |
4099 if( ( ffs_ret_code NEQ EFFS_OK ) AND | |
4100 ( ffs_ret_code NEQ EFFS_NOTFOUND ) ) | |
4101 { | |
4102 LastFFS_ReturnCode = ffs_ret_code; | |
4103 DB_MFREE( tmp_ptrFieldRecord -> SortedLists[i] ); | |
4104 tmp_ptrFieldRecord -> SortedLists[i] = NULL; | |
4105 DB_RETURN( DB_FAIL_FS ); | |
4106 } | |
4107 | |
4108 if( ( NOT tmp_ptrFieldRecord -> Clean ) OR /* not clean (consistent) */ | |
4109 ( ffs_ret_code EQ EFFS_NOTFOUND ) ) /* file does not exist */ | |
4110 { | |
4111 db_ret_code = | |
4112 write_sorted_list_to_FFS ( | |
4113 #ifdef FFS_CLOSE_BEFORE_OPEN | |
4114 db_handle, | |
4115 #endif | |
4116 sort_file, | |
4117 tmp_ptrFieldRecord -> NumOfRecords, | |
4118 tmp_ptrFieldRecord -> SortedLists[i] ); | |
4119 | |
4120 if( db_ret_code NEQ DB_OK ) | |
4121 { | |
4122 DB_MFREE( tmp_ptrFieldRecord -> SortedLists[i] ); | |
4123 tmp_ptrFieldRecord -> SortedLists[i] = NULL; | |
4124 DB_RETURN( db_ret_code ); | |
4125 } | |
4126 } | |
4127 | |
4128 /* writing in sort file is over */ | |
4129 DB_MFREE( tmp_ptrFieldRecord -> SortedLists[i] ); | |
4130 tmp_ptrFieldRecord -> SortedLists[i] = NULL; | |
4131 } | |
4132 } | |
4133 | |
4134 if( tmp_ptrFieldRecord -> Clean ) /* is it clean (consistent) ? */ | |
4135 { | |
4136 ++tmp_ptrFieldRecord; /* next field */ | |
4137 continue; | |
4138 } | |
4139 | |
4140 /* Clear "clean" in "~/dbm/DD_<db_handle>" if not clean */ | |
4141 | |
4142 db_ret_code = | |
4143 update_field_data_in_FFS ( (const char*)field_file, | |
4144 &DbmMaster[db_handle].FFSFileHandle, | |
4145 #ifdef FFS_CLOSE_BEFORE_OPEN | |
4146 db_handle, | |
4147 #endif | |
4148 fld_ctr, | |
4149 T_DB_FIELD_RECORD_SIZE, | |
4150 &clean_byte, | |
4151 ( T_DB_FIELD_RECORD_SIZE - 1 ) , | |
4152 1 ); /* "Clean" contained in last one byte */ | |
4153 | |
4154 if( db_ret_code NEQ DB_OK ) | |
4155 { | |
4156 /* this leaves out FFS and RAM in consistent state, | |
4157 this is ok since FFS is in correct state for some of fields ! */ | |
4158 DB_RETURN( db_ret_code ); | |
4159 } | |
4160 | |
4161 tmp_ptrFieldRecord -> Clean = CLEAN; | |
4162 | |
4163 ++tmp_ptrFieldRecord; /* next field */ | |
4164 | |
4165 } /* for all field records */ | |
4166 | |
4167 if( DbmMaster[db_handle].FFSFileHandle NEQ NULL ) | |
4168 { | |
4169 DB_FFS_CLOSE( DbmMaster[db_handle].FFSFileHandle ); | |
4170 } | |
4171 | |
4172 /* updation of FFS is over */ | |
4173 | |
4174 /* Update corresponding "clean" field for database in RAM data structures, | |
4175 also DBState = OPEN */ | |
4176 DbmMaster[db_handle].Tracked_Clean |= CLEAN; | |
4177 DbmMaster[db_handle].DBState = OPEN; | |
4178 | |
4179 /* done */ | |
4180 DB_RETURN( DB_OK ); | |
4181 } | |
4182 | |
4183 /* | |
4184 +--------------------------------------------------------------------+ | |
4185 | PROJECT: PHB MODULE: DBM | | |
4186 | ROUINE: db_search | | |
4187 +--------------------------------------------------------------------+ | |
4188 | |
4189 PURPOSE : Searches for an entry within a given database and a given file | |
4190 */ | |
4191 int db_search ( int db_handle, | |
4192 USHORT field_id, | |
4193 UBYTE sort_index, | |
4194 UBYTE* order_num, | |
4195 T_SEARCH_FUNC search_function, | |
4196 ULONG flags, | |
4197 const UBYTE* search_tag ) | |
4198 { | |
4199 T_DB_CODE db_ret_code; | |
4200 | |
4201 UBYTE fld_ctr, | |
4202 tmp_byte, | |
4203 sort_index_ctr, | |
4204 bit_num; | |
4205 | |
4206 UBYTE* tmp_byte_ptr; | |
4207 | |
4208 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
4209 | |
4210 char sort_file[FILENAME_LEN]; | |
4211 | |
4212 int record_num = 0, | |
4213 index_num ; | |
4214 | |
4215 TRACE_FUNCTION("db_search()"); | |
4216 | |
4217 /* DBM_State check */ | |
4218 DBM_State_check; | |
4219 | |
4220 /* db_handle check */ | |
4221 db_ret_code = db_handle_check( db_handle ); | |
4222 if( db_ret_code NEQ DB_OK ) | |
4223 DB_RETURN( db_ret_code ); | |
4224 | |
4225 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
4226 fld_ctr = field_id_search( db_handle, field_id ); | |
4227 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
4228 DB_RETURN( DB_INVALID_FIELD ); | |
4229 | |
4230 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
4231 | |
4232 if( sort_index EQ 0 ) | |
4233 { | |
4234 /* If sort_index is zero, | |
4235 o Do linear search using RecordBitMap, search/comparison function is given by caller. | |
4236 o If search is successful, return the record number. | |
4237 o Otherwise return DB_RECORD_NOT_FOUND. */ | |
4238 | |
4239 /* Sanity check */ | |
4240 if( (*order_num) > tmp_ptrFieldRecord -> NumOfRecords ) | |
4241 DB_RETURN( DB_FAIL ); | |
4242 | |
4243 /* search from next record, | |
4244 search_node->top would be zero for fresh search */ | |
4245 | |
4246 record_num = *order_num; | |
4247 | |
4248 /* get the correct byte */ | |
4249 tmp_byte_ptr = | |
4250 tmp_ptrFieldRecord -> RecordBitMap + RECORD_BITMAP_SIZE - BITMAP_INDEX(record_num) - 1; | |
4251 tmp_byte = *tmp_byte_ptr; | |
4252 | |
4253 /* get the correct bit position */ | |
4254 bit_num = BIT_POS(record_num); | |
4255 tmp_byte >>= bit_num; | |
4256 | |
4257 /* for bytes in bitmap */ | |
4258 while( record_num < tmp_ptrFieldRecord -> NumOfRecords ) | |
4259 { | |
4260 /* for bits in byte */ | |
4261 while( bit_num < MAX_BIT_POS ) | |
4262 { | |
4263 if( record_num > tmp_ptrFieldRecord -> NumOfRecords ) | |
4264 break; | |
4265 | |
4266 if( NOT (tmp_byte & 0x01 ) ) /* if record does not exist, move on to next */ | |
4267 { | |
4268 tmp_byte >>= 1; | |
4269 ++bit_num; | |
4270 ++record_num; | |
4271 continue; | |
4272 } | |
4273 | |
4274 /* ok, this is a valid record */ | |
4275 | |
4276 if( search_function( flags, | |
4277 search_tag, | |
4278 db_handle, | |
4279 field_id, | |
4280 (UBYTE)record_num ) | |
4281 EQ 0 ) /* yeah, "EQ 0" is success */ | |
4282 { | |
4283 /* found it ! */ | |
4284 *order_num = record_num; /* for next search */ | |
4285 DB_VALUE_RETURN( record_num ); | |
4286 } | |
4287 | |
4288 tmp_byte >>= 1; | |
4289 ++bit_num; | |
4290 ++record_num; | |
4291 | |
4292 } /* for bits in byte */ | |
4293 | |
4294 --tmp_byte_ptr; | |
4295 tmp_byte = *tmp_byte_ptr; | |
4296 bit_num = 0; | |
4297 | |
4298 } /* for bytes in bitmap */ | |
4299 | |
4300 /* record not found */ | |
4301 DB_RETURN( DB_RECORD_NOT_FOUND ); | |
4302 | |
4303 } else { | |
4304 /* If sort_index is not zero, search using sorted list */ | |
4305 | |
4306 /* Search given sort_index in SortIndexList for above field_id; | |
4307 if not found, return DB_INVALID_INDEX. */ | |
4308 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
4309 { | |
4310 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index ) | |
4311 break; | |
4312 } | |
4313 | |
4314 if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS ) | |
4315 DB_RETURN( DB_INVALID_INDEX ); | |
4316 | |
4317 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] EQ NULL ) | |
4318 { | |
4319 /* If no, populate the sorted list from file, | |
4320 "<DBDirectory>/UD_<field_id>_sort_<sort_index>". | |
4321 Sorted lists are freed in db_flush */ | |
4322 | |
4323 sprintf( sort_file, | |
4324 "%s/UD_%d_sort_%d", | |
4325 DbmMaster[db_handle].DBDirectory, | |
4326 tmp_ptrFieldRecord -> FieldID, | |
4327 sort_index ); | |
4328 | |
4329 db_ret_code = | |
4330 populate_sorted_list_from_FFS ( | |
4331 | |
4332 #ifdef FFS_CLOSE_BEFORE_OPEN | |
4333 db_handle, | |
4334 #endif | |
4335 sort_file, | |
4336 tmp_ptrFieldRecord -> NumOfRecords, | |
4337 &(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]) ); | |
4338 | |
4339 if( db_ret_code NEQ DB_OK ) | |
4340 DB_RETURN( db_ret_code ); | |
4341 | |
4342 } | |
4343 | |
4344 /* (Binary) search the sorted list, search/compare function is given by caller. | |
4345 o If search is successful, return the record number. | |
4346 o Otherwise return DB_RECORD_NOT_FOUND */ | |
4347 | |
4348 | |
4349 index_num = | |
4350 search( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr], | |
4351 tmp_ptrFieldRecord -> UsedRecords, | |
4352 order_num, | |
4353 search_function, | |
4354 flags, | |
4355 search_tag, | |
4356 db_handle, | |
4357 field_id ); | |
4358 | |
4359 if( index_num EQ SEARCH_FAILED ) | |
4360 DB_RETURN( DB_RECORD_NOT_FOUND ); | |
4361 | |
4362 DB_VALUE_RETURN( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][index_num - 1] ); | |
4363 | |
4364 } | |
4365 } | |
4366 | |
4367 /* | |
4368 +--------------------------------------------------------------------+ | |
4369 | PROJECT: PHB MODULE: DBM | | |
4370 | ROUINE: db_delete_record | | |
4371 +--------------------------------------------------------------------+ | |
4372 | |
4373 PURPOSE : Delete a record in the given field of the given database | |
4374 */ | |
4375 T_DB_CODE db_delete_record ( int db_handle, | |
4376 USHORT field_id, | |
4377 USHORT record_num ) | |
4378 { | |
4379 T_DB_CODE db_ret_code; | |
4380 | |
4381 UBYTE fld_ctr, | |
4382 tmp_byte; | |
4383 | |
4384 char field_file[FILENAME_LEN]; | |
4385 | |
4386 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
4387 | |
4388 UBYTE* field_data; | |
4389 | |
4390 TRACE_FUNCTION("db_delete_record()"); | |
4391 | |
4392 /* DBM_State check */ | |
4393 DBM_State_check; | |
4394 | |
4395 /* db_handle check */ | |
4396 db_ret_code = db_handle_check( db_handle ); | |
4397 if( db_ret_code NEQ DB_OK ) | |
4398 DB_RETURN( db_ret_code ); | |
4399 | |
4400 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
4401 fld_ctr = field_id_search( db_handle, field_id ); | |
4402 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
4403 DB_RETURN( DB_INVALID_FIELD ); | |
4404 | |
4405 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
4406 | |
4407 /* Using RecordBitMap, check whether record_num exists; | |
4408 if it does not exist, return DB_OK. */ | |
4409 | |
4410 tmp_byte = | |
4411 (tmp_ptrFieldRecord -> RecordBitMap)[ RECORD_BITMAP_SIZE - BITMAP_INDEX(record_num) - 1]; | |
4412 | |
4413 if( NOT ( tmp_byte & ( 0x01 << BIT_POS(record_num) ) ) ) /* if record does *not* exist */ | |
4414 DB_RETURN( DB_OK ); | |
4415 | |
4416 /* Update "Clean" and "RecordBitMap" fields in "~/dbm/DD_<db_handle>" */ | |
4417 | |
4418 /* create the field data that is to be written */ | |
4419 | |
4420 DB_MALLOC( field_data, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
4421 memset( field_data, 0, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
4422 memcpy( field_data, tmp_ptrFieldRecord -> RecordBitMap, RECORD_BITMAP_SIZE ); | |
4423 | |
4424 /* updating RecordBitMap */ | |
4425 reset_bit_in_bitmap( field_data, | |
4426 RECORD_BITMAP_SIZE, | |
4427 (UBYTE)record_num ); | |
4428 | |
4429 /* clean is reset in memset, so no processing for it | |
4430 (in case of non-tracked database, anyway we ignore it ! */ | |
4431 | |
4432 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle ); | |
4433 | |
4434 db_ret_code = | |
4435 update_field_data_in_FFS ( (const char*)field_file, | |
4436 &DbmMaster[db_handle].FFSFileHandle, | |
4437 #ifdef FFS_CLOSE_BEFORE_OPEN | |
4438 db_handle, | |
4439 #endif | |
4440 fld_ctr, | |
4441 T_DB_FIELD_RECORD_SIZE, | |
4442 field_data, | |
4443 RecordBitMap_OFFSET, | |
4444 ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
4445 | |
4446 if( db_ret_code NEQ DB_OK ) | |
4447 { | |
4448 DB_MFREE( field_data ); | |
4449 DB_RETURN( db_ret_code ); | |
4450 } | |
4451 | |
4452 DB_MFREE( field_data ); | |
4453 /* updation of DD_<db_handle> is over */ | |
4454 | |
4455 /* Update corresponding "Clean" and "RecordBitMap" fields in RAM data structures, | |
4456 also update DBState (as IN_USE) and decrement UsedRecords. */ | |
4457 | |
4458 tmp_ptrFieldRecord -> Clean = NOT_CLEAN; | |
4459 | |
4460 /* updating RecordBitMap */ | |
4461 reset_bit_in_bitmap( tmp_ptrFieldRecord -> RecordBitMap, | |
4462 RECORD_BITMAP_SIZE, | |
4463 (UBYTE)record_num ); | |
4464 | |
4465 #ifdef INSERTION_SORT | |
4466 | |
4467 /* get the sort lists in RAM from FFS */ | |
4468 get_sort_lists_from_FFS( (UBYTE)db_handle, fld_ctr ); | |
4469 | |
4470 /* delete in available sort lists | |
4471 yeah, we call it *before* updating UsedRecords */ | |
4472 delete_in_sort_lists( (UBYTE)db_handle, fld_ctr, (UBYTE)record_num ); | |
4473 | |
4474 #endif /* INSERTION_SORT */ | |
4475 | |
4476 --tmp_ptrFieldRecord -> UsedRecords; | |
4477 | |
4478 DbmMaster[db_handle].Tracked_Clean &= ~ (CLEAN); | |
4479 DbmMaster[db_handle].DBState = IN_USE; | |
4480 | |
4481 /* history log updation */ | |
4482 | |
4483 return update_history_log( db_handle, field_id, record_num ); | |
4484 | |
4485 } | |
4486 | |
4487 /* | |
4488 +--------------------------------------------------------------------+ | |
4489 | PROJECT: PHB MODULE: DBM | | |
4490 | ROUINE: db_read_record | | |
4491 +--------------------------------------------------------------------+ | |
4492 | |
4493 PURPOSE : Read length bytes at offset from the record in given (database, field) | |
4494 */ | |
4495 int db_read_record ( int db_handle, | |
4496 USHORT field_id, | |
4497 USHORT record_num, | |
4498 USHORT offset, | |
4499 USHORT length, | |
4500 UBYTE* record_buffer ) | |
4501 { | |
4502 T_DB_CODE db_ret_code; | |
4503 | |
4504 UBYTE fld_ctr, | |
4505 tmp_byte; | |
4506 | |
4507 char user_field_file[FILENAME_LEN]; | |
4508 | |
4509 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
4510 | |
4511 | |
4512 TRACE_FUNCTION("db_read_record()"); | |
4513 | |
4514 /* DBM_State check */ | |
4515 DBM_State_check; | |
4516 | |
4517 /* db_handle check */ | |
4518 db_ret_code = db_handle_check( db_handle ); | |
4519 if( db_ret_code NEQ DB_OK ) | |
4520 DB_RETURN( db_ret_code ); | |
4521 | |
4522 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
4523 fld_ctr = field_id_search( db_handle, field_id ); | |
4524 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
4525 DB_RETURN( DB_INVALID_FIELD ); | |
4526 | |
4527 /* Using RecordBitMap, check whether record_num exists; | |
4528 if it does not exist, return DB_EMPTY_RECORD. */ | |
4529 | |
4530 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
4531 | |
4532 tmp_byte = | |
4533 (tmp_ptrFieldRecord -> RecordBitMap)[ RECORD_BITMAP_SIZE - BITMAP_INDEX(record_num) - 1 ]; | |
4534 | |
4535 if( NOT ( tmp_byte & ( 0x01 << BIT_POS(record_num) ) ) ) /* if record does *not* exist */ | |
4536 DB_RETURN( DB_EMPTY_RECORD ); | |
4537 | |
4538 /* Check if record exceeds the record size (i.e. offset + length > record size); | |
4539 if it exceeds, return error DB_INVALID_SIZE */ | |
4540 if( (offset + length) > | |
4541 tmp_ptrFieldRecord -> RecordSize ) | |
4542 DB_RETURN( DB_INVALID_SIZE ); | |
4543 | |
4544 /* Check if FFS file is already opened using FFSFileHandle, part of field record. | |
4545 If it is not yet opened, open the FFS file and update FFSFileHandle. | |
4546 This is taken care in read_user_record_from_FFS below. */ | |
4547 | |
4548 /* Read record_num from "<DBDirectory>/UD_<field_id>" | |
4549 Put "length" number of bytes from "offset" in buffer. (assuming that | |
4550 buffer contain enough memory i.e. caller should take care of allocating | |
4551 enough memory space for buffer) */ | |
4552 | |
4553 /* User data file name is "<DBDirectory>/UD_<field_id>" */ | |
4554 | |
4555 sprintf( user_field_file, | |
4556 "%s/UD_%d", | |
4557 DbmMaster[db_handle].DBDirectory, | |
4558 tmp_ptrFieldRecord -> FieldID ); | |
4559 | |
4560 db_ret_code = | |
4561 read_user_record_from_FFS ( user_field_file, | |
4562 | |
4563 #ifndef FFS_CLOSE_BEFORE_OPEN | |
4564 &(tmp_ptrFieldRecord -> FFSFileHandle), | |
4565 #else | |
4566 db_handle, | |
4567 fld_ctr, | |
4568 &Dummy_FFSFileHandle, | |
4569 #endif | |
4570 (UBYTE)record_num, | |
4571 tmp_ptrFieldRecord -> RecordSize, | |
4572 offset, | |
4573 length, | |
4574 record_buffer ); | |
4575 | |
4576 if( db_ret_code NEQ DB_OK ) | |
4577 DB_RETURN( db_ret_code ); | |
4578 | |
4579 DB_VALUE_RETURN( record_num ); | |
4580 } | |
4581 | |
4582 /* | |
4583 +--------------------------------------------------------------------+ | |
4584 | PROJECT: PHB MODULE: DBM | | |
4585 | ROUINE: db_remove | | |
4586 +--------------------------------------------------------------------+ | |
4587 | |
4588 PURPOSE : Remove a database. The database must not be in use. | |
4589 */ | |
4590 T_DB_CODE db_remove ( const char* directory ) | |
4591 { | |
4592 int db_handle; | |
4593 | |
4594 UBYTE db_ctr, | |
4595 fld_ctr; | |
4596 | |
4597 T_DB_CODE db_ret_code; | |
4598 | |
4599 UBYTE* dbm_data; | |
4600 UBYTE field_file[FILENAME_LEN]; | |
4601 | |
4602 | |
4603 | |
4604 TRACE_FUNCTION("db_remove()"); | |
4605 | |
4606 /* DBM_State check */ | |
4607 DBM_State_check; | |
4608 | |
4609 /* Search for "directory" in DbmMaster | |
4610 If not found, return DB_INVALID_DB */ | |
4611 | |
4612 for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr ) | |
4613 { | |
4614 if ( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY ) | |
4615 { | |
4616 if( memcmp( DbmMaster[db_ctr].DBDirectory, | |
4617 directory, | |
4618 strlen(directory) ) EQ 0 ) | |
4619 break; | |
4620 } | |
4621 } | |
4622 | |
4623 if( db_ctr EQ MAX_DBs ) | |
4624 DB_RETURN( DB_INVALID_DB ); | |
4625 | |
4626 db_handle = db_ctr; | |
4627 | |
4628 /* If DBState for found database in DbmMaster is OPEN or IN_USE, return error DB_IN_USE */ | |
4629 | |
4630 if( ( DbmMaster[db_ctr].DBState EQ OPEN ) OR | |
4631 ( DbmMaster[db_ctr].DBState EQ IN_USE ) ) | |
4632 DB_RETURN( DB_IN_USE ); | |
4633 | |
4634 | |
4635 /* Delete all files under directory "<DBDirectory>" (DBDirectory = directory) */ | |
4636 | |
4637 for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr ) | |
4638 { | |
4639 db_ret_code = remove_field_from_FFS( (UBYTE)db_handle, fld_ctr ); | |
4640 | |
4641 if( db_ret_code NEQ DB_OK ) | |
4642 DB_RETURN( db_ret_code ); | |
4643 } | |
4644 | |
4645 /* Delete the DBDirectory */ | |
4646 db_ret_code = delete_file_dir_from_FFS ( (const char*)DbmMaster[db_handle].DBDirectory ); | |
4647 | |
4648 if( db_ret_code NEQ DB_OK ) | |
4649 DB_RETURN( db_ret_code ); | |
4650 | |
4651 /* Delete Field file = DD_<pos. in DD_master> */ | |
4652 | |
4653 sprintf( field_file, "%s/DD_%d", DB_DIR, db_ctr); | |
4654 | |
4655 db_ret_code = delete_file_dir_from_FFS ( (const char*)field_file ); | |
4656 | |
4657 if( db_ret_code NEQ DB_OK ) | |
4658 DB_RETURN( db_ret_code ); | |
4659 | |
4660 /* Update FFS data i.e. file, "~/dbm/DD_master" */ | |
4661 | |
4662 /* prepare the dbm data and write */ | |
4663 | |
4664 DB_MALLOC( dbm_data, T_DB_MASTER_RECORD_SIZE ); | |
4665 memset( dbm_data, 0xFF, T_DB_MASTER_RECORD_SIZE ); | |
4666 | |
4667 db_ret_code = | |
4668 update_dbm_data_in_FFS ( DB_MASTER_FILE, | |
4669 (UBYTE) db_handle, /* to supress warning */ | |
4670 T_DB_MASTER_RECORD_SIZE, | |
4671 dbm_data, | |
4672 0, | |
4673 T_DB_MASTER_RECORD_SIZE ); | |
4674 | |
4675 if( db_ret_code NEQ DB_OK ) | |
4676 { | |
4677 DB_MFREE( dbm_data ); | |
4678 DB_RETURN( db_ret_code ); | |
4679 } | |
4680 | |
4681 DB_MFREE( dbm_data ); | |
4682 | |
4683 /* updation of DD_master done */ | |
4684 | |
4685 /* Free the memory for field records. | |
4686 Update this entry in DbmMaster as unused. (DBState = UNUSED_ENTRY). | |
4687 Also, decrement UsedDBs. */ | |
4688 | |
4689 DB_MFREE( DbmMaster[db_handle].ptrFieldRecord ); | |
4690 | |
4691 DbmMaster[db_handle].DBState = UNUSED_ENTRY; | |
4692 | |
4693 --UsedDBs; | |
4694 | |
4695 /* everything ok ! */ | |
4696 DB_RETURN( DB_OK ); | |
4697 | |
4698 } | |
4699 | |
4700 /* | |
4701 +--------------------------------------------------------------------+ | |
4702 | PROJECT: PHB MODULE: DBM | | |
4703 | ROUINE: db_close | | |
4704 +--------------------------------------------------------------------+ | |
4705 | |
4706 PURPOSE : Close a database; if in use, it flushes it before closing it. | |
4707 */ | |
4708 T_DB_CODE db_close ( int db_handle ) | |
4709 { | |
4710 TRACE_FUNCTION("db_close()"); | |
4711 | |
4712 /* DBM_State check */ | |
4713 DBM_State_check; | |
4714 | |
4715 /* Check for db_handle range */ | |
4716 if( db_handle >= MAX_DBs ) | |
4717 DB_RETURN( DB_INVALID_DB ); | |
4718 | |
4719 /* If DBState for db_handleth position in DbmMaster is | |
4720 o UNUSED_ENTRY, return error DB_INVALID_DB | |
4721 o CLOSED, return DB_OK. | |
4722 o OPEN, update DBState as CLOSED and return DB_OK. | |
4723 o IN_USE, call db_flush, update DBState as CLOSED and return DB_OK */ | |
4724 | |
4725 switch( DbmMaster[db_handle].DBState ) | |
4726 { | |
4727 case UNUSED_ENTRY: DB_RETURN( DB_INVALID_DB ); | |
4728 | |
4729 case CLOSED: DB_RETURN( DB_OK ); | |
4730 | |
4731 case OPEN: | |
4732 case IN_USE: { | |
4733 db_flush( db_handle ); | |
4734 DbmMaster[db_handle].DBState = CLOSED; | |
4735 DB_RETURN( DB_OK ); | |
4736 } | |
4737 | |
4738 default: DB_RETURN( DB_FAIL ); | |
4739 } | |
4740 | |
4741 } | |
4742 | |
4743 /* | |
4744 +--------------------------------------------------------------------+ | |
4745 | PROJECT: PHB MODULE: DBM | | |
4746 | ROUINE: db_exit | | |
4747 +--------------------------------------------------------------------+ | |
4748 | |
4749 PURPOSE : Shutdown the data base | |
4750 */ | |
4751 void db_exit ( void ) | |
4752 { | |
4753 /* It is assumed as "forced" exit and so no error would be | |
4754 raised even if database is in use. Also, here we will not | |
4755 delete the database, but just sync the database and free | |
4756 the RAM structures. | |
4757 | |
4758 1) Call db_flush for all databases present in DbmMaster. | |
4759 2) Free the memory for field records for all databases. | |
4760 3) Update all entries in DbmMaster as unused (this step is not required) | |
4761 4) Set DBM_State as DBM_NOT_INITIALISED. */ | |
4762 | |
4763 UBYTE db_ctr; | |
4764 | |
4765 for ( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr ) | |
4766 { | |
4767 if( DbmMaster[db_ctr].DBState EQ UNUSED_ENTRY ) | |
4768 continue; | |
4769 | |
4770 db_close( db_ctr ); | |
4771 | |
4772 DB_MFREE( DbmMaster[db_ctr].ptrFieldRecord ); | |
4773 | |
4774 DbmMaster[db_ctr].DBState = UNUSED_ENTRY; | |
4775 | |
4776 } | |
4777 | |
4778 DBM_State = DBM_NOT_INITIALISED; | |
4779 | |
4780 UsedDBs = 0; | |
4781 | |
4782 return; | |
4783 } | |
4784 | |
4785 /* | |
4786 +--------------------------------------------------------------------+ | |
4787 | PROJECT: PHB MODULE: DBM | | |
4788 | ROUINE: db_remove_field | | |
4789 +--------------------------------------------------------------------+ | |
4790 | |
4791 PURPOSE : Delete field in given database | |
4792 */ | |
4793 T_DB_CODE db_remove_field ( int db_handle, | |
4794 USHORT field_id ) | |
4795 { | |
4796 UBYTE fld_ctr, | |
4797 db_ret_code; | |
4798 | |
4799 UBYTE* field_data; | |
4800 | |
4801 char field_file[FILENAME_LEN]; | |
4802 | |
4803 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
4804 | |
4805 TRACE_FUNCTION("db_remove_field()"); | |
4806 | |
4807 /* DBM_State check */ | |
4808 DBM_State_check; | |
4809 | |
4810 /* db_handle check */ | |
4811 db_ret_code = db_handle_check( db_handle ); | |
4812 if( db_ret_code NEQ DB_OK ) | |
4813 DB_RETURN( db_ret_code ); | |
4814 | |
4815 /* field id search; if field id not found, return error DB_INVALID_FIELD */ | |
4816 fld_ctr = field_id_search( db_handle, field_id ); | |
4817 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
4818 DB_RETURN( DB_INVALID_FIELD ); | |
4819 | |
4820 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
4821 | |
4822 #ifndef FFS_CLOSE_BEFORE_OPEN | |
4823 | |
4824 /* Check if FFS file is open using FFSFileHandle, part of field record; | |
4825 if so, return error DB_IN_USE. */ | |
4826 if( tmp_ptrFieldRecord -> FFSFileHandle NEQ NULL ) | |
4827 DB_RETURN( DB_IN_USE ); | |
4828 | |
4829 #else | |
4830 | |
4831 if( db_status_user_field_file( db_handle, fld_ctr ) EQ OPENED_FOR_WRITE ) | |
4832 DB_RETURN( DB_IN_USE ); | |
4833 | |
4834 #endif | |
4835 | |
4836 /* Remove file "<DBDirectory>/UD_<field_id>" */ | |
4837 | |
4838 db_ret_code = remove_field_from_FFS( (UBYTE)db_handle, fld_ctr ); | |
4839 | |
4840 if( db_ret_code NEQ DB_OK ) | |
4841 DB_RETURN( db_ret_code ); | |
4842 | |
4843 /* Update "~/dbm/DD_<db_handle>" for removed field id. */ | |
4844 | |
4845 /* create the field data that is to be written */ | |
4846 | |
4847 DB_MALLOC( field_data, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
4848 memset( field_data, 0xFF, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
4849 | |
4850 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle ); | |
4851 | |
4852 db_ret_code = | |
4853 update_field_data_in_FFS ( (const char*)field_file, | |
4854 &DbmMaster[db_handle].FFSFileHandle, | |
4855 #ifdef FFS_CLOSE_BEFORE_OPEN | |
4856 db_handle, | |
4857 #endif | |
4858 fld_ctr, | |
4859 T_DB_FIELD_RECORD_SIZE, | |
4860 field_data, | |
4861 RecordBitMap_OFFSET, | |
4862 ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) ); | |
4863 | |
4864 if( db_ret_code NEQ DB_OK ) | |
4865 { | |
4866 DB_MFREE( field_data ); | |
4867 DB_RETURN( db_ret_code ); | |
4868 } | |
4869 | |
4870 DB_MFREE( field_data ); | |
4871 /* updation of DD_<db_handle> is over */ | |
4872 | |
4873 /* update in RAM */ | |
4874 | |
4875 tmp_ptrFieldRecord -> FieldID = INVALID_FIELD_ID; | |
4876 | |
4877 DB_RETURN( DB_OK ); | |
4878 | |
4879 } | |
4880 | |
4881 /* | |
4882 +--------------------------------------------------------------------+ | |
4883 | PROJECT: PHB MODULE: DBM | | |
4884 | ROUINE: db_read_change_log | | |
4885 +--------------------------------------------------------------------+ | |
4886 | |
4887 PURPOSE : Get an information about the changed records since the last | |
4888 call of this function | |
4889 */ | |
4890 T_DB_CODE db_read_change_log ( int db_handle, | |
4891 T_DB_CHANGED* changed) | |
4892 { | |
4893 T_DB_CODE db_ret_code; | |
4894 TRACE_FUNCTION("db_read_change_log()"); | |
4895 | |
4896 /* DBM_State check */ | |
4897 DBM_State_check; | |
4898 | |
4899 /* db_handle check */ | |
4900 db_ret_code = db_handle_check( db_handle ); | |
4901 if( db_ret_code NEQ DB_OK ) | |
4902 DB_RETURN( db_ret_code ); | |
4903 | |
4904 /* Copy contents of internal history log to HistoryRecord */ | |
4905 *changed = DB_History_log; /* This would work ?? */ | |
4906 | |
4907 /* Clear internal history log. */ | |
4908 DB_History_log.entries = 0; /* this is enough for clearing history log ! */ | |
4909 | |
4910 /* done */ | |
4911 DB_RETURN( DB_OK ); | |
4912 | |
4913 } | |
4914 | |
4915 /* | |
4916 +--------------------------------------------------------------------+ | |
4917 | PROJECT: PHB MODULE: DBM | | |
4918 | ROUINE: db_remove_index | | |
4919 +--------------------------------------------------------------------+ | |
4920 | |
4921 PURPOSE : Removes a sort index | |
4922 */ | |
4923 T_DB_CODE db_remove_index ( int db_handle, | |
4924 USHORT field_id, | |
4925 UBYTE sort_index ) | |
4926 { | |
4927 UBYTE db_ret_code, | |
4928 fld_ctr, | |
4929 sort_index_ctr; | |
4930 UBYTE field_file[FILENAME_LEN]; | |
4931 | |
4932 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
4933 | |
4934 char sort_file[FILENAME_LEN]; | |
4935 | |
4936 UBYTE* field_data; | |
4937 | |
4938 | |
4939 TRACE_FUNCTION("db_remove_index()"); | |
4940 | |
4941 /* DBM_State check */ | |
4942 DBM_State_check; | |
4943 | |
4944 /* db_handle check */ | |
4945 db_ret_code = db_handle_check( db_handle ); | |
4946 if( db_ret_code NEQ DB_OK ) | |
4947 DB_RETURN( db_ret_code ); | |
4948 | |
4949 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
4950 fld_ctr = field_id_search( db_handle, field_id ); | |
4951 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
4952 DB_RETURN( DB_INVALID_FIELD ); | |
4953 | |
4954 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
4955 | |
4956 /* Search given sort_index in SortIndexList for above field_id; | |
4957 if not found, return DB_INVALID_INDEX. */ | |
4958 for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr ) | |
4959 { | |
4960 if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index ) | |
4961 break; | |
4962 } | |
4963 | |
4964 if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS ) | |
4965 DB_RETURN( DB_INVALID_INDEX ); | |
4966 | |
4967 /* Remove file, "<DBDirectory>/UD_<field_id>_sort_<sort_index>" */ | |
4968 | |
4969 sprintf( sort_file, | |
4970 "%s/UD_%d_sort_%d", | |
4971 DbmMaster[db_handle].DBDirectory, | |
4972 tmp_ptrFieldRecord -> FieldID, | |
4973 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] ); | |
4974 | |
4975 db_ret_code = delete_file_dir_from_FFS ( sort_file ); | |
4976 | |
4977 if( db_ret_code NEQ DB_OK ) | |
4978 DB_RETURN( db_ret_code ); | |
4979 | |
4980 /* Update file , "~/dbm/DD_<db_handle>" for SortIndexes. */ | |
4981 | |
4982 /* create the field data that is to be written */ | |
4983 | |
4984 DB_MALLOC( field_data, MAX_NUM_OF_SORT_INDEXS ); | |
4985 memcpy( field_data, tmp_ptrFieldRecord -> SortIndexList, MAX_NUM_OF_SORT_INDEXS ); | |
4986 | |
4987 field_data[sort_index_ctr] = INVALID_SORT_INDEX; | |
4988 | |
4989 sprintf( field_file, "%s/DD_%d", DB_DIR, db_handle ); | |
4990 | |
4991 db_ret_code = | |
4992 update_field_data_in_FFS ( (const char*)field_file, | |
4993 &DbmMaster[db_handle].FFSFileHandle, | |
4994 #ifdef FFS_CLOSE_BEFORE_OPEN | |
4995 db_handle, | |
4996 #endif | |
4997 fld_ctr, | |
4998 T_DB_FIELD_RECORD_SIZE, | |
4999 field_data, | |
5000 SortIndexList_OFFSET, | |
5001 MAX_NUM_OF_SORT_INDEXS ); | |
5002 if( db_ret_code NEQ DB_OK ) | |
5003 { | |
5004 DB_MFREE( field_data ); | |
5005 DB_RETURN( db_ret_code ); | |
5006 } | |
5007 | |
5008 DB_MFREE( field_data ); | |
5009 /* updation of DD_<db_handle> is over */ | |
5010 | |
5011 /* Update corresponding RAM structure i.e. DbmFieldRecord | |
5012 Check if we have sort list corresponding to this sort index; if so, free it. */ | |
5013 | |
5014 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] = INVALID_SORT_INDEX; | |
5015 if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] NEQ NULL ) | |
5016 { | |
5017 DB_MFREE( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] ); | |
5018 tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] = NULL; | |
5019 } | |
5020 | |
5021 DB_RETURN( DB_OK ); | |
5022 } | |
5023 | |
5024 /* | |
5025 +--------------------------------------------------------------------+ | |
5026 | PROJECT: PHB MODULE: DBM | | |
5027 | ROUINE: db_field_changed | | |
5028 +--------------------------------------------------------------------+ | |
5029 | |
5030 PURPOSE : Check whether a database field has been changed since last | |
5031 db_flush(). | |
5032 */ | |
5033 T_DB_CODE db_field_changed ( int db_handle, | |
5034 USHORT field_id, | |
5035 BOOL* changed ) | |
5036 { | |
5037 UBYTE fld_ctr; | |
5038 T_DB_CODE db_ret_code; | |
5039 | |
5040 TRACE_FUNCTION("db_field_changed()"); | |
5041 | |
5042 /* DBM_State check */ | |
5043 DBM_State_check; | |
5044 | |
5045 /* db_handle check */ | |
5046 db_ret_code = db_handle_check( db_handle ); | |
5047 if( db_ret_code NEQ DB_OK ) | |
5048 DB_RETURN( db_ret_code ); | |
5049 | |
5050 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
5051 fld_ctr = field_id_search( db_handle, field_id ); | |
5052 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
5053 DB_RETURN( DB_INVALID_FIELD ); | |
5054 | |
5055 /* Check "Clean" field in field record; | |
5056 a) if (Clean = true), changed = false. */ | |
5057 | |
5058 *changed = NOT DbmMaster[db_handle].ptrFieldRecord[fld_ctr].Clean; | |
5059 | |
5060 DB_RETURN( DB_OK ); | |
5061 } | |
5062 | |
5063 /* | |
5064 +--------------------------------------------------------------------+ | |
5065 | PROJECT: PHB MODULE: DBM | | |
5066 | ROUINE: db_record_empty | | |
5067 +--------------------------------------------------------------------+ | |
5068 | |
5069 PURPOSE : Check whether a database field is empty. The result is | |
5070 given to the caller in the *empty variable | |
5071 */ | |
5072 T_DB_CODE db_record_empty ( int db_handle, | |
5073 USHORT field_id, | |
5074 USHORT record_num, | |
5075 BOOL* empty ) | |
5076 { | |
5077 UBYTE fld_ctr, | |
5078 tmp_byte; | |
5079 T_DB_CODE db_ret_code; | |
5080 | |
5081 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
5082 | |
5083 | |
5084 TRACE_FUNCTION("db_record_empty()"); | |
5085 | |
5086 *empty = TRUE; | |
5087 | |
5088 /* DBM_State check */ | |
5089 DBM_State_check; | |
5090 | |
5091 /* db_handle check */ | |
5092 db_ret_code = db_handle_check( db_handle ); | |
5093 if( db_ret_code NEQ DB_OK ) | |
5094 DB_RETURN( db_ret_code ); | |
5095 | |
5096 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
5097 fld_ctr = field_id_search( db_handle, field_id ); | |
5098 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
5099 DB_RETURN( DB_INVALID_FIELD ); | |
5100 | |
5101 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
5102 | |
5103 /* Using RecordBitMap, check whether record_num is free; | |
5104 if so, empty = true and false otherwise */ | |
5105 | |
5106 tmp_byte = | |
5107 (tmp_ptrFieldRecord -> RecordBitMap)[ RECORD_BITMAP_SIZE - BITMAP_INDEX(record_num) - 1 ]; | |
5108 | |
5109 if( tmp_byte & ( 0x01 << BIT_POS(record_num) ) ) /* if record exist */ | |
5110 *empty = FALSE; | |
5111 | |
5112 DB_RETURN( DB_OK ); | |
5113 | |
5114 } | |
5115 | |
5116 /* | |
5117 +--------------------------------------------------------------------+ | |
5118 | PROJECT: PHB MODULE: DBM | | |
5119 | ROUINE: db_find_free_record | | |
5120 +--------------------------------------------------------------------+ | |
5121 | |
5122 PURPOSE : Find an free record in given (database, field) | |
5123 */ | |
5124 int db_find_free_record ( int db_handle, | |
5125 USHORT field_id ) | |
5126 { | |
5127 UBYTE fld_ctr; | |
5128 T_DB_CODE db_ret_code; | |
5129 | |
5130 int record_num; | |
5131 | |
5132 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
5133 | |
5134 | |
5135 TRACE_FUNCTION("db_find_free_record()"); | |
5136 | |
5137 /* DBM_State check */ | |
5138 DBM_State_check; | |
5139 | |
5140 /* db_handle check */ | |
5141 db_ret_code = db_handle_check( db_handle ); | |
5142 if( db_ret_code NEQ DB_OK ) | |
5143 DB_RETURN( db_ret_code ); | |
5144 | |
5145 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
5146 fld_ctr = field_id_search( db_handle, field_id ); | |
5147 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
5148 DB_RETURN( DB_INVALID_FIELD ); | |
5149 | |
5150 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
5151 | |
5152 /* Using RecordBitMap, search for free record. | |
5153 If found , return the found record_num | |
5154 Return DB_RECORD_NOT_FOUND */ | |
5155 | |
5156 record_num = 1 + search_clear_bit_in_bitmap( tmp_ptrFieldRecord -> RecordBitMap, | |
5157 RECORD_BITMAP_SIZE ); | |
5158 | |
5159 if( record_num > tmp_ptrFieldRecord -> NumOfRecords ) | |
5160 DB_RETURN( DB_RECORD_NOT_FOUND ); | |
5161 | |
5162 DB_VALUE_RETURN( record_num ); | |
5163 | |
5164 } | |
5165 | |
5166 /* | |
5167 +--------------------------------------------------------------------+ | |
5168 | PROJECT: PHB MODULE: DBM | | |
5169 | ROUINE: db_info | | |
5170 +--------------------------------------------------------------------+ | |
5171 | |
5172 PURPOSE : Get information about an open database | |
5173 */ | |
5174 T_DB_CODE db_info ( int db_handle, | |
5175 T_DB_INFO* db_info ) | |
5176 { | |
5177 T_DB_CODE db_ret_code; | |
5178 | |
5179 TRACE_FUNCTION("db_info()"); | |
5180 | |
5181 /* DBM_State check */ | |
5182 DBM_State_check; | |
5183 | |
5184 /* db_handle check */ | |
5185 db_ret_code = db_handle_check( db_handle ); | |
5186 if( db_ret_code NEQ DB_OK ) | |
5187 DB_RETURN( db_ret_code ); | |
5188 | |
5189 (*db_info).clean = ( DbmMaster[db_handle].Tracked_Clean & CLEAN ) ? TRUE : FALSE ; | |
5190 (*db_info).tracked = ( DbmMaster[db_handle].Tracked_Clean & TRACKED ) ? TRUE : FALSE ; | |
5191 | |
5192 DB_RETURN( DB_OK ); | |
5193 } | |
5194 | |
5195 /* | |
5196 +--------------------------------------------------------------------+ | |
5197 | PROJECT: PHB MODULE: DBM | | |
5198 | ROUINE: db_info_field | | |
5199 +--------------------------------------------------------------------+ | |
5200 | |
5201 PURPOSE : Get general information about a field in an open database. | |
5202 */ | |
5203 T_DB_CODE db_info_field ( int db_handle, | |
5204 USHORT field_id, | |
5205 T_DB_INFO_FIELD* info_field ) | |
5206 { | |
5207 UBYTE fld_ctr; | |
5208 T_DB_CODE db_ret_code; | |
5209 | |
5210 T_DBM_FIELDRECORD* tmp_ptrFieldRecord; | |
5211 | |
5212 | |
5213 TRACE_FUNCTION("db_info_field()"); | |
5214 | |
5215 /* DBM_State check */ | |
5216 DBM_State_check; | |
5217 | |
5218 /* db_handle check */ | |
5219 db_ret_code = db_handle_check( db_handle ); | |
5220 if( db_ret_code NEQ DB_OK ) | |
5221 DB_RETURN( db_ret_code ); | |
5222 | |
5223 /* field id search; if field not found, return error DB_INVALID_FIELD */ | |
5224 fld_ctr = field_id_search( db_handle, field_id ); | |
5225 if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles ) | |
5226 DB_RETURN( DB_INVALID_FIELD ); | |
5227 | |
5228 tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr; | |
5229 | |
5230 /* Using data available in RAM in field record, fill up info_field | |
5231 (i.e. clean, db_type, num_of_records and used_records). */ | |
5232 | |
5233 (*info_field).clean = tmp_ptrFieldRecord -> Clean; | |
5234 (*info_field).entry_type = tmp_ptrFieldRecord -> DBType; | |
5235 (*info_field).record_size = tmp_ptrFieldRecord -> RecordSize; | |
5236 (*info_field).num_records = tmp_ptrFieldRecord -> NumOfRecords; | |
5237 (*info_field).used_records = tmp_ptrFieldRecord -> UsedRecords; | |
5238 | |
5239 DB_RETURN( DB_OK ); | |
5240 | |
5241 } | |
5242 | |
5243 /* | |
5244 +--------------------------------------------------------------------+ | |
5245 | PROJECT: PHB MODULE: DBM | | |
5246 | ROUINE: db_get_last_fs_error | | |
5247 +--------------------------------------------------------------------+ | |
5248 | |
5249 PURPOSE : Delivers the last error provided by the (flash) file system | |
5250 that resulted in DB_FAIL_FS. | |
5251 */ | |
5252 int db_get_last_fs_error ( void ) | |
5253 { | |
5254 DB_VALUE_RETURN( LastFFS_ReturnCode ); | |
5255 } | |
5256 | |
5257 #endif /* #ifdef TI_PS_FFS_PHB */ | |
5258 |