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