comparison src/aci2/atb/ATBPb.c @ 3:93999a60b835

src/aci2, src/condat2: import of g23m/condat source pieces from TCS211
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 26 Sep 2016 00:29:36 +0000
parents
children
comparison
equal deleted inserted replaced
2:c41a534f33c6 3:93999a60b835
1 /*******************************************************************************
2
3 CONDAT (UK)
4
5 ********************************************************************************
6
7 This software product is the property of Condat (UK) Ltd and may not be
8 disclosed to any third party without the express permission of the owner.
9
10 ********************************************************************************
11
12 $Project name:
13 $Project code:
14 $Module:
15 $File: ATBPb.c
16 $Revision:
17
18 $Author: Condat(UK)
19 $Date:
20
21 ********************************************************************************
22
23 Description:
24
25
26 ********************************************************************************
27
28 $History: ATBPb.c
29
30 Jan 18, 2004 REF: CRR MMI-SPR-25332 xnkulkar
31 Description: Moving entries from Sim Card to phone memory fails.
32 Solution: When entries are moved, corresponding updations are done in cache as well.
33
34
35 $End
36
37 *******************************************************************************/
38
39 #if defined (NEW_FRAME)
40
41 #include "typedefs.h"
42 #include "vsi.h"
43 #include "pei.h"
44 #include "custom.h"
45 #include "gsm.h"
46
47 #else
48
49 #include "STDDEFS.H"
50 #include "custom.h"
51 #include "gsm.h"
52 #include "vsi.h"
53
54 #endif
55
56 #include <stdio.h>
57 #include <string.h>
58
59 #include "mfw_mfw.h"
60 #include "mfw_sys.h"
61
62 #include "cus_aci.h"
63 #include "prim.h"
64 #include "pcm.h"
65
66 #include "ATBPb.h"
67 #include "ATBPb_i.h"
68
69 /* Global data for phonebook */
70
71 static T_PB_DATA *phonebook[PB_PHONEBOOKS_MAX] = {0};
72
73
74 /*******************************************************************************
75
76 $Function: ATB_pb_GetPhonebook
77
78 $Description: Checks to see which file system is selected
79
80 $Returns: PB_OK Action completed OK.
81 PB_FILEWRITEFAIL File write encountered an error
82
83 $Arguments: phonebook_id The phonebook identifier
84 current_type Place to store type of phonebook selected.
85
86 *******************************************************************************/
87
88 PB_RET ATB_pb_GetPhonebook(SHORT phonebook_id, T_PB_TYPE *current_type)
89 {
90 PB_RET result;
91 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
92
93 tracefunction("ATB_pb_GetPhonebook");
94
95 if (data)
96 {
97 *current_type = data->current_type;
98 return PB_OK;
99 }
100
101 result = FS_pb_GetPhonebook(phonebook_id, current_type);
102
103 return result;
104 }
105
106
107 /*******************************************************************************
108
109 $Function: ATB_pb_SetPhonebook
110
111 $Description: Select file system
112
113 $Returns: PB_OK Action completed OK.
114 PB_FILEREADFAIL File read encountered an error
115
116 $Arguments: phonebook_id The phonebook identifier
117 current_type Type of phonebook selected.
118
119 *******************************************************************************/
120
121 PB_RET ATB_pb_SetPhonebook(SHORT phonebook_id, T_PB_TYPE current_type)
122 {
123 PB_RET result;
124 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
125
126 tracefunction("ATB_pb_SetPhonebook");
127
128 if (data)
129 data->current_type = current_type;
130
131 result = FS_pb_SetPhonebook(phonebook_id, current_type);
132
133 return result;
134 }
135
136
137 /*******************************************************************************
138
139 $Function: ATB_pb_Initialise
140
141 $Description: Initialise an instance of phonebook. Dynamically allocates a record
142 cache in RAM. Creates the necessary file(s) if they do not already exist.
143 Sorts the phonebook by name and by number, creating the appropriate
144 index tables.
145 IMPORTANT: if the file reading is non-blocking - i.e. if a request to read
146 a file does not return with an answer straight away, but the system
147 awaits a callback - then "cache_max" must equal "records_max". This
148 ensures that all records are stored in RAM and can be retrieved without
149 waiting for a response. If the file reading is blocking, then cache_max
150 can be smaller than records_max.
151
152 The memory allocated by this operation will not be freed until
153 ATB_pb_Exit() is called.
154
155 $Returns: PB_OK Action completed OK.
156 PB_EXCT Action currently executing, callback awaited.
157 GI_pb_OK will be called if successful,
158 GI_pb_Error otherwise.
159 PB_BUSY Failed, phonebook is busy.
160 PB_FILEREADFAIL File read encountered an error
161 PB_FILEWRITEFAIL File write encountered an error
162 PB_BOOKALREADYEXISTS Tried to initialise a phonebook that already
163 exists
164
165 $Arguments: phonebook_id The phonebook identifier
166 type Type of phonebook.
167 records_max Indicates the maximum number of entries the
168 phonebook can hold.
169 cache_max Indicates the maximum number of records that the
170 PB will store concurrently in RAM.
171 alpha_max Maximum size of unicode alpha tag in characters
172 number_max Maximum size of phone number in digits
173 ext_max Maximum size of extended data in bytes
174
175 *******************************************************************************/
176
177 PB_RET ATB_pb_Initialise(SHORT phonebook_id, T_PB_TYPE type, SHORT records_max, SHORT cache_max,
178 SHORT alpha_max, SHORT number_max, SHORT ext_max)
179 {
180 T_PB_DATA *data;
181
182 tracefunction("ATB_pb_Initialise()");
183
184 /* Check to see if this phonebook has already been allocated */
185
186 if (ATB_hnd_GetPbData(phonebook_id)!=NULL)
187 {
188 trace("* ERROR * - Phonebook already exists");
189 GI_pb_Error(phonebook_id, PB_INITIALISE, PB_BOOKALREADYEXISTS);
190 return PB_BOOKALREADYEXISTS;
191 }
192
193 /* Allocate memory for phonebook data */
194
195 data = (T_PB_DATA *)GI_pb_MemAlloc(sizeof(T_PB_DATA));
196 ATB_hnd_SetPbData(phonebook_id, data);
197
198 data->records_max = records_max;
199 data->records_used = 0;
200 data->search_results = 0;
201
202 data->alpha_max = alpha_max;
203 data->number_max = number_max;
204 data->ext_max = ext_max;
205
206 /* Allocate memory for index tables */
207
208 data->name_table = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT));
209 memset(data->name_table, 0, records_max*sizeof(SHORT));
210 data->number_table = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT));
211 memset(data->number_table, 0, records_max*sizeof(SHORT));
212 data->search_table = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT));
213 memset(data->search_table, 0, records_max*sizeof(SHORT));
214 data->in_memory = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT));
215 memset(data->in_memory, PB_EMPTY_RECORD, records_max*sizeof(SHORT));
216
217 /* Allocate memory for cache */
218
219 data->cache_max = cache_max;
220 data->cache_size = 0;
221 data->cache = (T_PB_RECORD **)GI_pb_MemAlloc(records_max*sizeof(T_PB_RECORD *));
222 memset(data->cache, 0, records_max*sizeof(T_PB_RECORD *));
223
224 /* Set up command */
225
226 data->command_id = PB_INITIALISE;
227 data->status = PB_STATUS_INIT;
228 data->param.Initialise.type = type;
229 data->param.Initialise.records_max = records_max;
230
231 return ATB_status_Initialise(phonebook_id);
232 }
233
234 /* Status function for Initialise */
235
236 PB_RET ATB_status_Initialise(SHORT phonebook_id)
237 {
238 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
239 T_PB_INITIALISE *Initialise;
240 SHORT blocking;
241 PB_RET result;
242
243 /* Ensure that phonebook exists */
244 if (!data)
245 {
246 trace("**ERROR** Phonebook does not exist");
247 return PB_BOOKDOESNOTEXIST;
248 }
249
250 Initialise = &data->param.Initialise;
251 blocking = TRUE;
252 while (blocking)
253 {
254 switch(data->status)
255 {
256 case PB_STATUS_INIT:
257 trace("ATB_status_Initialise: INIT");
258 result = FS_pb_Initialise(phonebook_id, Initialise->type, Initialise->records_max,
259 data->alpha_max, data->number_max, data->ext_max);
260
261 /* Select next state */
262
263 data->status = PB_STATUS_EXEC;
264 Initialise->phys_index = 0;
265 Initialise->first_record = TRUE;
266 Initialise->record = ATB_pb_AllocRec(phonebook_id);
267
268 /* Allow exit from function */
269
270 if (result!=PB_OK)
271 blocking = FALSE;
272 break;
273
274 case PB_STATUS_EXEC:
275 trace("ATB_status_Initialise: EXEC");
276
277 /* Try to read in index tables from file system. If we can't find them, the
278 * records will be read in and sorted. */
279
280 if (Initialise->first_record)
281 {
282 result = FS_pb_ReadTables(phonebook_id, &data->records_used, data->name_table, data->number_table);
283 if (result==PB_OK)
284 {
285 /* Escape to PB_STATUS_COMPLETE */
286 result = PB_OK;
287 data->status = PB_STATUS_COMPLETE;
288 break;
289 }
290 }
291 /* If we've already read a record, and it's an existing record, add it to the
292 * index tables and to the cache */
293
294 else
295 {
296 if (Initialise->record->alpha.data[0]!=(USHORT)0xFFFF)
297 {
298 ATB_mem_UpdateCache(phonebook_id, Initialise->phys_index, Initialise->record);
299 ATB_index_AddRec(phonebook_id, INDEX_NAME, Initialise->phys_index, Initialise->record, NULL);
300 ATB_index_AddRec(phonebook_id, INDEX_NUMBER, Initialise->phys_index, Initialise->record, NULL);
301 data->records_used++;
302 }
303
304 Initialise->phys_index++;
305 }
306
307 /* Start processing after first record is read */
308
309 Initialise->first_record = FALSE;
310
311 /* If we haven't just read the last record, read the next one */
312
313 if (Initialise->phys_index<data->records_max)
314 {
315 result = FS_pb_ReadRec(phonebook_id, Initialise->phys_index, Initialise->record);
316 }
317 else
318 {
319 /* Set next state as finished */
320 result = PB_OK;
321 data->status = PB_STATUS_COMPLETE;
322 }
323
324
325 /* Allow exit from function */
326
327 if (result!=PB_OK)
328 blocking = FALSE;
329 break;
330
331 case PB_STATUS_COMPLETE:
332 trace("ATB_status_Initialise: COMPLETE");
333 blocking = FALSE;
334
335 /* Close file */
336
337 FS_pb_Finished(phonebook_id);
338 FS_pb_WriteTables(phonebook_id, data->records_used, data->name_table, data->number_table);
339
340 /* Free the allocated record */
341
342 ATB_pb_FreeRec(phonebook_id, Initialise->record);
343
344 /* Notify the GI of success */
345 GI_pb_OK(phonebook_id, data->command_id, NULL);
346 result = PB_OK;
347 data->status = PB_STATUS_NONE;
348 break;
349 }
350 }
351
352 return result;
353 }
354
355
356 /*******************************************************************************
357
358 $Function: ATB_pb_Exit
359
360 $Description: Frees memory associated with phonebook. To be called when the
361 phonebook is no longer required, or at shutdown.
362
363 $Returns: PB_OK Action completed OK.
364
365 $Arguments: phonebook_id The phonebook identifier
366
367 *******************************************************************************/
368
369 PB_RET ATB_pb_Exit(SHORT phonebook_id)
370 {
371 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
372 SHORT phys_index;
373
374 trace("ATB_pb_Exit");
375
376 /* Ensure that phonebook exists */
377 if (!data)
378 {
379 trace("**ERROR** Phonebook does not exist");
380 return PB_BOOKDOESNOTEXIST;
381 }
382
383 for (phys_index = 0; phys_index<data->records_max; phys_index++)
384 {
385 if (data->cache[phys_index]!=NULL)
386 ATB_pb_FreeRec(phonebook_id, data->cache[phys_index]);
387 }
388
389 GI_pb_MemFree((UBYTE *)data->cache, data->records_max*sizeof(T_PB_RECORD *));
390 GI_pb_MemFree((UBYTE *)data->in_memory, data->records_max*sizeof(SHORT));
391 GI_pb_MemFree((UBYTE *)data->search_table, data->records_max*sizeof(SHORT));
392 GI_pb_MemFree((UBYTE *)data->number_table, data->records_max*sizeof(SHORT));
393 GI_pb_MemFree((UBYTE *)data->name_table, data->records_max*sizeof(SHORT));
394
395 GI_pb_MemFree((UBYTE *)data, sizeof(T_PB_DATA));
396
397 ATB_hnd_SetPbData(phonebook_id, NULL);
398 return PB_OK;
399 }
400
401
402 /*******************************************************************************
403
404 $Function: ATB_pb_Status
405
406 $Description: Returns PB_OK if the phonebook is ready for a new command,
407 or PB_BUSY if the phonebook is busy.
408
409 $Returns: PB_OK All tasks completed, phonebook ready.
410 PB_BUSY Commands currently executing.
411
412 $Arguments: phonebook_id The phonebook identifier
413
414 *******************************************************************************/
415
416 PB_RET ATB_pb_Status(SHORT phonebook_id)
417 {
418 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
419 PB_RET result;
420
421 /* Ensure that phonebook exists */
422 if (!data)
423 {
424 trace("**ERROR** Phonebook does not exist");
425 return PB_BOOKDOESNOTEXIST;
426 }
427
428 // Jan 18, 2004 REF: CRR MMI-SPR-25332 xnkulkar
429 // Description: Moving entries from Sim Card to phone memory fails.
430 // Solution: result should be set as PB_OK when PB_STATUS_COMPLETE is true also.
431 if ((data->status==PB_STATUS_NONE) ||(data->status==PB_STATUS_COMPLETE))
432 result = PB_OK;
433 else
434 result = PB_BUSY;
435
436 return result;
437 }
438
439
440 /*******************************************************************************
441
442 $Function: ATB_pb_Info
443
444 $Description: Returns information about the phonebook, which will be returned
445 in the data structure pointed to by phonebook_info. The caller must
446 allocate the T_PB_INFO structure.
447
448 $Returns: PB_OK Action completed OK.
449
450 $Arguments: phonebook_id The phonebook identifier
451 phonebook_info Pointer to data structure to contain phonebook
452 information (allocated by caller).
453
454 *******************************************************************************/
455
456 PB_RET ATB_pb_Info(SHORT phonebook_id, T_PB_INFO *phonebook_info)
457 {
458 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
459
460 /* Ensure that phonebook exists */
461 if (!data)
462 {
463 trace("**ERROR** Phonebook does not exist");
464 return PB_BOOKDOESNOTEXIST;
465 }
466
467 phonebook_info->records_used = data->records_used;
468 phonebook_info->records_max = data->records_max;
469 phonebook_info->records_free = data->records_max - data->records_used;
470 phonebook_info->search_results = data->search_results;
471
472 return PB_OK;
473 }
474
475
476 /*******************************************************************************
477
478 $Function: ATB_pb_ReadRec
479
480 $Description: Reads a record from the logical position index. The record information
481 will be returned in the data structure pointed to by record. The
482 T_PB_RECORD structure must be allocated by the user.
483
484 This function calls the ATB_mem_ReadRec function, with an additional
485 check to make sure no other commands are currently executing.
486
487 $Returns: PB_OK Action completed OK.
488 PB_BUSY Failed, phonebook is busy.
489 PB_FILEREADFAIL File read encountered an error
490 PB_RECDOESNOTEXIST Tried to access a record that does not exist
491
492 $Arguments: phonebook_id The phonebook identifier
493 index_type The index list from which the record is to be read
494 log_index Logical index in the index list of the record to read
495 record Structure in which to store record data
496
497 *******************************************************************************/
498
499 PB_RET ATB_pb_ReadRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index, T_PB_RECORD *record)
500 {
501 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
502 PB_RET result;
503
504 tracefunction("ATB_pb_ReadRec");
505
506 /* Ensure that phonebook exists */
507 if (!data)
508 {
509 trace("**ERROR** Phonebook does not exist");
510 return PB_BOOKDOESNOTEXIST;
511 }
512
513 /* Make sure phonebook is not busy */
514
515 if (ATB_pb_Status(phonebook_id)==PB_BUSY)
516 {
517 trace("* ERROR * - Phonebook is busy");
518 result = PB_BUSY;
519 }
520 else
521 {
522 /* Read the record from cache or from file */
523
524 result = ATB_mem_ReadRec(phonebook_id, index_type, log_index, record);
525 }
526
527 /* Send success/failure info to the GI */
528
529 if (result==PB_OK)
530 GI_pb_OK(phonebook_id, PB_READREC, NULL);
531 else if (result!=PB_EXCT)
532 GI_pb_Error(phonebook_id, PB_READREC, result);
533
534 /* Close any open file */
535
536 FS_pb_Finished(phonebook_id);
537
538 return result;
539 }
540
541
542 /*******************************************************************************
543
544 $Function: ATB_pb_WriteRec
545
546 $Description: Writes a record to the logical position index. If the index is
547 PB_NEW_RECORD, a new record is added, otherwise the previous
548 record at that position is overwritten. The name and number index lists
549 will be updated with the new entry in the appropriate place in each.
550 GI_pb_OK will be called to confirm that the write completed successfully,
551 otherwise GI_pb_Error will be called with an error code.
552 Since the order of the records may change due to sorting, GI_pb_OK
553 will receive a pointer to an integer new_log_index, which will store the
554 new position of the record in the chosen index list. This is allocated
555 by and will be destroyed by the phonebook, so must be copied by the
556 GI before function return.
557
558 $Returns: PB_OK Action completed OK.
559 PB_EXCT Action currently executing, callback awaited.
560 GI_pb_OK will be called if successful,
561 GI_pb_Error otherwise.
562 GI_pb_OK will receive a pointer to the following:
563 SHORT new_log_index - The new position of the
564 record in the chosen index list
565 PB_BUSY Failed, phonebook is busy.
566 PB_FILEWRITEFAIL File write encountered an error
567 PB_RECDOESNOTEXIST (Overwriting only) Tried to access a record that
568 does not exist
569
570 $Arguments: phonebook_id The phonebook identifier
571 index_type The index list of the record to write
572 log_index Logical index in the index list of the record to write
573 record Pointer to record data to write to phonebook
574 (allocated by caller)
575
576 *******************************************************************************/
577
578 PB_RET ATB_pb_WriteRec(SHORT phonebook_id, T_PB_TYPE index_type, SHORT log_index, T_PB_RECORD *record)
579 {
580 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
581 SHORT phys_index;
582
583 tracefunction("ATB_pb_WriteRec");
584
585 /* Ensure that phonebook exists */
586 if (!data)
587 {
588 trace("**ERROR** Phonebook does not exist");
589 return PB_BOOKDOESNOTEXIST;
590 }
591
592 /* Make sure phonebook is not busy */
593
594 if (ATB_pb_Status(phonebook_id)==PB_BUSY)
595 {
596 trace("* ERROR * - Phonebook is busy");
597 GI_pb_Error(phonebook_id, PB_WRITEREC, PB_BUSY);
598 return PB_BUSY;
599 }
600
601 /* Are we adding a new record, or overwriting an old one? */
602
603 if (log_index==PB_NEW_RECORD)
604 {
605 /* Is phonebook full? */
606
607 if (data->records_used==data->records_max)
608 {
609 GI_pb_Error(phonebook_id, PB_WRITEREC, PB_BOOKFULL);
610 return PB_BOOKFULL;
611 }
612
613 /* Find an empty physical record */
614 for (phys_index=0; phys_index<data->records_max; phys_index++)
615 {
616 if (data->in_memory[phys_index]==PB_EMPTY_RECORD)
617 break;
618 }
619 }
620 else
621 {
622 /* Check that record exists */
623
624 if (log_index<0
625 || (log_index>=data->records_used && (index_type==INDEX_NAME || index_type==INDEX_NUMBER))
626 || (index_type==INDEX_SEARCH && log_index>data->search_results)
627 || (index_type==INDEX_PHYSICAL && log_index>data->records_max))
628 {
629 GI_pb_Error(phonebook_id, PB_WRITEREC, PB_RECDOESNOTEXIST);
630 return PB_RECDOESNOTEXIST;
631 }
632
633 phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index);
634 }
635
636 /* Set up command */
637
638 data->command_id = PB_WRITEREC;
639 data->status = PB_STATUS_INIT;
640
641 data->param.WriteRec.log_index = log_index;
642 data->param.WriteRec.index_type = index_type;
643 data->param.WriteRec.phys_index = phys_index;
644 data->param.WriteRec.record = record;
645
646 return ATB_status_WriteRec(phonebook_id);
647 }
648
649 /* Status function for WriteRec */
650
651 PB_RET ATB_status_WriteRec(SHORT phonebook_id)
652 {
653 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
654 T_PB_WRITEREC *WriteRec = &data->param.WriteRec;
655 SHORT blocking;
656 PB_RET result;
657 SHORT name_log_index;
658 SHORT number_log_index;
659 SHORT *log_index_return;
660
661 blocking = TRUE;
662 while (blocking)
663 {
664 switch(data->status)
665 {
666 case PB_STATUS_INIT:
667 result = FS_pb_WriteRec(phonebook_id, WriteRec->phys_index, WriteRec->record);
668
669 /* Select next state */
670
671 data->status = PB_STATUS_COMPLETE;
672
673 /* Allow exit from function */
674
675 if (result!=PB_OK)
676 blocking = FALSE;
677 break;
678
679 case PB_STATUS_COMPLETE:
680
681 if (WriteRec->log_index!=PB_NEW_RECORD)
682 {
683 name_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NAME, WriteRec->phys_index);
684 ATB_index_RemoveRec(phonebook_id, INDEX_NAME, name_log_index);
685 number_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NUMBER, WriteRec->phys_index);
686 ATB_index_RemoveRec(phonebook_id, INDEX_NUMBER, number_log_index);
687 data->records_used--;
688 }
689
690 /* Indicate that record is new, then add to the cache */
691
692 data->in_memory[WriteRec->phys_index] = 0;
693 ATB_mem_UpdateCache(phonebook_id, WriteRec->phys_index, WriteRec->record);
694
695 /* Add the record to the index lists */
696
697 ATB_index_AddRec(phonebook_id, INDEX_NAME, WriteRec->phys_index, WriteRec->record, &name_log_index);
698 ATB_index_AddRec(phonebook_id, INDEX_NUMBER, WriteRec->phys_index, WriteRec->record, &number_log_index);
699 data->records_used++;
700
701 blocking = FALSE;
702
703 /* Close any open file */
704
705 FS_pb_Finished(phonebook_id);
706 FS_pb_WriteTables(phonebook_id, data->records_used, data->name_table, data->number_table);
707
708 /* Notify the GI of success */
709 log_index_return = NULL;
710 if (WriteRec->index_type==INDEX_NAME)
711 log_index_return = &name_log_index;
712 if (WriteRec->index_type==INDEX_NUMBER)
713 log_index_return = &number_log_index;
714
715 GI_pb_OK(phonebook_id, data->command_id, log_index_return);
716 result = PB_OK;
717 data->status = PB_STATUS_NONE;
718 break;
719 }
720 }
721
722 /* Report any errors to the GI */
723
724 if (result!=PB_OK && result!=PB_EXCT)
725 {
726 GI_pb_Error(phonebook_id, PB_WRITEREC, result);
727 }
728
729 return result;
730 }
731
732
733 /*******************************************************************************
734
735 $Function: ATB_pb_DeleteRec
736
737 $Description: Deletes a record at a logical position index.
738 GI_pb_OK will be called to confirm that the delete completed successfully,
739 otherwise GI_pb_Error will be called with an error code.
740
741 $Returns: PB_OK Action completed OK.
742 PB_EXCT Action currently executing, callback awaited.
743 GI_pb_OK will be called if successful,
744 GI_pb_Error otherwise.
745 PB_BUSY Failed, phonebook is busy.
746 PB_FILEWRITEFAIL File write encountered an error
747 PB_RECDOESNOTEXIST Tried to access a record that does not exist
748
749 $Arguments: phonebook_id The phonebook identifier
750 index_type The index list of the record to delete
751 log_index Logical index in the index list of the record to delete
752
753 *******************************************************************************/
754
755 PB_RET ATB_pb_DeleteRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index)
756 {
757 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
758
759 tracefunction("ATB_pb_DeleteRec");
760
761 /* Ensure that phonebook exists */
762 if (!data)
763 {
764 trace("**ERROR** Phonebook does not exist");
765 return PB_BOOKDOESNOTEXIST;
766 }
767
768 /* Make sure phonebook is not busy */
769
770 if (ATB_pb_Status(phonebook_id)==PB_BUSY)
771 {
772 trace("* ERROR * - Phonebook is busy");
773 GI_pb_Error(phonebook_id, PB_DELETEREC, PB_BUSY);
774 return PB_BUSY;
775 }
776
777 /* Check that record exists */
778
779 if (log_index<0
780 || (log_index>=data->records_used && (index_type==INDEX_NAME || index_type==INDEX_NUMBER))
781 || (index_type==INDEX_SEARCH && log_index>data->search_results)
782 || (index_type==INDEX_PHYSICAL && log_index>data->records_max))
783 {
784 GI_pb_Error(phonebook_id, PB_DELETEREC, PB_RECDOESNOTEXIST);
785 return PB_RECDOESNOTEXIST;
786 }
787
788 /* Set up the command */
789
790 data->command_id = PB_DELETEREC;
791 data->status = PB_STATUS_INIT;
792
793 data->param.DeleteRec.log_index = log_index;
794 data->param.DeleteRec.index_type = index_type;
795 data->param.DeleteRec.phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index);
796
797 return ATB_status_DeleteRec(phonebook_id);
798 }
799
800 /* Status function for DeleteRec */
801
802 PB_RET ATB_status_DeleteRec(SHORT phonebook_id)
803 {
804 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
805 T_PB_DELETEREC *DeleteRec = &data->param.DeleteRec;
806 SHORT blocking;
807 PB_RET result;
808 SHORT name_log_index;
809 SHORT number_log_index;
810
811 blocking = TRUE;
812 while (blocking)
813 {
814 switch(data->status)
815 {
816 case PB_STATUS_INIT:
817 result = FS_pb_DeleteRec(phonebook_id, DeleteRec->phys_index);
818
819 /* Select next state */
820
821 data->status = PB_STATUS_COMPLETE;
822
823 /* Allow exit from function */
824
825 if (result!=PB_OK)
826 blocking = FALSE;
827 break;
828
829 case PB_STATUS_COMPLETE:
830 name_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NAME, DeleteRec->phys_index);
831 ATB_index_RemoveRec(phonebook_id, INDEX_NAME, name_log_index);
832 number_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NUMBER, DeleteRec->phys_index);
833 ATB_index_RemoveRec(phonebook_id, INDEX_NUMBER, number_log_index);
834 data->records_used--;
835 data->in_memory[DeleteRec->phys_index] = -1;
836
837 // Jan 18, 2004 REF: CRR MMI-SPR-25332 xnkulkar
838 // Description: Moving entries from Sim Card to phone memory fails.
839 // Solution: When entries are moved, corresponding updations are done in cache as well.
840 if(data->cache[DeleteRec->phys_index]!=NULL)
841 {
842 ATB_pb_FreeRec(phonebook_id, data->cache[DeleteRec->phys_index]);
843 data->cache[DeleteRec->phys_index]=NULL;
844 data->cache_size--;
845 }
846
847 /* Close any open file */
848
849 FS_pb_Finished(phonebook_id);
850 FS_pb_WriteTables(phonebook_id, data->records_used, data->name_table, data->number_table);
851
852 blocking = FALSE;
853
854 /* Notify the GI of success */
855
856 GI_pb_OK(phonebook_id, data->command_id, NULL);
857 result = PB_OK;
858 data->status = PB_STATUS_NONE;
859 break;
860 }
861 }
862
863 /* Report any errors to the GI */
864
865 if (result!=PB_OK && result!=PB_EXCT)
866 {
867 GI_pb_Error(phonebook_id, PB_DELETEREC, result);
868 }
869
870 return result;
871 }
872
873
874 /*******************************************************************************
875
876 $Function: ATB_pb_Find
877
878 $Description: Find the nearest match to the supplied record. Only the index_type
879 specified will be considered: if the index_type is INDEX_NAME, then the
880 name only will be matched; if INDEX_NUMBER, then just the number.
881 The new_log_index parameter should be a pointer to a user allocated
882 integer. This will return the logical index of the closest match in the
883 index list specified. This index either corresponds to a perfect match,
884 or to the record that would appear just after the provided record in the
885 list. For example, if the list consisted of record 0, Alice and record 1,
886 Carol, then a search for Bob would return 1. A search for a record
887 that would occur before the first record always returns 0. A search for
888 a record that would occur after the last record returns the index of the
889 last record +1.
890 The "match" parameter should be a pointer to a user allocated variable
891 of type T_PB_MATCH. This returns information about how closely the
892 found entry matches the record. In the example above, a search for
893 Bob would return 1 and MATCH_NONE; a search for Ca would return 1
894 and MATCH_START, and a search for Carol would return 1 and
895 MATCH_EXACT. Rarely, match may be MATCH_FRAGMENT: this can be
896 considered equivalent to MATCH_NONE in this context.
897
898 $Returns: PB_OK Action completed OK.
899 PB_BUSY Failed, phonebook is busy.
900 PB_FILEREADFAIL File read encountered an error
901 PB_RECDOESNOTEXIST Tried to access a record that does not exist
902 (should never happen)
903
904 $Arguments: phonebook_id The phonebook identifier
905 index_type The index_type of the provided record that is to be
906 searched for, and the index list that the resulting
907 new_log_index pertains to
908 record The record whose index_type is to be matched
909 new_log_index Returns with the logical index of the closest matching
910 record
911 match Specifies how good the resulting match was
912 (MATCH_NONE, MATCH_START, MATCH_FRAGMENT
913 or MATCH_EXACT).
914
915 *******************************************************************************/
916
917
918 PB_RET ATB_pb_Find (SHORT phonebook_id, T_PB_INDEX index_type, T_PB_RECORD *record, SHORT *new_log_index, T_PB_MATCH *match)
919 {
920 PB_RET result;
921
922 tracefunction("ATB_pb_Find");
923
924 result = ATB_index_Find(phonebook_id, index_type, record, new_log_index, match);
925
926 /* Close any open file */
927
928 FS_pb_Finished(phonebook_id);
929
930 /* Send success/failure info to the GI */
931
932 if (result==PB_OK)
933 GI_pb_OK(phonebook_id, PB_FIND, NULL);
934 else if (result!=PB_EXCT)
935 GI_pb_Error(phonebook_id, PB_FIND, result);
936
937 return result;
938 }
939
940
941 /*******************************************************************************
942
943 $Function: ATB_pb_ReadRecList
944
945 $Description: Fetches record information of sequential records in an index list, starting
946 at logical record start_log_index and fetching recs_count records in total.
947 The information will be stored in the caller allocated array of records
948 provided.
949
950 $Returns: PB_OK Action completed OK.
951 PB_BUSY Failed, phonebook is busy.
952 PB_FILEREADFAIL File read encountered an error
953 PB_RECDOESNOTEXIST Tried to access a record that does not exist
954
955 $Arguments: phonebook_id The phonebook identifier
956 index_type The index list to use
957 start_log_index Logical index in the index list of the first record to
958 read
959 recs_count Total number of sequential records to read.
960 record Array of entries in which to store the fetched records.
961 The array must be recs_count in size. (Caller allocated).
962
963 *******************************************************************************/
964
965 PB_RET ATB_pb_ReadRecList(SHORT phonebook_id, T_PB_INDEX index_type, SHORT start_log_index, SHORT num_recs, T_PB_LIST *list)
966 {
967 PB_RET result;
968 SHORT log_index;
969
970 tracefunction("ATB_pb_ReadRecList");
971
972 list->records_used = 0;
973
974 /* Make sure phonebook is not busy */
975
976 if (ATB_pb_Status(phonebook_id)==PB_BUSY)
977 {
978 trace("* ERROR * - Phonebook is busy");
979 /* Report any errors to the GI */
980 GI_pb_Error(phonebook_id, PB_READRECLIST, PB_BUSY);
981 return PB_BUSY;
982 }
983
984 /* Read in list of records */
985
986 for (log_index = start_log_index; log_index<start_log_index+num_recs && log_index<list->records_max; log_index++)
987 {
988 result = ATB_mem_ReadRec(phonebook_id, index_type, log_index, &list->record[log_index-start_log_index]);
989 if (result!=PB_OK)
990 break;
991 list->records_used++;
992 }
993
994 /* Close any open file */
995
996 FS_pb_Finished(phonebook_id);
997
998 /* Send success/failure info to the GI */
999
1000 if (result==PB_OK)
1001 GI_pb_OK(phonebook_id, PB_READRECLIST, NULL);
1002 else if (result!=PB_EXCT)
1003 GI_pb_Error(phonebook_id, PB_READRECLIST, result);
1004
1005 return result;
1006 }
1007
1008
1009 /*******************************************************************************
1010
1011 $Function: ATB_pb_Search
1012
1013 $Description: Searches every record in the index list for a fragment. The index list
1014 must be either INDEX_NAME or INDEX_NUMBER. If it is INDEX_NAME,
1015 then a name fragment will be searched for; if it is INDEX_NUMBER,
1016 a number fragment will be searched for.
1017
1018 The results are stored in an index list. They may be accessed by
1019 using the normal read and write functions, using the index type
1020 INDEX_SEARCH. The size of the search list is returned in the variable
1021 recs_count.
1022
1023 $Returns: PB_OK Action completed OK.
1024 PB_BUSY Failed, phonebook is busy.
1025 PB_FILEREADFAIL File read encountered an error
1026 PB_RECDOESNOTEXIST Tried to access a record that does not exist
1027 (should never happen)
1028
1029 $Arguments: phonebook_id The phonebook identifier
1030 index_type The index list to use
1031 record Record containing the fragment to search for
1032 recs_count Pointer to an int (user allocated) in which will be returned
1033 the number of search results.
1034
1035
1036 *******************************************************************************/
1037
1038 PB_RET ATB_pb_Search(SHORT phonebook_id, T_PB_INDEX index_type, T_PB_RECORD *record, SHORT *recs_count)
1039 {
1040 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1041 PB_RET result;
1042 SHORT count = 0;
1043 SHORT log_index;
1044 T_PB_MATCH match;
1045 T_PB_RECORD *cur_record;
1046
1047 /* Ensure that phonebook exists */
1048 if (!data)
1049 {
1050 trace("**ERROR** Phonebook does not exist");
1051 return PB_BOOKDOESNOTEXIST;
1052 }
1053
1054 /* Allocate record for temporary use */
1055
1056 cur_record = ATB_pb_AllocRec(phonebook_id);
1057
1058 /* Make sure phonebook is not busy */
1059
1060 if (ATB_pb_Status(phonebook_id)==PB_BUSY)
1061 {
1062 trace("* ERROR * - Phonebook is busy");
1063 GI_pb_Error(phonebook_id, PB_SEARCH, PB_BUSY);
1064 return PB_BUSY;
1065 }
1066
1067 /* Make sure we're searching a valid index type */
1068
1069 if (index_type==INDEX_PHYSICAL || index_type==INDEX_SEARCH)
1070 {
1071 GI_pb_Error(phonebook_id, PB_SEARCH, PB_INDEXINVALID);
1072 return PB_INDEXINVALID;
1073 }
1074
1075 for (log_index=0; log_index<data->records_used; log_index++)
1076 {
1077 result = ATB_mem_ReadRec(phonebook_id, index_type, log_index, cur_record);
1078 if (result!=PB_OK)
1079 break;
1080
1081 match = ATB_index_Match(record, cur_record, index_type);
1082
1083 if (match==MATCH_EXACT || match==MATCH_START || match==MATCH_FRAGMENT)
1084 {
1085 data->search_table[count] = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index);
1086 count++;
1087 }
1088 }
1089
1090 data->search_results = count;
1091 *recs_count = count;
1092
1093 /* Free allocated record */
1094
1095 ATB_pb_FreeRec(phonebook_id, cur_record);
1096
1097 /* Close any open file */
1098
1099 FS_pb_Finished(phonebook_id);
1100
1101 /* Send success/failure info to the GI */
1102
1103 if (result==PB_OK)
1104 GI_pb_OK(phonebook_id, PB_SEARCH, NULL);
1105 else if (result!=PB_EXCT)
1106 GI_pb_Error(phonebook_id, PB_SEARCH, result);
1107
1108 return result;
1109 }
1110
1111
1112 /*******************************************************************************
1113
1114 $Function: ATB_pb_ConvIndex
1115
1116 $Description: Returns the index in table dest_index_type corresponding to the index
1117 in table src_index_type.
1118
1119 $Returns: PB_OK Action completed OK.
1120
1121 $Arguments: phonebook_id The phonebook identifier.
1122 index_type The index table of the original index.
1123 log_index The original logical index.
1124 new_index_type The index table required.
1125 new_log_index Pointer to where the new logical index will be stored
1126
1127 *******************************************************************************/
1128
1129 PB_RET ATB_pb_ConvIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index,
1130 T_PB_INDEX new_index_type, SHORT *new_log_index)
1131 {
1132 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1133 SHORT phys_index;
1134
1135 /* Ensure that phonebook exists */
1136 if (!data)
1137 {
1138 trace("**ERROR** Phonebook does not exist");
1139 return PB_BOOKDOESNOTEXIST;
1140 }
1141
1142 if (index_type==new_index_type)
1143 {
1144 *new_log_index = log_index;
1145 }
1146 else
1147 {
1148 phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index);
1149 *new_log_index = ATB_index_GetLogIndex(phonebook_id, new_index_type, phys_index);
1150 }
1151
1152 return PB_OK;
1153 }
1154
1155
1156 /*******************************************************************************
1157
1158 $Function: ATB_pb_CharToBCD
1159
1160 $Description: Converts an ascii string of digits into BCD form, with 4 bits representing
1161 each digit.
1162
1163 $Returns: None
1164
1165 $Arguments: src - source string (ascii)
1166 dest - destination string for BCD digits
1167
1168 *******************************************************************************/
1169
1170 void ATB_pb_CharToBCD(UBYTE *dest, char *src, int max_len)
1171 {
1172 UBYTE srcIndex = 0;
1173 UBYTE destIndex = 0;
1174 BOOL leftbits = TRUE; /* Left or right nibble */
1175 UBYTE digit = 0;
1176
1177 while (digit!=0xF && srcIndex<max_len)
1178 {
1179 if (src[srcIndex]==NULL)
1180 digit = 0xF; /* 0xF terminates BCD */
1181 else
1182 digit = src[srcIndex]-'0'; /* The digit, 0 to 9. */
1183
1184 if (leftbits)
1185 {
1186 dest[destIndex] = digit;
1187 leftbits = FALSE;
1188 }
1189 else
1190 {
1191 dest[destIndex] |= digit<<4; /* *16 shifts right 4 bits */
1192 leftbits = TRUE;
1193 destIndex++;
1194 }
1195 srcIndex++;
1196 }
1197
1198 return;
1199 }
1200
1201
1202 /*******************************************************************************
1203
1204 $Function: ATB_pb_BCDToChar
1205
1206 $Description: Converts a BCD string to ascii digits
1207
1208 $Returns: None
1209
1210 $Arguments: src - source string (BCD)
1211 dest - destination string for ascii digits
1212
1213 *******************************************************************************/
1214
1215 void ATB_pb_BCDToChar(char *dest, UBYTE *src, int max_len)
1216 {
1217 SHORT numIndex = 0;
1218 UBYTE digit = 0xF; //dummy
1219
1220 while (digit!=NULL && numIndex<max_len)
1221 {
1222 /*HELLO!*/
1223 digit = ATB_num_Digit(src, numIndex);
1224
1225 if (digit==0xF)
1226 digit = NULL;
1227 else
1228 digit+='0';
1229 dest[numIndex] = digit;
1230
1231 numIndex++;
1232 }
1233
1234 return;
1235 }
1236
1237
1238 /*******************************************************************************
1239
1240 $Function: ATB_pb_AllocRec
1241
1242 $Description: Allocates memory for a record
1243
1244 $Returns:
1245
1246 $Arguments: phonebook_id The phonebook identifier
1247
1248 *******************************************************************************/
1249
1250 T_PB_RECORD *ATB_pb_AllocRec(SHORT phonebook_id)
1251 {
1252 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1253 T_PB_RECORD *record;
1254
1255 record = (T_PB_RECORD *)GI_pb_MemAlloc(sizeof(T_PB_RECORD));
1256
1257 record->alpha.data = (USHORT *)GI_pb_MemAlloc(data->alpha_max*sizeof(USHORT));
1258 record->number = (UBYTE *)GI_pb_MemAlloc(data->number_max/2);
1259 if (data->ext_max>0)
1260 {
1261 record->ext_data = (UBYTE *)GI_pb_MemAlloc(data->ext_max);
1262 }
1263 else
1264 {
1265 record->ext_data = NULL;
1266 }
1267 record->ton_npi = 0;
1268
1269 return record;
1270 }
1271
1272
1273 /*******************************************************************************
1274
1275 $Function: ATB_pb_FreeRec
1276
1277 $Description: Frees memory allocated for a record
1278
1279 $Returns:
1280
1281 $Arguments: phonebook_id The phonebook identifier
1282 record The record to destroy
1283
1284 *******************************************************************************/
1285
1286 void ATB_pb_FreeRec(SHORT phonebook_id, T_PB_RECORD *record)
1287 {
1288 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1289
1290 if (data->ext_max>0 && record->ext_data!=NULL)
1291 {
1292 GI_pb_MemFree((UBYTE *)record->ext_data, data->ext_max);
1293 }
1294 GI_pb_MemFree((UBYTE *)record->number, data->number_max/2);
1295 GI_pb_MemFree((UBYTE *)record->alpha.data, data->alpha_max*sizeof(USHORT));
1296
1297 GI_pb_MemFree((UBYTE *)record, sizeof(T_PB_RECORD));
1298
1299 return;
1300 }
1301
1302
1303 /*******************************************************************************
1304
1305 $Function: ATB_pb_AllocRecList
1306
1307 $Description: Allocates memory for a list of records
1308
1309 $Returns:
1310
1311 $Arguments: phonebook_id The phonebook identifier
1312 num_recs The number of records to allocate
1313
1314 *******************************************************************************/
1315
1316 T_PB_LIST *ATB_pb_AllocRecList(SHORT phonebook_id, SHORT num_recs)
1317 {
1318 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1319 T_PB_LIST *list;
1320 SHORT rec_index;
1321
1322 list = (T_PB_LIST *)GI_pb_MemAlloc(sizeof(T_PB_LIST));
1323 list->records_max = num_recs;
1324 list->records_used = 0;
1325 list->record = (T_PB_RECORD *)GI_pb_MemAlloc(sizeof(T_PB_RECORD)*num_recs);
1326
1327 for (rec_index=0; rec_index<num_recs; rec_index++)
1328 {
1329 list->record[rec_index].alpha.data = (USHORT *)GI_pb_MemAlloc(data->alpha_max*sizeof(USHORT));
1330 list->record[rec_index].number = (UBYTE *)GI_pb_MemAlloc(data->number_max/2);
1331 if (data->ext_max>0)
1332 {
1333 list->record[rec_index].ext_data = (UBYTE *)GI_pb_MemAlloc(data->ext_max);
1334 }
1335 else
1336 {
1337 list->record[rec_index].ext_data = NULL;
1338 }
1339 }
1340
1341 return list;
1342 }
1343
1344
1345 /*******************************************************************************
1346
1347 $Function: ATB_pb_FreeRecList
1348
1349 $Description: Frees memory allocated for a list of records
1350
1351 $Returns:
1352
1353 $Arguments: phonebook_id The phonebook identifier
1354 record The records to destroy
1355 num_recs Number of records in the list
1356
1357 *******************************************************************************/
1358
1359 void ATB_pb_FreeRecList(SHORT phonebook_id, T_PB_LIST *list)
1360 {
1361 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1362 SHORT rec_index;
1363
1364 for (rec_index=0; rec_index<list->records_max; rec_index++)
1365 {
1366 if (data->ext_max>0 && list->record[rec_index].ext_data!=NULL)
1367 {
1368 GI_pb_MemFree((UBYTE *)list->record[rec_index].ext_data, data->ext_max);
1369 }
1370 GI_pb_MemFree((UBYTE *)list->record[rec_index].number, data->number_max/2);
1371 GI_pb_MemFree((UBYTE *)list->record[rec_index].alpha.data, data->alpha_max*sizeof(USHORT));
1372 }
1373
1374 GI_pb_MemFree((UBYTE *)list->record, sizeof(T_PB_RECORD)*list->records_max);
1375 GI_pb_MemFree((UBYTE *)list, sizeof(T_PB_LIST));
1376
1377 return;
1378 }
1379
1380
1381 /*******************************************************************************
1382
1383 $Function: ATB_mem_CopyRec
1384
1385 $Description: Copies a record from one location to another. The destination should
1386 have memory allocated for its strings.
1387
1388 $Returns:
1389
1390 $Arguments: dest_record The destination record
1391 src_record The source record
1392
1393 *******************************************************************************/
1394
1395 void ATB_pb_CopyRec(SHORT phonebook_id, T_PB_RECORD *dest_record, T_PB_RECORD *src_record)
1396 {
1397 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1398
1399 dest_record->alpha.length = src_record->alpha.length;
1400 dest_record->alpha.dcs = src_record->alpha.dcs;
1401 memcpy((UBYTE *)dest_record->alpha.data, (UBYTE *)src_record->alpha.data, data->alpha_max*sizeof(USHORT));
1402 memcpy(dest_record->number, src_record->number, data->number_max/2);
1403 if (data->ext_max>0)
1404 {
1405 memcpy(dest_record->ext_data, src_record->ext_data, data->ext_max);
1406 }
1407 dest_record->ton_npi = src_record->ton_npi;
1408
1409 return;
1410 }
1411
1412
1413 /*******************************************************************************
1414
1415 $Function: ATB_pb_OK
1416
1417 $Description: This function is called if the requested FS command executed successfully.
1418
1419 $Returns: None.
1420
1421 $Arguments: phonebook_id The phonebook identifier
1422
1423 *******************************************************************************/
1424
1425
1426 PB_RET ATB_pb_OK(SHORT phonebook_id)
1427 {
1428 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1429 PB_RET result;
1430
1431 switch(data->command_id)
1432 {
1433 case PB_INITIALISE:
1434 result = ATB_status_Initialise(phonebook_id);
1435 break;
1436 case PB_WRITEREC:
1437 result = ATB_status_WriteRec(phonebook_id);
1438 break;
1439 case PB_DELETEREC:
1440 result = ATB_status_DeleteRec(phonebook_id);
1441 break;
1442 }
1443
1444 return result;
1445 }
1446
1447
1448 /*******************************************************************************
1449
1450 $Function: ATB_pb_Error
1451
1452 $Description: This function is called if an error was returned while executing the
1453 requested command.
1454
1455 $Returns: None.
1456
1457 $Arguments: phonebook_id The phonebook identifier
1458 error_id Identifies the error that occurred.
1459
1460 *******************************************************************************/
1461
1462 void ATB_pb_Error(SHORT phonebook_id, SHORT error_id)
1463 {
1464 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1465
1466 /* Forward the error report to the GI */
1467
1468 GI_pb_Error(phonebook_id, data->command_id, error_id);
1469 data->status = PB_STATUS_NONE;
1470
1471 return;
1472 }
1473
1474 /*******************************************************************************
1475
1476 $Function: ATB_index_GetTable
1477
1478 $Description: Returns a pointer to the index table specified by the index_type
1479
1480 $Returns: None.
1481
1482 $Arguments: phonebook_id The phonebook identifier
1483 index_type The index table required.
1484
1485 *******************************************************************************/
1486
1487 SHORT * ATB_index_GetTable(SHORT phonebook_id, T_PB_INDEX index_type)
1488 {
1489 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1490 SHORT *table = NULL;
1491
1492 switch(index_type)
1493 {
1494 case INDEX_NAME:
1495 table = data->name_table;
1496 break;
1497 case INDEX_NUMBER:
1498 table = data->number_table;
1499 break;
1500 case INDEX_SEARCH:
1501 table = data->search_table;
1502 break;
1503 default:
1504 table = GI_pb_GetTable(index_type);
1505 break;
1506 }
1507
1508 return table;
1509 }
1510
1511
1512 /*******************************************************************************
1513
1514 $Function: ATB_index_Find
1515
1516 $Description: Find the nearest match to the supplied record. See ATB_pb_Find for
1517 more information.
1518
1519 $Returns: PB_OK Action completed OK.
1520 PB_BUSY Failed, phonebook is busy.
1521 PB_FILEREADFAIL File read encountered an error
1522 PB_RECDOESNOTEXIST Tried to access a record that does not exist
1523 (should never happen)
1524
1525 $Arguments: phonebook_id The phonebook identifier
1526 index_type The index_type of the provided record that is to be
1527 searched for, and the index list that the resulting
1528 new_log_index pertains to
1529 record The record whose index_type is to be matched
1530 new_log_index Returns with the logical index of the closest matching
1531 record
1532 match Specifies how good the resulting match was
1533 (MATCH_NONE, MATCH_START, MATCH_FRAGMENT
1534 or MATCH_EXACT).
1535
1536 *******************************************************************************/
1537
1538 PB_RET ATB_index_Find (SHORT phonebook_id, T_PB_INDEX index_type, T_PB_RECORD *record, SHORT *new_log_index, T_PB_MATCH *match)
1539 {
1540 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1541 PB_RET result = PB_OK;
1542 SHORT *table;
1543 SHORT lower;
1544 SHORT upper;
1545 SHORT middle;
1546 T_PB_RECORD *comp_record;
1547 T_PB_COMPARE compare;
1548 UBYTE searching;
1549
1550 /* Ensure that phonebook exists */
1551 if (!data)
1552 {
1553 trace("**ERROR** Phonebook does not exist");
1554 return PB_BOOKDOESNOTEXIST;
1555 }
1556
1557 /* Allocate record for comparison */
1558
1559 comp_record = ATB_pb_AllocRec(phonebook_id);
1560
1561 /* Make sure we're searching a valid index type */
1562
1563 if (index_type==INDEX_PHYSICAL || index_type==INDEX_SEARCH)
1564 {
1565 GI_pb_Error(phonebook_id, PB_FIND, PB_INDEXINVALID);
1566 return PB_INDEXINVALID;
1567 }
1568
1569 table = ATB_index_GetTable(phonebook_id, index_type);
1570
1571 /* The initial upper and lower bounds are the bounds of the array */
1572 lower = 0;
1573 upper = data->records_used-1;
1574
1575 searching = TRUE;
1576
1577 /* If the list is empty, insert at 0 */
1578
1579 if (data->records_used==0)
1580 {
1581 middle = 0;
1582 searching = FALSE;
1583 }
1584
1585 while (searching)
1586 {
1587 /* Compare our record with the middle element of the partition */
1588
1589 middle = (lower+upper)/2;
1590
1591 result = ATB_mem_ReadRec(phonebook_id, index_type, middle, comp_record);
1592
1593 if (result!=PB_OK)
1594 break;
1595
1596 compare = ATB_index_Compare(record, comp_record, index_type);
1597
1598 switch(compare)
1599 {
1600 case COMPARE_IDENTICAL:
1601 /* We've found a match; stop searching */
1602 searching = FALSE;
1603 break;
1604
1605 case COMPARE_FIRSTBEFORE:
1606 if (middle==lower)
1607 {
1608 /* The partition is a single element, so stop here. */
1609 searching = FALSE;
1610 }
1611 else
1612 {
1613 /* Our record comes before the middle element;
1614 * redefine the partiton */
1615 upper = middle - 1;
1616 }
1617 break;
1618
1619 case COMPARE_FIRSTAFTER:
1620 if (middle==upper)
1621 {
1622 /* The partition is a single element, so stop here. The record
1623 * we need is the record after this one. */
1624 middle++;
1625 searching = FALSE;
1626 }
1627 else
1628 {
1629 /* Our record comes after the middle element;
1630 * redefine the partiton */
1631 lower = middle+1;
1632 }
1633 break;
1634 }
1635 }
1636
1637 /* Store our results */
1638
1639 if (new_log_index)
1640 *new_log_index = middle;
1641
1642 if (match)
1643 {
1644 ATB_mem_ReadRec(phonebook_id, index_type, middle, comp_record);
1645 *match = ATB_index_Match(record, comp_record, index_type);
1646 }
1647
1648 /* Free allocated record */
1649
1650 ATB_pb_FreeRec(phonebook_id, comp_record);
1651
1652 /* Send success/failure info to the GI */
1653
1654 if (result==PB_OK)
1655 GI_pb_OK(phonebook_id, PB_FIND, NULL);
1656 else if (result!=PB_EXCT)
1657 GI_pb_Error(phonebook_id, PB_FIND, result);
1658
1659 return result;
1660 }
1661
1662
1663 /*******************************************************************************
1664
1665 $Function: ATB_index_GetPhysIndex
1666
1667 $Description: Returns the physical index corresponding to the given logical index, in
1668 the index table specified by the index_type.
1669
1670 $Returns: None.
1671
1672 $Arguments: phonebook_id The phonebook identifier.
1673 index_type The index table required.
1674 log_index The logical index.
1675
1676 *******************************************************************************/
1677
1678 SHORT ATB_index_GetPhysIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index)
1679 {
1680 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1681 SHORT phys_index;
1682 SHORT *table;
1683
1684 switch(index_type)
1685 {
1686 case INDEX_PHYSICAL:
1687 phys_index = log_index;
1688 break;
1689 case INDEX_NAME:
1690 case INDEX_NUMBER:
1691 case INDEX_SEARCH:
1692 table = ATB_index_GetTable(phonebook_id, index_type);
1693 phys_index = table[log_index];
1694 break;
1695 }
1696
1697 return phys_index;
1698 }
1699
1700
1701 /*******************************************************************************
1702
1703 $Function: ATB_index_GetLogIndex
1704
1705 $Description: Provided with the physical index, finds the logical index of the record
1706 in the index table specified.
1707
1708 $Returns: None.
1709
1710 $Arguments: phonebook_id The phonebook identifier
1711 index_type The index table required.
1712 phys_index The logical index of the record to find
1713
1714 *******************************************************************************/
1715
1716 SHORT ATB_index_GetLogIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT phys_index)
1717 {
1718 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1719 SHORT *table = ATB_index_GetTable(phonebook_id, index_type);
1720 SHORT log_index;
1721
1722 if (index_type==INDEX_PHYSICAL)
1723 {
1724 log_index = phys_index;
1725 }
1726 else
1727 {
1728 for (log_index=0; log_index<data->records_used; log_index++)
1729 {
1730 if (table[log_index]==phys_index)
1731 break;
1732 }
1733 }
1734
1735 return log_index;
1736 }
1737
1738
1739 /*******************************************************************************
1740
1741 $Function: ATB_index_AddRec
1742
1743 $Description: Adds a record to an index list, sorting automatically as required.
1744
1745 $Returns: None.
1746
1747 $Arguments: phonebook_id The phonebook identifier
1748 index_type The index table required.
1749 phys_index The physical index of the record to add.
1750 record The record to add.
1751 new_log_index New logical index of record.
1752
1753 *******************************************************************************/
1754
1755 void ATB_index_AddRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT phys_index, T_PB_RECORD *record, SHORT *new_log_index)
1756 {
1757 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1758 SHORT *table = ATB_index_GetTable(phonebook_id, index_type);
1759 SHORT log_index;
1760 SHORT found_log_index;
1761
1762 ATB_index_Find(phonebook_id, index_type, record, &found_log_index, NULL);
1763
1764 /* Shift end of index table down */
1765
1766 for (log_index=data->records_used; log_index>found_log_index; log_index--)
1767 {
1768 table[log_index] = table[log_index-1];
1769 }
1770
1771 table[found_log_index] = phys_index;
1772
1773 if (new_log_index)
1774 *new_log_index = found_log_index;
1775
1776 return;
1777 }
1778
1779 /*******************************************************************************
1780
1781 $Function: ATB_index_RemoveRec
1782
1783 $Description: Removes a record reference from an index list, sorting the index list
1784 appropriately.
1785
1786 $Returns: None.
1787
1788 $Arguments: phonebook_id The phonebook identifier
1789 index_type The index table required.
1790 log_index The logical index of the record to remove
1791
1792 *******************************************************************************/
1793
1794 void ATB_index_RemoveRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index)
1795 {
1796 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1797 SHORT *table = ATB_index_GetTable(phonebook_id, index_type);
1798 SHORT table_index;
1799
1800 for (table_index = log_index+1; table_index<data->records_used; table_index++)
1801 {
1802 table[table_index-1] = table[table_index];
1803 }
1804
1805 return;
1806 }
1807
1808
1809 /*******************************************************************************
1810
1811 $Function: ATB_index_Match
1812
1813 $Description: This function attempts a match between two records based on the
1814 index_type specified in index_type. It returns a value indicating
1815 whether there is no match (MATCH_NONE), a partial match
1816 (MAX_START), or an exact match (MATCH_EXACT).
1817 The function GI_pb_Match is called first, to check whether there is
1818 any user-specific matching required. If not, then ATB_alpha_Match
1819 is called for an alpha tag, or ATB_num_Match for a phone number.
1820 For any other index_type, MATCH_NONE is returned as default.
1821
1822 $Returns: MATCH_EXACT, MATCH_START or MATCH_NONE
1823
1824 $Arguments: record1 The first record to be compared
1825 record2 The second record to be compared
1826 index_type Indicator of the index_type which is to be matched
1827
1828 *******************************************************************************/
1829
1830 T_PB_MATCH ATB_index_Match(T_PB_RECORD *record1, T_PB_RECORD *record2, T_PB_INDEX index_type)
1831 {
1832 T_PB_MATCH match;
1833
1834 match = GI_pb_Match(record1, record2, index_type);
1835
1836 if (match==MATCH_DEFAULT)
1837 {
1838 switch(index_type)
1839 {
1840 case INDEX_NAME:
1841 match = ATB_alpha_Match(&record1->alpha, &record2->alpha);
1842 break;
1843 case INDEX_NUMBER:
1844 match = ATB_num_Match(record1->number, record2->number);
1845 break;
1846 }
1847 }
1848
1849 return match;
1850 }
1851
1852
1853
1854 /*******************************************************************************
1855
1856 $Function: ATB_index_Compare
1857
1858 $Description: This function compares two records based on the index_type specified in
1859 index_type. It returns a value indicating whether the first record should
1860 come before or after the second.
1861 The function GI_pb_Compare is called first, to check whether there is
1862 any user-specific sorting required. If not, then ATB_alpha_Compare is
1863 called for an alpha tag, or ATB_num_Compare for a phone number.
1864 For any other index_type, COMPARE_FIRSTBEFORE is returned as default.
1865
1866 $Returns: COMPARE_IDENTICAL The two records are identical
1867 COMPARE_FIRSTBEFORE The first record should come before the second record
1868 COMPARE_FIRSTAFTER The first record should come after the second record
1869
1870 $Arguments: record1 The first record to be compared
1871 record2 The second record to be compared
1872 index_type Indicator of the index_type which is to be compared
1873
1874 *******************************************************************************/
1875
1876 T_PB_COMPARE ATB_index_Compare(T_PB_RECORD *record1, T_PB_RECORD *record2, T_PB_INDEX index_type)
1877 {
1878 T_PB_COMPARE compare;
1879
1880 compare = GI_pb_Compare(record1, record2, index_type);
1881
1882 if (compare==COMPARE_DEFAULT)
1883 {
1884 switch(index_type)
1885 {
1886 case INDEX_NAME:
1887 compare = ATB_alpha_Compare(&record1->alpha, &record2->alpha);
1888 break;
1889 case INDEX_NUMBER:
1890 compare = ATB_num_Compare(record1->number, record2->number);
1891 break;
1892 }
1893 }
1894
1895 return compare;
1896 }
1897
1898
1899 /*******************************************************************************
1900
1901 $Function: ATB_alpha_Compare
1902
1903 $Description: This function compares two alpha strings on the basis of an ascending
1904 alphanumeric latin list, and specifies which record would come first.
1905
1906
1907 $Returns: COMPARE_FIRSTBEFORE The first record should come before the second record
1908 COMPARE_FIRSTAFTER The first record should come after the second record
1909
1910 $Arguments: alpha1 The first alpha tag
1911 alpha2 The second alpha tag
1912
1913 *******************************************************************************/
1914
1915 T_PB_COMPARE ATB_alpha_Compare(T_PB_ALPHA *alpha1, T_PB_ALPHA *alpha2)
1916 {
1917 T_PB_COMPARE compare;
1918 SHORT charIndex;
1919 USHORT length1 = alpha1->length;
1920 USHORT length2 = alpha2->length;
1921 USHORT char1;
1922 USHORT char2;
1923
1924 compare = COMPARE_IDENTICAL; /* Default */
1925
1926 /* Special case, length of first string is 0 */
1927
1928 if (length1==0)
1929 compare = COMPARE_FIRSTBEFORE;
1930
1931 for (charIndex = 0; charIndex < length1; charIndex++)
1932 {
1933 if (charIndex==length2) /* E.g. "Johnson" and "John" */
1934 {
1935 compare = COMPARE_FIRSTAFTER;
1936 break;
1937 }
1938
1939 char1 = alpha1->data[charIndex];
1940 if (char1>=(SHORT)'A' && char1<=(SHORT)'Z')
1941 char1 += (SHORT)('a'-'A');
1942 char2 = alpha2->data[charIndex];
1943 if (char2>=(SHORT)'A' && char2<=(SHORT)'Z')
1944 char2 += (SHORT)('a'-'A');
1945
1946 if (char1 < char2)
1947 {
1948 compare = COMPARE_FIRSTBEFORE;
1949 break;
1950 }
1951 if (char1 > char2)
1952 {
1953 compare = COMPARE_FIRSTAFTER;
1954 break;
1955 }
1956 if (charIndex==length1-1 && length2>length1) /*E.g. "John" and "Johnson" */
1957 {
1958 compare = COMPARE_FIRSTBEFORE;
1959 break;
1960 }
1961 }
1962
1963 return compare;
1964 }
1965
1966
1967 /*******************************************************************************
1968
1969 $Function: ATB_alpha_Match
1970
1971 $Description: This function matches two alpha strings on the basis of a latin string
1972 matched from the start, and specifies how they match.
1973
1974 $Returns: MATCH_NONE The strings do not match
1975 MATCH_START The first string matches the start of the second string
1976 MATCH_EXACT The two strings match exactly
1977
1978 $Arguments: alpha1 The first alpha tag
1979 alpha2 The second alpha tag
1980
1981 *******************************************************************************/
1982
1983 T_PB_COMPARE ATB_alpha_Match(T_PB_ALPHA *alpha1, T_PB_ALPHA *alpha2)
1984 {
1985 T_PB_MATCH match;
1986 SHORT charIndex;
1987 USHORT length1 = alpha1->length;
1988 USHORT length2 = alpha2->length;
1989 SHORT offset;
1990 UBYTE searching;
1991 UBYTE some_match;
1992 USHORT char1, char2;
1993
1994 match = MATCH_EXACT; /* Default */
1995 searching = TRUE;
1996 some_match = FALSE;
1997 offset = 0;
1998
1999 do
2000 {
2001 for (charIndex = 0; charIndex < length1; charIndex++)
2002 {
2003
2004 if (charIndex==(length2-offset)) /* E.g. "Johnson" and "John" */
2005 {
2006 searching = FALSE;
2007 break; /* No match, will exit do/while */
2008 }
2009
2010 char1 = alpha1->data[charIndex];
2011 if (char1>=(SHORT)'A' && char1<=(SHORT)'Z')
2012 char1 += (SHORT)('a'-'A');
2013 char2 = alpha2->data[charIndex+offset];
2014 if (char2>=(SHORT)'A' && char2<=(SHORT)'Z')
2015 char2 += (SHORT)('a'-'A');
2016
2017 if (char1 != char2)
2018 {
2019 some_match = FALSE; /* Any fragment so far identified does not fit */
2020 break; /* No match, keep looking */
2021 }
2022
2023 some_match = TRUE;
2024
2025 if (charIndex==length1-1 && length2>length1) /*E.g. "John" and "Johnson" */
2026 {
2027 if (offset==0)
2028 match = MATCH_START;
2029 else
2030 match = MATCH_FRAGMENT;
2031 break;
2032 }
2033 }
2034
2035 if (some_match==TRUE)
2036 {
2037 searching = FALSE;
2038 }
2039 else
2040 {
2041 offset++;
2042
2043 /* If the fragment won't fit, don't keep looking */
2044 if ((offset+length1)>length2)
2045 {
2046 match=MATCH_NONE;
2047 searching = FALSE;
2048 }
2049 }
2050 }while (searching);
2051
2052 return match;
2053 }
2054
2055
2056 /*******************************************************************************
2057
2058 $Function: ATB_num_Digit
2059
2060 $Description: Extracts the four-bit digit from a BCD number
2061
2062 $Returns: The four bit digit
2063
2064 $Arguments: num The BCD number
2065 numIndex The position in the BCD number to look
2066
2067 *******************************************************************************/
2068
2069 UBYTE ATB_num_Digit(UBYTE *num, SHORT numIndex)
2070 {
2071 UBYTE digit;
2072 UBYTE shift = (numIndex&0x1)*0x4;
2073
2074 digit = num[numIndex>>1]; /* Each BCD digit takes up half a byte */
2075 digit &= (0xF<<shift); /* Isolate the digit */
2076 digit >>= shift; /* Shift it so it has a value 0x0 - 0xF */
2077
2078 return digit;
2079 }
2080
2081
2082 /*******************************************************************************
2083
2084 $Function: ATB_num_Length
2085
2086 $Description: Returns the length of a BCD number in digits
2087
2088 $Returns: Length of BCD number
2089
2090 $Arguments: num The BCD number
2091
2092 *******************************************************************************/
2093
2094 SHORT ATB_num_Length(UBYTE *num)
2095 {
2096 SHORT length;
2097
2098 for (length = 0; ATB_num_Digit(num, length)!=0xF; length++)
2099 {
2100 }
2101
2102 return length;
2103 }
2104
2105
2106 /*******************************************************************************
2107
2108 $Function: ATB_num_Compare
2109
2110 $Description: This function compares two phone numbers by the standard comparison
2111 method (ascending numeric, from the end of the number) and specifies
2112 which record would come first if sorted in this method.
2113
2114 $Returns: COMPARE_FIRSTBEFORE The first record should come before the second record
2115 COMPARE_FIRSTAFTER The first record should come after the second record
2116
2117 $Arguments: num1 The first number
2118 num2 The second number
2119
2120 *******************************************************************************/
2121
2122 T_PB_COMPARE ATB_num_Compare(UBYTE *num1, UBYTE *num2)
2123 {
2124 T_PB_COMPARE compare;
2125 SHORT charIndex;
2126 SHORT length1 = ATB_num_Length(num1);
2127 SHORT length2 = ATB_num_Length(num2);
2128 UBYTE digit1;
2129 UBYTE digit2;
2130
2131 compare = COMPARE_IDENTICAL; /* Default */
2132
2133 for (charIndex = 0; charIndex < length1; charIndex++)
2134 {
2135 if (charIndex==length2) /* E.g. "123456" and "1234" */
2136 {
2137 compare = COMPARE_FIRSTAFTER;
2138 break;
2139 }
2140
2141 digit1 = ATB_num_Digit(num1, (SHORT)(length1-charIndex-1));
2142 digit2 = ATB_num_Digit(num2, (SHORT)(length2-charIndex-1));
2143
2144 if (digit1 < digit2)
2145 {
2146 compare = COMPARE_FIRSTBEFORE;
2147 break;
2148 }
2149 if (digit1 > digit2)
2150 {
2151 compare = COMPARE_FIRSTAFTER;
2152 break;
2153 }
2154 if (charIndex==length1-1 && length2>length1) /*E.g. "1234" and "123456" */
2155 {
2156 compare = COMPARE_FIRSTBEFORE;
2157 break;
2158 }
2159 }
2160
2161 return compare;
2162 }
2163
2164 /*******************************************************************************
2165
2166 $Function: ATB_num_Match
2167
2168 $Description: This function matches phone numbers, from the end backwards, and
2169 specifies how they match.
2170
2171 $Returns: MATCH_NONE The numbers do not match
2172 MATCH_START The first number matches the end of the second number
2173 MATCH_EXACT The two numbers match exactly
2174
2175 $Arguments: num1 The first number
2176 num2 The second number
2177
2178 *******************************************************************************/
2179
2180 T_PB_MATCH ATB_num_Match(UBYTE *num1, UBYTE *num2)
2181 {
2182 T_PB_MATCH match;
2183 SHORT charIndex;
2184 SHORT length1 = ATB_num_Length(num1);
2185 SHORT length2 = ATB_num_Length(num2);
2186 SHORT offset;
2187 UBYTE searching;
2188 UBYTE some_match;
2189 UBYTE digit1;
2190 UBYTE digit2;
2191
2192 match = MATCH_EXACT; /* Default */
2193 searching = TRUE;
2194 some_match = FALSE;
2195 offset = 0;
2196
2197 do
2198 {
2199 for (charIndex = 0; charIndex < length1; charIndex++)
2200 {
2201 if (charIndex==(length2-offset)) /* E.g. "12345" and "123" */
2202 {
2203 searching = FALSE;
2204 break; /* No match, will exit do/while */
2205 }
2206
2207 digit1 = ATB_num_Digit(num1, (SHORT)(length1-charIndex-1));
2208 digit2 = ATB_num_Digit(num2, (SHORT)(length2-charIndex-1));
2209
2210 if (digit1 != digit2)
2211 {
2212 some_match = FALSE; /* Any fragment so far identified does not fit */
2213 break; /* No match, keep looking */
2214 }
2215
2216 some_match = TRUE;
2217
2218 if (charIndex==length1-1 && length2>length1) /*E.g. "123" and "12345" */
2219 {
2220 if (offset==0)
2221 match = MATCH_START;
2222 else
2223 match = MATCH_FRAGMENT;
2224 break;
2225 }
2226 }
2227
2228 if (some_match==TRUE)
2229 {
2230 searching = FALSE;
2231 }
2232 else
2233 {
2234 offset++;
2235
2236 /* If the fragment won't fit, don't keep looking */
2237 if ((offset+length1)>length2)
2238 {
2239 match=MATCH_NONE;
2240 searching = FALSE;
2241 }
2242 }
2243 } while (searching);
2244
2245 return match;
2246 }
2247
2248
2249 /*******************************************************************************
2250
2251 $Function: ATB_mem_UpdateCache
2252
2253 $Description: Updates the cache with the record provided. If the cache is full, the
2254 least used record is overwritten.
2255
2256 $Returns: None.
2257
2258 $Arguments: phonebook_id The phonebook identifier
2259 index_type The index table required.
2260 phys_index The physical index of the record to add.
2261 record The record to add.
2262
2263 *******************************************************************************/
2264
2265 void ATB_mem_UpdateCache(SHORT phonebook_id, SHORT phys_index, T_PB_RECORD *record)
2266 {
2267 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
2268 SHORT cacheIndex;
2269 SHORT leastUsed;
2270 SHORT leastIndex;
2271
2272 /* First check if record is already in RAM */
2273
2274 if (data->cache[phys_index] != NULL)
2275 {
2276 /* Copy the record in case it has changed */
2277
2278 ATB_pb_CopyRec(phonebook_id, data->cache[phys_index], record);
2279
2280 if (data->in_memory[phys_index]<0xFFFF)
2281 data->in_memory[phys_index]++;
2282 return;
2283 }
2284
2285 /* If the cache is full, find the least accessed record */
2286
2287 if (data->cache_size==data->cache_max)
2288 {
2289 leastIndex = 0;
2290 leastUsed = 255;
2291
2292 for (cacheIndex=0; cacheIndex<data->records_max; cacheIndex++)
2293 {
2294 if (data->cache[cacheIndex]!=NULL && data->in_memory[cacheIndex] < leastUsed)
2295 {
2296 leastUsed = data->in_memory[cacheIndex];
2297 leastIndex = cacheIndex;
2298 }
2299 }
2300
2301 /* Give the new record the memory allocated for the least used record */
2302
2303 data->cache[phys_index] = data->cache[leastIndex];
2304 data->cache[leastIndex] = NULL;
2305 data->in_memory[leastIndex] = 0;
2306 }
2307
2308 /* If the cache is not full, allocate memory for record */
2309
2310 else
2311 {
2312 data->cache[phys_index] = ATB_pb_AllocRec(phonebook_id);
2313 data->cache_size++;
2314 }
2315
2316 /* Copy the record into cache */
2317
2318 ATB_pb_CopyRec(phonebook_id, data->cache[phys_index], record);
2319 data->in_memory[phys_index] = 1;
2320
2321 return;
2322 }
2323
2324 /*******************************************************************************
2325
2326 $Function: ATB_mem_ReadRec
2327
2328 $Description: Reads a record from the logical position index. Information is read from
2329 cache if it is present in memory, otherwise it will be read from file.
2330
2331 The record information will be returned in the data structure pointed to
2332 by record. The T_PB_RECORD structure must be allocated by the caller.
2333
2334 $Returns: PB_OK Action completed OK.
2335 PB_FILEREADFAIL File read encountered an error
2336 PB_RECDOESNOTEXIST Tried to access a record that does not exist
2337
2338 $Arguments: phonebook_id The phonebook identifier
2339 index_type The index list from which the record is to be read
2340 log_index Logical index in the index list of the record to read
2341 record Structure in which to store record data
2342
2343 *******************************************************************************/
2344
2345 PB_RET ATB_mem_ReadRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index, T_PB_RECORD *record)
2346 {
2347 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
2348 SHORT phys_index;
2349 PB_RET result;
2350
2351 /* Check that record exists */
2352
2353 if (log_index<0
2354 || (log_index>=data->records_used && (index_type==INDEX_NAME || index_type==INDEX_NUMBER))
2355 || (index_type==INDEX_SEARCH && log_index>data->search_results)
2356 || (index_type==INDEX_PHYSICAL && log_index>data->records_max))
2357 {
2358 trace("*** Error - record does not exist ***");
2359 return PB_RECDOESNOTEXIST;
2360 }
2361
2362 /* Get the corresponding physical record index */
2363
2364 phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index);
2365
2366 /* If the record is in the cache, simply copy it. Otherwise, call FS to read the record. */
2367
2368 if (data->in_memory[phys_index]>0)
2369 {
2370 ATB_pb_CopyRec(phonebook_id, record, data->cache[phys_index]);
2371 result = PB_OK;
2372 }
2373 else
2374 {
2375 /* NB - assumes blocking read operation. If the read operation is blocking,
2376 * the cache must be large enough to store all the phonebook entries. */
2377 result = FS_pb_ReadRec(phonebook_id, phys_index, record);
2378 ATB_mem_UpdateCache(phonebook_id, phys_index, record);
2379 }
2380
2381 return result;
2382 }
2383
2384
2385 /*******************************************************************************
2386
2387 $Function: ATB_hnd_GetPbData
2388
2389 $Description: Returns phonebook data handle
2390
2391 $Returns: The phonebook data handle
2392
2393 $Arguments: phonebook_id The phonebook identifier
2394
2395 *******************************************************************************/
2396
2397 T_PB_DATA* ATB_hnd_GetPbData(SHORT phonebook_id)
2398 {
2399 return phonebook[phonebook_id];
2400 }
2401
2402
2403 /*******************************************************************************
2404
2405 $Function: ATB_hnd_SetPbData
2406
2407 $Description: Sets phonebook data handle
2408
2409 $Returns: None
2410
2411 $Arguments: phonebook_id The phonebook identifier
2412 data The phonebook data
2413
2414 *******************************************************************************/
2415
2416 void ATB_hnd_SetPbData(SHORT phonebook_id, T_PB_DATA *data)
2417 {
2418 phonebook[phonebook_id] = data;
2419
2420 return;
2421 }
2422