2
* ===========================================================================
5
* National Center for Biotechnology Information
7
* This software/database is a "United States Government Work" under the
8
* terms of the United States Copyright Act. It was written as part of
9
* the author's official duties as a United States Government employee and
10
* thus cannot be copyrighted. This software/database is freely available
11
* to the public for use. The National Library of Medicine and the U.S.
12
* Government have not placed any restriction on its use or reproduction.
14
* Although all reasonable efforts have been taken to ensure the accuracy
15
* and reliability of the software and data, the NLM and the U.S.
16
* Government do not and cannot warrant the performance or results that
17
* may be obtained by using this software or data. The NLM and the U.S.
18
* Government disclaim all warranties, express or implied, including
19
* warranties of performance, merchantability or fitness for any particular
22
* Please cite the author in any work or product based on this material.
24
* ===========================================================================
26
* RCS $Id: cdnewlib.c,v 6.2 1999/03/12 18:44:57 kans Exp $
28
* Author: Gregory Schuler
30
* Version Creation Date: 08-22-94
32
* File Description: Entrez low-level interface to CD-ROMs
35
* --------------------------------------------------------------------------
36
* Rev Date Name Description of modification
37
* ---- -------- -------- ------------------------------------------------
38
* 1.1 08-22-94 Schuler Initial revision
39
* 1.2 08-22-94 Schuler Rearranged the #include directives
40
* 1.3 08-25-94 Schuler cd3_CdGetDocSum: fix for new *.sum format.
41
* 1.3 08-25-94 Schuler Added error codes to ErrPostEx in many places.
42
* 1.4 08-25-94 Kans Some typecasts to make compilers happy
43
* 1.5 08-26-94 Schuler Some typecasts to make compilers happy
44
* 1.6 08-28-94 Ostell Convert double-slash comment to slash-star
45
* 1.7 08-31-94 Schuler Fixed bug in CdTrmLookup
46
* 1.8 08-31-94 Schuler Added magic number/version number checking
47
* 1.9 09-01-94 Schuler Use defines for directory names throughout
48
* 1.10 09-01-94 Kans Fixed bug in CdEntrez_FileOpen
49
* 1.11 09-02-94 Schuler Fixed bug in TrmIndex_Destruct
50
* 1.12 09-02-94 Schuler Implemented the CdMap_Destruct function
51
* 1.13 09-05-94 Schuler Implemented the ReadCdLayout function; Fixed bug
52
* in CdEnumFiles; Fixed bug in CdEntrez_FileOpen
53
* 1.14 09-05-94 Schuler Fixed bug in CdTrmLookup
54
* 1.15 09-05-94 Schuler Fixed bug in CdTrmLookup (tricky!)
55
* 1.16 09-06-94 Schuler Added some more VERBOSEs and ASSERTs
56
* 1.17 09-09-94 Schuler Fixed bug in CD swapping logic
57
* 1.18 09-21-94 Schuler Fixed bug in CdFini (NULL out _huff_tab)
58
* 1.19 09-22-94 Schuler Another fix to swapping logic...
59
* 1.20 10-04-94 Schuler Fixed invalid redeclaration of SwapInt4
61
* 1.22 10-08-94 Kans Eliminate prompt to insert CD when already there
62
* 1.23 10-10-94 Schuler Fixed bug in CdEnumFiles (wanted Entrez3 always)
63
* 1.24 10-24-94 Schuler Fixed CdDevice_FileOpen for to respect the
64
* upper_case and semicolon_one flags.
65
* 1.25 10-25-94 Schuler Change to CdVolume_Mount to re-init settings
66
* of upper_case and semicolon_one
67
* 1.26 10-26-94 Schuler Changed "long" to "Int4" in a couple places
68
* 1.27 11-17-94 Schuler Fixed bug in ReadCdLayout
69
* 1.28 11-17-94 Schuler Fixed bug in FindFloatingEntrezVolumes
70
* 1.29 11-17-94 Schuler Scan for already-mounted Entrez CDs on
71
* Mac desktop at startup
72
* 1.30 11-17-94 Schuler Fixed CdTestPath to properly handle cases where
73
* CD-ROM files are upper case and case matters
74
* 1.31 11-18-94 Schuler Added verbose trace message logging
75
* 1.32 11-19-94 Schuler Plugged some memory leaks
76
* 1.33 11-21-94 Schuler Fixed FileReadSwap4 to support 8-byte longs
77
* 1.34 11-22-94 Schuler Changed arg in cd3_CdLinkUidGet fom long to DocUid
78
* 1.35 11-22-94 Schuler Fixed invalid redeclaration of SwapInt4
79
* 1.36 11-22-94 Schuler Changed "long" to "DocUid" in CdLinkUidGet
80
* 1.37 11-25-94 Schuler Fixed bug in UidIndex_ReadPage (re: 8-byte longs)
81
* 1.38 11-30-94 Schuler Populate new cd_count field EntrezInfo
82
* 1.39 01-04-95 Kans ?
83
* 1.40 01-20-95 Schuler Added the CdMountEntrezVolume() and
84
* CdUnmountEntrezVolume() functions.
85
* 1.41 02-27-95 Schuler CdVolume_Mount() calls CdDevice_Init() if needed
86
* 1.42 02-28-95 Schuler Added more verbose log messages
87
* 1.43 02-28-95 Schuler Plugged some memory leaks
88
* 1.44 03-02-95 Schuler Changed fopen/fclose to FileOpen/FileClose
90
* 05-19-95 Schuler Added rcs Log directive for automatic insertion of
91
* modification comments.
93
* Revision $Log: cdnewlib.c,v $
94
* Revision Revision 6.2 1999/03/12 18:44:57 kans
95
* Revision fixed ErrPostEx problem
97
* Revision Revision 6.1 1998/08/24 18:42:16 kans
98
* Revision fixed -v -fd warnings
100
* Revision Revision 6.0 1997/08/25 18:13:01 madden
101
* Revision Revision changed to 6.0
103
* Revision Revision 5.3 1997/06/26 21:55:38 vakatov
104
* Revision [PC] DLL'd "ncbicdr.lib", "ncbiacc.lib", "ncbinacc.lib" and "ncbicacc.lib"
106
* Revision Revision 5.2 1997/02/14 22:34:49 epstein
107
* Revision allocated more memory for detailed info
109
* Revision 5.1 1996/11/19 21:46:45 shavirin
110
* CdInit() CdFini() messages made optional (printed in
113
* Revision 5.0 1996/05/28 13:55:34 ostell
114
* Set to revision 5.0
116
* Revision 4.2 1996/04/02 19:02:49 epstein
117
* change CDVOL_MAX and its use
119
* Revision 4.1 1996/03/26 16:29:11 epstein
120
* migrate byte-swapping functions to ncbimisc.[ch]
122
* Revision 4.0 1995/07/26 13:50:32 ostell
123
* force revision to 4.0
125
* Revision 1.48 1995/06/05 21:32:56 kans
126
* CdEnumFiles now uses safe fgets version (UnixFileGets)
128
* Revision 1.47 1995/05/18 17:27:46 kans
129
* changed qsort to HeapSort to avoid corruption/hang on one platform
131
* Revision 1.46 1995/05/16 14:36:20 schuler
132
* Automatic comment insertion enabled
135
* ==========================================================================
138
#define REVISION_STR "$Revision: 6.2 $"
147
DeviceCount = (number)
148
This should be equal to the number of Entrez CD-ROM images
149
that may be simultaneosuly on-line, either as mounted CD-ROMs
150
or as hard disk images. For example, suppose that you have a
151
single CD-ROM drive on which you keep one of the Entrez CD-ROMs
152
mounted plus a huge hard disk onto which you have copied the
153
contents of the remaining two CD-ROMs. In this case, the
154
DeviceCount setting should be 3.
156
IdxCacheSize = (kbytes)
157
TrmCacheSize = (kbytes)
158
Maximum amount of memory to use for caching index & term files
160
LogVerbose = { Yes / No }
161
Causes verbose logging of status information for use in debugging
162
(default is No). Note that error logging must be enabled by the
163
application for anything to get logged.
166
[CdEntrez.device.#] (one section for each device, # = 1,2,3..)
168
Type = { CD / HARDDISK / NET }
169
Type of device: CD-ROM drive, local hard drive, or network drive.
171
Formal_Name = (some string)
172
This setting is optional, but provides a name for the device (e.g.
173
"Second CD-ROM drive") that can be used in user messages.
176
Full path corresponding to the root of the CD-ROM (excluding
177
the volume name when used with Insert_Volname=Yes; see below).
178
On the Macintosh, this should be omitted or left empty for
179
EJECTABLE devices with Insert_Volname=Yes.
181
Insert_Volname = { Yes / No }
182
If Yes, the name of the volume will be inserted after the
183
string specified in the Root setting and before the names of
184
subdirectories on the CD. This would be used for EJECTABLE
185
devices on Macintosh and Solaris systems (on the Mac, the
186
Root setting should be emtpy in this case as the path starts
187
with the volume name).
189
Ejectable = { Yes / No }
190
Set to yes if the device should be considered ejectable.
192
Bind = { Entrez1 / Entrez2 / Entrez 3 }
193
Use this setting to bind an Entrez CD-ROM to a device. The
194
setting should be the volume name of the CD: "Entrez1", "Entrez2",
195
etc. (not sensitive to case). Bound volumes are never ejected,
196
even if Ejectable=Yes.
202
These are some parameters to be passed to the MountCd and
203
EjectCd functions. They may be required on certain UNIX
208
#include <cdromlib.h>
210
#ifdef _NEW_CdEntrez_
213
static char _this_module[] = "CdEntrez";
215
#define THIS_MODULE _this_module
216
static char _this_file[] = __FILE__;
218
#define THIS_FILE _this_file
221
#define VERBOSE if(_verbose_trace) Nlm_ErrLogPrintf
224
#define TYPE_MAX DocType_MAX
228
#define TYPE_TAG_LEN 2
229
#define DIV_TAG_LEN 3
230
#define FLD_TAG_LEN 4
232
#define DEFAULT_IdxCacheSize 16
233
#define DEFAULT_SumCacheSize 16
234
#define DEFAULT_TrmCacheSize 8
237
#define VOLNUM_IS_VALID(x) ((x)<=_volume_ct && (x)>0)
238
#define TYPE_IS_VALID(x) ((x)<_type_ct && (x)>=0)
239
#define FIELD_IS_VALID(x) ((x)<_fld_ct && (x)>=0)
241
#define TYPTAG(x) _cdinfo->type_info[x].tag
242
#define FLDTAG(x) _cdinfo->field_info[x].tag
243
#define DIVTAG(x) _cdinfo->div_info[x].tag
255
#define MAGIC_hca 0x11BD
256
#define MAGIC_sum 0x0025
257
#define MAGIC_lnk 0x0A02
258
#define MAGIC_ofs 0x0A03
259
#define MAGIC_oix 0x0A04
260
#define MAGIC_trm 0x0A05
261
#define MAGIC_tix 0x0A06
262
#define MAGIC_pst 0x0A07
263
#define MAGIC_inf 0x0A0A
275
/* ========== CdDevice class ========== */
278
typedef struct CdDevice
280
CdDevInfo inf; /* device characteristics */
281
int bound_cd; /* Entrez volume number bound to this device, if any */
282
int hint; /* used during initialization for transient bind */
283
struct CdVolume *volume; /* Entrez volume currently mounted on this device */
284
unsigned is_cdrom :1; /* TRUE if device is a CD-ROM reader */
285
unsigned is_ejectable :1; /* TRUE if device should be considered ejectable */
286
unsigned ins_volname :1; /* TRUE if the volume name gets inserted into path */
287
unsigned semicolon_one :1; /* TRUE if the version number ";1" should be appended */
288
unsigned upper_case :1; /* TRUE if the file name should be upper case */
289
unsigned is_inited :1; /* TRUE if semicolon_one and upper_case are known */
290
time_t timestamp; /* time this device was last used */
294
#define CdDevice_New(a) CdDevice_Construct(MemNew(sizeof(CdDevice)),a)
295
#define CdDevice_Free(a) MemFree((void*)CdDevice_Destruct(a))
296
static CdDevice* CdDevice_Construct (CdDevice *cddev, int num);
297
static CdDevice* CdDevice_Destruct (CdDevice *cddev);
298
static int CdDevice_Init (CdDevice *cddev);
299
static int CdDevice_FileBuildPath (CdDevice *cddev, char *fpath, const char *fdir, const char *fname);
300
static FILE* CdDevice_FileOpen (CdDevice *cddev, const char *fdir, const char *fname, const char *fmode);
301
static void CdDevice_Touch (CdDevice *cddev);
302
static CdDevice* GetLruDevice (void);
304
/* ========== CdVolume class ========== */
306
typedef struct CdVolume
308
char *volume_name; /* "entrez1", "entrez2", or "entrez3" */
309
short volume_num; /* 1, 2, or 3 */
310
CdDevice *device; /* on which device is this volume mounted ? */
311
time_t timestamp; /* time this volume was last used */
315
#define CdVolume_New(a) CdVolume_Construct(MemNew(sizeof(CdVolume)),a)
316
#define CdVolume_Free(a) MemFree((void*)CdVolume_Destruct(a))
317
static CdVolume* CdVolume_Construct (CdVolume *cdvol, int number);
318
static CdVolume* CdVolume_Destruct (CdVolume *cdvol);
319
static CdDevice* CdVolume_Mount (CdVolume *cdvol, CdDevice *cddev, int verify);
320
static int CdVolume_Unmount (CdVolume *cdvol);
321
static int CdVolume_IsMounted (CdVolume *cdvol);
322
static int FindFloatingEntrezVolumes (int *outlist);
325
/* ========== UidIndex class ========= */
327
typedef struct UidIndex
329
DocType type; /* Document type: TYP_ML, TYP_AA, etc */
330
long uid_ct; /* Number of UIDs in index (can be > number of docs) */
331
long uid_min; /* Smallest UID in index */
332
long uid_max; /* Largest UID in index */
333
int pages; /* number of index pages */
334
long *index; /* array of 1st UID on each page */
338
typedef struct UidIndexRec
340
long uid; /* UID of document */
341
int divnum; /* division number (lookup in EntrezInfo) */
342
int filnum; /* hca file segment number (from 1) */
343
long hca_offset; /* offset into hca file for full ASN.1 record */
344
long sum_offset; /* offset into sum file for summary */
345
long lnk_offset; /* offset into lnk file for links */
349
#define UidIndex_New(a,b) UidIndex_Construct(MemNew(sizeof(UidIndex)),a,b)
350
#define UidIndex_Free(a) MemFree((void*)UidIndex_Destruct(a))
351
static UidIndex* UidIndex_Construct (UidIndex *uidx, DocType type, EntrezTypeData *info);
352
static UidIndex* UidIndex_Destruct (UidIndex *uidx);
353
static int UidIndex_ReadPageMap (UidIndex *uidx);
354
static long* UidIndex_ReadPage (UidIndex *uidx, int pagenum);
355
static int UidIndex_Lookup (UidIndex *uidx, DocUid uid, UidIndexRec *rec);
358
/* ========== TrmIndex class ========== */
360
typedef struct TrmIndex
362
struct TrmIndex *next; /* next element in linked list */
363
char tag[6]; /* tag for field (e.g. "mesh") */
364
unsigned type :6; /* ??? */
365
unsigned fld :6; /* ??? */
366
unsigned style :4; /* ??? */
367
long trm_ct; /* term count */
368
int page_ct; /* page count */
369
int page_size; /* page size */
370
char **index; /* array of 1st term on each page */
374
#define TrmIndex_New(a,b,c,d) TrmIndex_Construct(MemNew(sizeof(TrmIndex)),a,b,c,d)
375
#define TrmIndex_Free(a) MemFree((void*)TrmIndex_Destruct(a))
376
static TrmIndex* TrmIndex_Construct (TrmIndex *tidx, int type, int fld, const char *tag, EntrezFieldData *info);
377
static TrmIndex* TrmIndex_Destruct (TrmIndex *tidx);
378
static int TrmIndex_ReadPageMap (TrmIndex *tidx);
379
static Byte* TrmIndex_ReadPage (TrmIndex *tidx, int pagenum);
380
static int TrmIndex_Lookup (TrmIndex *tidx, const char *stem);
381
static CdTerm* TrmIndex_GetCdTerm (TrmIndex *tidx, const char *term);
382
static int TrmIndex_ScanPages (TrmIndex *tidx, int start, int count, CdTermProc proc);
383
static FILE * TrmIndex_PostingsFileOpen (TrmIndex *tidx);
385
static CdTerm* getcdtrm (TrmIndex *tidx, int pagenum, Byte **pptr);
386
static int trmcmp (const char *term1, const char *term2);
387
static int trmncmp (const char *term1, const char *term2, int n);
390
/* ========== CdMap class ========= */
394
unsigned user_set :1; /* any user-supplied path set ? */
395
unsigned multicd :1; /* files exist on multiple CDs ? */
396
unsigned lnklist :1; /* list is a linked list ? (array if false) */
397
short array_size; /* array size for list */
398
short id_num; /* id_number for divisions */
399
short cd_num; /* CD number */
400
short *cd_list; /* list of CD numbers, if multicd */
401
char *user_path; /* user-supplied path */
402
struct CdMap *list; /* linked list or array */
406
#define CdMap_New(a) CdMap_Construct((CdMap*)MemNew(sizeof(CdMap)),a)
407
#define CdMap_Free(x) MemFree((void*)CdMap_Destruct(x))
408
static CdMap* CdMap_Construct (CdMap *map, int list_size);
409
static CdMap* CdMap_Destruct (CdMap *map);
410
static void CdMap_ParseCdNums (CdMap *map, char *nums);
411
static void CdMap_FindPath (CdMap *map, const char *key);
412
static int CdMap_GetSpecs (CdMap *map, int *cdlist, char *fdir);
413
static CdMap* CdMap_GetChild (CdMap *map, int nkid);
416
static Boolean ReadCdLayout (FILE *fd);
419
/* ========== LSet class ========== */
420
typedef struct DocLink
438
#define LSet_New(a,b,c) LSet_Construct(MemNew(sizeof(LSet)),a,b,c)
439
#define LSet_Free(x) MemFree((void*)LSet_Destruct(x))
440
static LSet* LSet_Construct (LSet *lset, short sorc_type, short dest_type, int link_max);
441
static LSet * LSet_Destruct (LSet *lset);
442
static int LSet_Read (LSet *lset, FILE *fd);
443
static LinkSet* LSet_Convert (LSet *lset);
446
/* ========== HuffTable class ========== */
448
typedef struct HuffTable
456
#define HuffTable_New(a) HuffTable_Construct(MemNew(sizeof(HuffTable)),a)
457
#define HuffTable_Free(a) MemFree((void*)HuffTable_Destruct(a))
458
static HuffTable* HuffTable_Construct (HuffTable *huff, int slots);
459
static HuffTable* HuffTable_Destruct (HuffTable *huff);
460
static HuffTable* HuffTable_Read (FILE *fd);
463
/* ========== DecompInfo class ========== */
464
typedef struct DecompInfo
474
#define DecompInfo_New(a) DecompInfo_Construct(MemNew(sizeof(DecompInfo)),a)
475
#define DecompInfo_Free(a) MemFree((void*)DecompInfo_Destruct(a))
476
static DecompInfo* DecompInfo_Construct (DecompInfo *info, HuffTable *huff);
477
/*static DecompInfo* DecompInfo_Destruct (DecompInfo *info);*/
478
#define DecompInfo_Destruct(info) (info)
479
static AsnIo* DecompInfo_Attach (DecompInfo *info, FILE *fd);
480
static FILE* DecompInfo_Detach (DecompInfo *info);
482
static Int2 LIBCALLBACK DecompReadProc (void *p, char *buff, Uint2 count);
484
/* ========== Cache class ========== */
485
#define Cache_MAGIC_VALUE 223445L
487
typedef struct CachePage
495
typedef void (PASCAL *CacheDataFreeProc)(void *data);
496
static void PASCAL DefCacheDataFreeProc (void *data);
504
long page_size; /* optional */
507
CacheDataFreeProc fproc;
511
#define Cache_New(a,b) Cache_Construct(MemNew(sizeof(Cache)),a,b)
512
#define Cache_Free(a) MemFree((void*)Cache_Destruct(a))
513
static Cache* Cache_Construct (Cache *cache, int size, CacheDataFreeProc fproc);
514
static Cache* Cache_Destruct (Cache *cache);
515
static int Cache_Insert (Cache *cache, long id, void *data);
516
static int Cache_Delete (Cache *cache, long id);
517
static int Cache_Touch (Cache *cache, long id);
518
static void* Cache_Lock (Cache *cache, long id);
519
static int Cache_Unlock (Cache *cache, long id);
520
static void* Cache_Peek (Cache *cache, long id);
521
static void Cache_Purge (Cache*);
522
static void Cache_LogStats (Cache *cache, const char *name);
523
static char* Cache_ReportStats (Cache *cache, char *buffer);
524
static int Cache_IsValid (Cache *cache);
527
/* ========== Misc. structs ========== */
532
unsigned short magic;
533
unsigned short format;
544
typedef struct DivInfo
546
char tag[1+DIV_TAG_LEN];
547
short cd_num[TYPE_MAX];
551
/* ========== Misc. functions ========== */
553
static FILE * CdEntrez_FileOpen (CdEntrezDir dirnum, int doctype, int divnum, int ftype, const char *fname, const char *fmode);
554
static void CdEntrez_FileClose (CdEntrezDir dirnum, int doctype, FILE *fd);
556
static int InvalidConfiguration (int code);
557
static int FileCorrupt (const char *fname);
558
static int FileOutOfDate (const char *fname);
559
static int FileNotRecognized (const char *fname);
560
static int CatastrophicFailure (int code);
562
static Boolean IsInitialized (void);
563
static Boolean ValidType (int type);
564
static Boolean ValidField (int field);
566
static char * _GetAppParamStr (const char *filebase, const char *section,
567
const char *key, const char *dlft);
569
#ifndef GetAppParamStr
570
#define GetAppParamStr _GetAppParamStr
573
static int LIBCALLBACK default_CdInsertProc (const char *volname, const CdDevInfo *dev);
574
static int LIBCALLBACK default_CdEjectProc (const char *volname, const CdDevInfo *dev);
577
/* ========== Static Variables ========== */
579
static CdDevHook _hookInsert = default_CdInsertProc;
580
static CdDevHook _hookEject = default_CdEjectProc;
582
static char * _empty_string = "";
584
static HuffTable * _huff_tab[TYPE_MAX];
586
static FILE* _fd_idx[TYPE_MAX];
587
static FILE* _fd_sum[TYPE_MAX];
588
static FILE* _fd_lnk[TYPE_MAX];
600
struct CdFInfo _finfo[] = {
602
"hca", MAGIC_hca, FORMAT_hca,
603
"sum", MAGIC_sum, FORMAT_sum,
604
"lnk", MAGIC_lnk, FORMAT_lnk,
605
"ofs", MAGIC_ofs, FORMAT_ofs,
606
"oix", MAGIC_oix, FORMAT_oix,
607
"trm", MAGIC_trm, FORMAT_trm,
608
"tix", MAGIC_tix, FORMAT_tix,
609
"pst", MAGIC_pst, FORMAT_pst,
610
"inf", MAGIC_inf, FORMAT_inf
614
struct CdDirInfo _dir[] = {
615
SYS_KEYNAME, SYS_DIRNAME, NULL, NULL,
616
IDX_KEYNAME, IDX_DIRNAME, NULL, _fd_idx,
617
SUM_KEYNAME, SUM_DIRNAME, NULL, _fd_sum,
618
TRM_KEYNAME, TRM_DIRNAME, NULL, NULL,
619
LNK_KEYNAME, LNK_DIRNAME, NULL, _fd_lnk,
620
REC_KEYNAME, REC_DIRNAME, NULL, NULL
624
static EntrezInfo * _cdinfo;
625
static short _init_ct;
626
static short _rel_major;
627
static short _rel_minor;
628
static short _device_ct;
629
static short _volume_ct;
630
static short _type_ct;
631
static short _div_ct;
632
static short _fld_ct;
633
static short _verbose_trace;
635
static CdVolume * _cdvol;
636
static CdDevice * _cddev;
638
static DivInfo * _div;
639
static UidIndex * _uidx;
640
static TrmIndex ** _tidx[TYPE_MAX];
642
#define IDX_REC_SIZE 20
644
static int _idx_page_size;
645
static int _idx_page_slots;
646
static int _trm_page_size;
648
static Cache * _idx_cache;
649
static Cache * _trm_cache;
651
static char * _rcfile = "ncbi";
653
static CdMap _map[CdDir_LAST+1];
657
static int FileReadSwapShort (unsigned short *buffer, int count, FILE *fd);
658
static int FileReadSwapLong (unsigned long *buffer, int count, FILE *fd);
659
static int FileReadSwapInt4 (Uint4 *buffer, int count, FILE *fd);
663
static char * FileReadStr (FILE *fd, int lbyte);
668
/****************************************************************************
672
*****************************************************************************/
674
NLM_EXTERN Boolean cd3_CdInit (void)
683
CdDevice *dev_startup = NULL;
686
_verbose_trace = GetAppParamBoolean(_rcfile,"CdEntrez","LogVerbose",FALSE);
688
ErrLogPrintf("CdInit() [%s %s]\n", THIS_MODULE, REVISION_STR);
690
/*----- If already initialized, just increment counter -----*/
698
/***if (!_verbose_trace)
700
ErrLogPrintf(" Add \"LogVerbose=YES\" below [CdEntrez] in your NCBI\n");
701
ErrLogPrintf(" configuration file to log detailed information to this file.\n");
704
/*----- Gather information from config file -----*/
705
_device_ct = (int) GetAppParamInt(_rcfile,"CdEntrez","DeviceCount",0);
707
return InvalidConfiguration(1);
709
for (n=CdDir_FIRST; n<=CdDir_LAST; ++n)
711
if (FindPath(_rcfile,"CdEntrez.Paths",_dir[n].key,buffer,sizeof buffer))
712
_dir[n].user_dir = StrSave(buffer);
715
/*----- Initialize the list of devices -----*/
716
_cddev = (CdDevice*) MemNew(sizeof(CdDevice) * _device_ct);
717
for (n=0, dev=_cddev; n<_device_ct; ++n)
719
if (!CdDevice_Construct(dev++,n+1))
723
/*----- Now we need locate a copy of cdvolume.inf -----*/
724
memset((void*)&info,0,sizeof info);
726
if (_dir[CdDir_sys].user_dir !=NULL)
728
/* use the cdvolume.inf file on the hard disk */
729
strcpy(buffer,_dir[CdDir_sys].user_dir);
730
FileBuildPath(buffer,NULL,"cdvolume.inf");
734
/* first, look for a bound device */
735
for (k=0, dev=_cddev; k<_device_ct; ++k, ++dev)
737
if (_cddev[k].bound_cd && CdDevice_Init(dev))
740
CdDevice_FileBuildPath(dev,buffer,_dir[CdDir_sys].dir,"cdvolume.inf");
745
if (dev_startup == NULL)
747
/* if we reach this point, there are no bound devices, so
748
we now have to look through all of the devices, hoping
749
that one of them will have an Entrez CD-ROM already
755
for (k=0, dev=_cddev; k<_device_ct; ++k, ++dev)
757
if (CdDevice_Init(dev))
767
if (dev_startup == NULL)
769
/* Now were're going to have to ask the user
770
to insert one of the CD's */
772
dev_startup = &_cddev[0];
774
if (!(*_hookInsert)("Entrez1",&dev_startup->inf))
776
if (!CdDevice_Init(dev_startup))
778
VERBOSE("CdDevice_Init() failed, line %d\n",__LINE__);
783
CdDevice_FileBuildPath(dev_startup,buffer,_dir[CdDir_sys].dir,"cdvolume.inf");
787
/*----- OK, now we've found cdvolume.inf, let's read it -----*/
788
if ((fd = FileOpen(buffer,"rb")) ==NULL)
790
FileReadSwapShort(m,6,fd);
791
if (m[0] != MAGIC_inf)
792
return FileCorrupt(buffer);
793
if (m[1] > FORMAT_inf)
794
ErrPostEx(SEV_INFO,0,0,"File %s format number greater than expected",buffer);
799
VERBOSE("File cdvolume.inf read OK. \n");
800
VERBOSE("Release %d.%d (on %d CDs)\n",_rel_major,_rel_minor,_volume_ct);
802
/*----- Locate & read the cdentrez.inf file -----*/
803
if (_dir[CdDir_sys].user_dir !=NULL)
804
FileBuildPath(strcpy(buffer,_dir[CdDir_sys].user_dir),NULL,"cdentrez.inf");
806
CdDevice_FileBuildPath(dev_startup,buffer,_dir[CdDir_sys].dir,"cdentrez.inf");
807
if ((aio = AsnIoOpen(buffer,"r")) ==NULL)
808
return InvalidConfiguration(1);
809
_cdinfo = EntrezInfoAsnRead(aio,NULL);
810
_cdinfo->cd_count = _volume_ct;
814
ErrPostEx(SEV_INFO,0,0,"EntrezInfoAsnRead failure");
818
_type_ct = _cdinfo->type_count;
819
_fld_ct = _cdinfo->field_count;
820
_div_ct = _cdinfo->div_count;
821
_idx_page_size = _cdinfo->type_bucket_size;
822
_idx_page_slots = _idx_page_size / IDX_REC_SIZE;
823
_trm_page_size = _cdinfo->field_bucket_size;
824
VERBOSE("File cdentrez.inf read OK. \n");
826
/*----- initialize the list of volumes -----*/
827
_cdvol = (CdVolume*) MemNew(sizeof(CdVolume) * _volume_ct);
828
for (n=0; n<_volume_ct; ++n)
830
CdVolume_Construct(&(_cdvol[n]),n+1);
832
if (_cdvol[n].device == NULL)
833
{ /* the volume is not associated with any device, see if it's on desktop */
837
sprintf(volname,"entrez%d",n+1);
838
if (CdTestPath(volname,&info))
839
{ /* the volume is indeed on the desktop, find a device to mount it on */
841
for (i=0; i<_device_ct; ++i)
843
if (_cddev[i].volume == NULL)
845
if (CdVolume_Mount(&_cdvol[n],&_cddev[i],FALSE))
854
/*----- If fewer devices than volumes, at least one must be ejectable -----*/
855
if (_device_ct < _volume_ct)
857
for (n=0; n<_device_ct; ++n)
859
if (_cddev[n].is_ejectable)
863
return InvalidConfiguration(2);
866
/*----- Initialize index and term caches -----*/
867
n = (int) GetAppParamInt(_rcfile,"CdEntrez","IdxCacheSize",DEFAULT_IdxCacheSize);
868
pages = (int) ( (long)n * (long)KBYTE / (long)_idx_page_size);
869
pages = MAX(1,MIN(pages,256));
870
_idx_cache = Cache_New(pages,DefCacheDataFreeProc);
871
_idx_cache->page_size = _idx_page_size;
872
n = (int) GetAppParamInt(_rcfile,"CdEntrez","TrmCacheSize",DEFAULT_TrmCacheSize);
873
pages = (int) ( ((long)n * (long)KBYTE) / (long)_trm_page_size);
874
pages = MAX(1,MIN(pages,256));
875
_trm_cache = Cache_New(pages,DefCacheDataFreeProc);
876
_trm_cache->page_size = _trm_page_size;
878
/*----- Initialize the UidIndex & TrmIndex structures -----*/
879
_uidx = (UidIndex*) MemNew(sizeof(UidIndex) * _type_ct);
880
for (n=0; n<_type_ct; ++n)
882
UidIndex_Construct(&(_uidx[n]),(DocType)n,&(_cdinfo->types[n]));
884
_tidx[n] = (TrmIndex**) MemNew(sizeof(TrmIndex*) * _fld_ct);
885
for (j=0; j<_fld_ct; ++j)
887
if (_cdinfo->types[n].fields[j].num_terms > 0)
888
_tidx[n][j] = TrmIndex_New(n,j,FLDTAG(j),&(_cdinfo->types[n].fields[j]));
892
/*----- Read the cdlayout.inf file -----*/
893
if (_dir[CdDir_sys].user_dir !=NULL)
894
FileBuildPath(strcpy(buffer,_dir[CdDir_sys].user_dir),NULL,"cdlayout.inf");
896
CdDevice_FileBuildPath(dev_startup,buffer,_dir[CdDir_sys].dir,"cdlayout.inf");
897
if ((fd = FileOpen(buffer,"r")) ==NULL)
901
VERBOSE("File cdlayout.inf read OK \n");
903
/*----- Done. return success -----*/
909
NLM_EXTERN Boolean cd3_CdFini (void)
914
_verbose_trace = GetAppParamBoolean(_rcfile,"CdEntrez","LogVerbose",FALSE);
916
ErrLogPrintf("CdFini()\n");
918
if (!IsInitialized())
920
if ((--_init_ct) > 0)
923
/*----- Free index and cache data -----*/
924
if (Cache_IsValid(_idx_cache))
926
Cache_LogStats(_idx_cache,"idx");
927
Cache_Free(_idx_cache);
929
if (Cache_IsValid(_trm_cache))
931
Cache_LogStats(_trm_cache,"trm");
932
Cache_Free(_trm_cache);
934
for (i=0; i<_type_ct; ++i)
936
UidIndex_Destruct(&_uidx[i]);
937
for (j=0; j<_fld_ct; ++j)
938
TrmIndex_Free(_tidx[i][j]);
939
MemFree((void*)_tidx[i]);
941
HuffTable_Destruct(_huff_tab[i]);
944
MemFree((void*)_uidx);
946
/*----- Free CdVolume and CdDevice data -----*/
947
for (i=0; i<_volume_ct; ++i)
948
CdVolume_Destruct(&_cdvol[i]);
949
for (i=0; i<_device_ct; ++i)
950
CdDevice_Destruct(&_cddev[i]);
951
MemFree((void*)_cdvol);
952
MemFree((void*)_cddev);
954
/*----- Free cdlayout stuff -----*/
955
for (dir=CdDir_FIRST; dir<=CdDir_LAST; ++dir)
957
CdMap_Destruct(&_map[dir]);
958
MemFree(_dir[dir].user_dir);
961
/*----- Free the EntrezInfo struct -----*/
962
EntrezInfoFree(_cdinfo);
968
NLM_EXTERN AsnIo* cd3_EntrezInfoOpen (const char *dirname)
970
VERBOSE("EntrezInfoOpen(%s)\n", dirname ? dirname : "NULL");
972
/* NOT IMPLEMENTED */
974
/* Do we need this? Things seem to be working fine without it! */
980
NLM_EXTERN EntrezInfo* cd3_CdGetInfo (void)
982
VERBOSE("CdGetInfo()\n");
988
NLM_EXTERN char* cd3_CdDetailedInfo (void)
992
VERBOSE("CdDetailedInfo()\n");
994
if ((detailed = (char*)Malloc(8192)) == NULL)
997
if (!IsInitialized())
999
strcpy(detailed,"*** NOT INITIALIZED ***");
1004
sprintf(p,"Entrez release %d.%d\n",_rel_major,_rel_minor);
1006
if (_cdinfo->div_info != NULL)
1011
sprintf(p=strchr(p,0),"\nDIVISION INFORMATION\n");
1013
for (i=0, div=_cdinfo->div_info; i<_cdinfo->div_count; ++i, ++div)
1015
sprintf(p=strchr(p,0)," %s: ",div->tag);
1016
sprintf(p=strchr(p,0),"%-36s ",div->descr);
1017
sprintf(p=strchr(p,0),"%-25s\n",div->reldate ? div->reldate : "?");
1020
sprintf(p=strchr(p,0),"\n div Document Counts by Type\n");
1021
sprintf(p=strchr(p,0)," tag ml aa nt st\n");
1022
sprintf(p=strchr(p,0)," --- ------ ------ ------ ------\n");
1023
for (i=0, div=_cdinfo->div_info; i<_cdinfo->div_count; ++i, ++div)
1025
sprintf(p=strchr(p,0)," %s: ",div->tag);
1026
if (div->docs != NULL)
1028
for (j=0; j<_type_ct; ++j)
1029
sprintf(p=strchr(p,0),"%7ld ",div->docs[j]);
1031
sprintf(p=strchr(p,0),"\n");
1035
if (_idx_cache != NULL && _trm_cache != NULL)
1037
sprintf(p=strchr(p,0),"\nCACHE STATISTICS\n");
1038
sprintf(p=strchr(p,0),"\nIndex page cache:\n");
1039
Cache_ReportStats(_idx_cache,strchr(p,0));
1040
sprintf(p=strchr(p,0),"\nTerm page cache:\n");
1041
Cache_ReportStats(_trm_cache,strchr(p,0));
1047
NLM_EXTERN int cd3_CdTrmPageCt (DocType type, DocField fld)
1049
VERBOSE("CdTrmPageCt(%d,%d)\n",type,fld);
1051
if (IsInitialized() && ValidType(type) && ValidField(fld))
1053
return _cdinfo->types[type].fields[fld].num_bucket;
1058
NLM_EXTERN int cd3_CdTrmLookup (DocType type, DocField fld, const char *term)
1060
VERBOSE("CdTrmLookup(%d,%d,%s)\n",type,fld,term);
1062
if (IsInitialized() && ValidType(type) && ValidField(fld))
1064
TrmIndex *tidx = _tidx[type][fld];
1066
return TrmIndex_Lookup(tidx,term);
1071
NLM_EXTERN CdTerm* cd3_CdTrmFind (DocType type, DocField fld, const char *term)
1075
VERBOSE("CdTrmFind(%d,%d,%s)\n",type,fld,term);
1077
if (IsInitialized() && ValidType(type) && ValidField(fld))
1079
TrmIndex *tidx = _tidx[type][fld];
1081
trm = TrmIndex_GetCdTerm(tidx,term);
1086
NLM_EXTERN int cd3_CdTermScan (DocType type, DocField fld, int page_start,
1087
int page_count, CdTermProc proc)
1091
VERBOSE("CdTermScan(%d,%d,%d,%d,[proc])\n",type,fld,page_start,page_count);
1093
if (IsInitialized() && ValidType(type) && ValidField(fld))
1095
TrmIndex *tidx = _tidx[type][fld];
1099
page_count = INT_MAX;
1100
count = TrmIndex_ScanPages(tidx,page_start,page_count,proc);
1106
NLM_EXTERN long cd3_CdTrmUidsFil (DocType type, DocField fld, long offset,
1107
long count, const char *filename, Boolean append)
1111
VERBOSE("CdTrmUidsFil(%d,%d,%ld,%ld,%s,%s)\n",type,fld,offset,count,
1112
filename, append ? "TRUE" : "FALSE" );
1114
if (IsInitialized() && ValidType(type) && ValidField(fld))
1116
TrmIndex *tidx = _tidx[type][fld];
1119
FILE *fd1 = TrmIndex_PostingsFileOpen(tidx);
1120
FILE *fd2 = FileOpen(filename,(append) ? "ab":"wb");
1121
if (fd1 != NULL && fd2 != NULL)
1127
VERIFY(fseek(fd1,offset,SEEK_SET) ==0);
1129
for (n1=count; n1>0; n1-=n2)
1132
n2 = FileReadSwapInt4(arr,(int)n2,fd1);
1133
FileWrite((void*)arr,sizeof(Int4),(size_t)n2,fd2);
1137
else VERBOSE(" * TrmIndex_PostingsFileOpen failed\n");
1146
NLM_EXTERN long cd3_CdTrmUidsMem (DocType type, DocField fld, long offset,
1147
long count, DocUid *mem)
1149
VERBOSE("CdTrmUidsMem(%d,%d,%ld,%ld,[mem])\n",type,fld,
1152
ASSERT(count < (long)(UINT_MAX/sizeof(long)));
1154
if (IsInitialized() && ValidType(type) && ValidField(fld))
1156
TrmIndex *tidx = _tidx[type][fld];
1159
FILE *fd = TrmIndex_PostingsFileOpen(tidx);
1162
VERIFY(fseek(fd,offset,SEEK_SET) ==0);
1163
count = FileReadSwapInt4((Uint4*)mem,(int)count,fd);
1173
NLM_EXTERN int cd3_CdLinkUidGet (LinkSetPtr *result, DocType type,
1174
DocType link_to_type, int numuid, DocUid *uid_list,
1175
Boolean mark_missing, long maxlink)
1178
DocUid uid, *puid = uid_list;
1184
VERBOSE("CdLinkUidGet([result],%d,%d,%d,[list],%s,%ld)\n",
1185
type,link_to_type,numuid,
1186
mark_missing ? "TRUE" : "FALSE", maxlink);
1188
if (! (IsInitialized() && ValidType(type) && ValidType(link_to_type)) )
1194
uidx = &(_uidx[type]);
1196
for (i=cnt=0; i<numuid; ++i, ++puid)
1199
if (UidIndex_Lookup(uidx,uid,&rec))
1203
if (rec.lnk_offset > 0)
1208
strcpy(fname,TYPTAG(type));
1209
strcat(fname,".lnk");
1210
if ((fd = CdEntrez_FileOpen(CdDir_lnk,type,rec.divnum,LNK,fname,"rb")) ==NULL)
1212
maxlink = MIN(maxlink,INT_MAX);
1213
if ((lset = LSet_New(type,link_to_type,(int)maxlink)) ==NULL)
1216
if (fseek(fd,rec.lnk_offset,SEEK_SET) !=0)
1218
ErrPostEx(SEV_INFO,0,0,"fseek failure");
1221
if (!LSet_Read(lset,fd))
1225
else if (mark_missing)
1231
CdEntrez_FileClose(CdDir_lnk,type,fd);
1232
*result = (lset==NULL) ? NULL : LSet_Convert(lset);
1236
#define BIT_non_document 0x001
1237
#define BIT_no_abstract 0x002
1238
#define BIT_no_authors 0x004
1239
#define BIT_trans_title 0x008
1240
#define BIT_is_partial 0x010
1241
#define BIT_is_segmented 0x020
1243
NLM_EXTERN DocSum* cd3_CdGetDocSum (DocType type, DocUid uid)
1249
VERBOSE("CdGetDocSum(%d,%ld)\n",type,uid);
1251
if (!IsInitialized() || !ValidType(type))
1254
uidx = &(_uidx[type]);
1255
if (UidIndex_Lookup(uidx,uid,&rec) && rec.sum_offset > 0)
1260
strcpy(fname,TYPTAG(type));
1261
strcat(fname,".sum");
1262
if ((fd = CdEntrez_FileOpen(CdDir_sum,type,0,SUM,fname,"rb")) !=NULL)
1264
if (fseek(fd,rec.sum_offset,SEEK_SET) !=0)
1265
ErrPostEx(SEV_INFO,0,0,"fseek failure");
1267
if ((sum = (DocSum*)MemNew(sizeof(DocSum))) !=NULL)
1269
unsigned short m[4];
1270
FileReadSwapShort(m,3,fd);
1272
/* m[0] is doc-flags */
1273
if (m[0] & BIT_non_document) sum->non_document = TRUE;
1274
if (m[0] & BIT_no_abstract) sum->no_abstract = TRUE;
1275
if (m[0] & BIT_no_authors) sum->no_authors = TRUE;
1276
if (m[0] & BIT_trans_title) sum->translated_title = TRUE;
1277
if (m[0] & BIT_is_partial) sum->is_partial = TRUE;
1278
if (m[0] & BIT_is_segmented) sum->is_segmented = TRUE;
1280
/* m[1] is create date */
1283
sum->create.year = 1950 + ((int) (m[1] & 0xFE00) >> 9);
1284
sum->create.month = ((int) (m[1] & 0x01E0) >> 5);
1285
sum->create.day = (m[1] & 0x001F);
1288
/* m[2] is modify date */
1291
sum->modify.year = 1950 + ((int) (m[2] & 0xFE00) >> 9);
1292
sum->modify.month = ((int) (m[2] & 0x01E0) >> 5);
1293
sum->modify.day = (m[2] & 0x001F);
1296
FileReadSwapShort((unsigned short*)sum->link_count,_type_ct,fd);
1297
sum->caption = FileReadStr(fd,1);
1298
sum->title = FileReadStr(fd,2);
1299
sum->extra = FileReadStr(fd,1);
1302
CdEntrez_FileClose(CdDir_sum,type,fd);
1307
VERBOSE(" * bad UID %ld ?\n", uid);
1312
NLM_EXTERN AsnIo* cd3_CdDocAsnOpen (DocType type, DocUid uid)
1319
VERBOSE("CdDocAsnOpen(%d,%ld)\n",type,uid);
1321
if (!IsInitialized() || !ValidType(type))
1324
uidx = &(_uidx[type]);
1325
if (UidIndex_Lookup(uidx,uid,&rec))
1332
sprintf(fname,"%s%s%03d.hca",TYPTAG(type),DIVTAG(rec.divnum-1),rec.filnum);
1333
if ((fd = CdEntrez_FileOpen(CdDir_rec,uidx->type,rec.divnum,HCA,fname,"rb")) ==NULL)
1336
if (_huff_tab[type] == NULL)
1338
fseek(fd,22,SEEK_SET);
1339
_huff_tab[type] = HuffTable_Read(fd);
1340
if (_huff_tab[type] == NULL)
1342
return (AsnIo*) CatastrophicFailure(1);
1345
if (fseek(fd,rec.hca_offset,SEEK_SET) !=0)
1348
ErrPostEx(SEV_INFO,0,0,"fseek failure");
1353
if ((c & 0x0F) != 1)
1354
ErrPostEx(SEV_INFO,0,0,"unknown error");
1358
decomp = DecompInfo_New(_huff_tab[type]);
1359
aio = DecompInfo_Attach(decomp,fd);
1365
NLM_EXTERN AsnIo* cd3_CdDocAsnClose (AsnIo* aio)
1370
VERBOSE("CdDocAsnClose([aio])\n");
1372
ASSERT(aio != NULL);
1373
info = (DecompInfo*) aio->iostruct;
1374
ASSERT(info!= NULL);
1375
fd = DecompInfo_Detach(info);
1377
DecompInfo_Free(info);
1382
Boolean LIBCALL CdTestPath (const char *path, CdRomInfo *info)
1384
static char *fdir = SYS_DIRNAME;
1385
static char *fname = "cdvolume.inf";
1386
char fpath[256], *p;
1387
unsigned short m[8];
1390
VERBOSE("CdTestPath(%s,[info])\n",path);
1391
ASSERT(info != NULL);
1393
memset((void*)info,0,sizeof(CdRomInfo));
1395
/*----- lowercase, without ";1" -----*/
1397
p = strchr(fpath,'\0');
1398
FileBuildPath(fpath,fdir,fname);
1400
if (FileLength(fpath) >0)
1402
VERBOSE(" access attempt [%s] failed\n",fpath);
1404
/*----- lowercase, with ";1" -----*/
1406
if (FileLength(fpath) >0)
1408
info->semicolon_one = 1;
1411
VERBOSE(" access attempt [%s] failed\n",fpath);
1413
/*----- uppercase, without ";1" -----*/
1414
info->upper_case = 1;
1416
FileBuildPath(fpath,fdir,(char*)fname);
1418
if (FileLength(fpath) >0)
1420
VERBOSE(" access attempt [%s] failed\n",fpath);
1422
/*----- uppercase, with ";1" -----*/
1424
if (FileLength(fpath) >0)
1426
info->semicolon_one = 1;
1430
VERBOSE(" access attempt [%s] failed\n",fpath);
1431
VERBOSE(" struck out on [%s]. must be either invalid or not mounted\n",path);
1435
/*----- success -----*/
1437
VERBOSE(" access attempt [%s] succeeded\n",fpath);
1439
if ((fd = FileOpen(fpath,"rb")) == NULL)
1441
/*ErrPostEx(SEV_ERROR,2,3,"fopen(\"%s\",\"rb\") failed\n",fpath);*/
1445
/*----- read first 5 values in file -----
1446
* m[0] magic value for this file
1447
* m[1] format code for this file
1448
* m[2] cdrom release number (major portion)
1449
* m[3] cdrom release number (minor portion)
1450
* m[4] cdrom volume number (1, 2, or 3)
1451
* m[5] number of CD-ROMs in the set
1454
FileReadSwapShort(m,6,fd); /**** need to check for error ****/
1456
if (m[0] != MAGIC_inf)
1457
return FileCorrupt(fpath);
1458
if (m[1] != FORMAT_inf)
1459
VERBOSE(" unexpected format number (%d) for file %s\n",(int)m[1],fpath);
1460
info->rel_major = m[2];
1461
info->rel_minor = m[3];
1462
info->cd_num = m[4];
1463
info->cd_count = m[5];
1464
VERBOSE(" release %d.%d; cd %d of %d\n",(int)m[2],(int)m[3],(int)m[4],(int)m[5]);
1469
static char UnixReadChar (FILE *f)
1477
getcrsult = fgetc (f);
1478
ch = (char) getcrsult;
1479
if (getcrsult == EOF && feof (f)) {
1486
static char *UnixFileGets(char *buff, int maxsize, FILE *f)
1492
if (buff != NULL && maxsize > 0) {
1496
ch = UnixReadChar (f);
1497
while (ch != '\0' && ch != '\r' && ch != '\n' && i < maxsize) {
1500
ch = UnixReadChar (f);
1516
NLM_EXTERN long LIBCALL cd3_CdEnumFiles (CdEntrezDir dir, DocType type, const char *div,
1517
EntrezEnumFileProc proc, void *opaque_data)
1521
VERBOSE("CdEnumFiles(%d,%d,%s,[proc],[opaque])\n",dir,type,
1522
div ? div : "NULL");
1524
if ((fd = CdEntrez_FileOpen(CdDir_sys,0,0,0,"cdlayout.inf","r")) != NULL)
1526
char prefix[32], *p;
1528
long size, total_size = 0;
1533
strcpy(prefix,_dir[dir].key);
1537
strcat(prefix,TYPTAG(type));
1545
while (UnixFileGets(line,sizeof line,fd))
1547
if (strchr("#\r\n",line[0]))
1548
continue; /* comment line */
1550
if (isalpha(line[0]))
1555
if (strncmp(line,prefix,strlen(prefix))==0)
1558
VERIFY(p=strchr(line+1,'\t'));
1564
else if (line[0] == '\t')
1568
VERIFY(p=strchr(line+1,'\t'));
1575
if (!(*proc)(cdnum,_dir[dir].dir,line+1,size,opaque_data))
1583
if (count==0 && dir==CdDir_sys)
1585
static char * fn[] = { "cdentrez.inf", "cdlayout.inf", "cdvolume.inf" };
1586
static long fs[] = { 9865, 4504, 12 };
1589
/* The list of filenames and filesizes for the sysinfo directory
1590
was inadvertently omitted from the cdlayout.inf file on the
1591
sample CD-ROMs distributed to developers. This section of
1592
code should never be executed in the final release. */
1594
VERBOSE(" HACK (faking cdlayout.inf information for SYSINFO directory)\n");
1595
for (i=0; i<DIM(fs); ++i, ++count)
1599
if (!(*proc)(1,_dir[dir].dir,fn[i],fs[i],opaque_data))
1602
total_size += fs[i];
1606
VERBOSE(" %d files enumerated\n",count);
1613
NLM_EXTERN CdDevHook LIBCALL CdSetInsertHook (CdDevHook hook)
1615
CdDevHook prev = _hookInsert;
1617
VERBOSE("CdSetInsertHook\n");
1619
_hookInsert = (hook==NULL) ? hook : default_CdInsertProc;
1624
NLM_EXTERN CdDevHook LIBCALL CdSetEjectHook (CdDevHook hook)
1626
CdDevHook prev = _hookEject;
1628
VERBOSE("CdSetEjectHook\n");
1630
_hookEject = (hook==NULL) ? hook : default_CdEjectProc;
1635
NLM_EXTERN Boolean LIBCALL CdMountEntrezVolume (int cdnum, char *root, size_t buflen)
1637
if (root != NULL) *root = '\0';
1639
if (cdnum < 1 || cdnum > _volume_ct)
1640
ErrPostEx(SEV_WARNING,1,0,"Entrez CD number (%d) out of range",cdnum);
1643
CdVolume *cdvol = & _cdvol[cdnum-1];
1646
if ((cddev = cdvol->device) ==NULL)
1647
cddev = CdVolume_Mount(cdvol,NULL,TRUE);
1654
CdDevice_FileBuildPath(cddev,temp,NULL,NULL);
1655
strncat(root,temp,buflen);
1664
NLM_EXTERN Boolean LIBCALL CdUnmountEntrezVolume (int cdnum)
1669
if (cdnum < 1 || cdnum > _volume_ct)
1671
ErrPostEx(SEV_WARNING,1,0,"Entrez CD number (%d) out of range",cdnum);
1675
cdvol = & _cdvol[cdnum-1];
1676
cddev = cdvol->device;
1677
if (cddev != NULL && cddev->is_ejectable)
1679
char volume_to_eject[32];
1680
volume_to_eject[0] = '\0';
1681
if (cddev->ins_volname)
1682
sprintf(volume_to_eject,"entrez%d",cddev->volume->volume_num);
1683
else if (cdvol->volume_name != NULL)
1684
strcpy(volume_to_eject,cdvol->volume_name);
1686
if (!(*_hookEject)(volume_to_eject,&cddev->inf))
1687
ErrPostEx(SEV_INFO,0,0,"Unable to eject %s",cdvol->volume_name);
1689
return CdVolume_Unmount(cdvol);
1695
/****************************************************************************
1699
*****************************************************************************/
1702
static Boolean IsInitialized (void)
1704
if (_cdinfo == NULL)
1706
ErrPostEx(SEV_INFO,ERR_NotInited,1,"Library not initialized");
1713
static Boolean ValidType (int type)
1715
if (!TYPE_IS_VALID(type))
1717
ErrPostEx(SEV_INFO,ERR_BadParam,SUB_DocType,
1718
"DocType value (%d) out of range ",type);
1725
static Boolean ValidField (int field)
1727
if (!FIELD_IS_VALID(field))
1729
ErrPostEx(SEV_INFO,ERR_BadParam,SUB_DocField,
1730
"DocField value (%d) out of range ",field);
1736
static FILE * CdEntrez_FileOpen (CdEntrezDir dirnum, int doctype, int divnum,
1737
int ftype, const char *fname, const char *fmode)
1739
static int cdnum[CDVOL_MAX];
1745
ASSERT(dirnum >= CdDir_FIRST && dirnum <= CdDir_LAST);
1746
ASSERT(doctype < _type_ct);
1747
ASSERT(divnum <= _div_ct);
1751
map = &_map[dirnum];
1752
cdcnt = CdMap_GetSpecs(map,cdnum,fpath);
1753
if ((map = CdMap_GetChild(map,doctype)) != NULL)
1755
cdcnt = CdMap_GetSpecs(map,cdnum,fpath);
1756
if ((map = CdMap_GetChild(map,divnum)) != NULL)
1758
cdcnt = CdMap_GetSpecs(map,cdnum,fpath);
1762
if (fpath[0] != '\0' && fpath[0] != '#')
1764
FileBuildPath(fpath,NULL,(char*)fname);
1765
fd = FileOpen(fpath,fmode);
1776
ASSERT(VOLNUM_IS_VALID(n));
1777
cdvol = &_cdvol[n-1];
1781
/* If the information sought exists on more than one volume, select
1782
a mounted volume if possible. Favor most-recently-used volumes. */
1786
for (i=0, cdvol=NULL; i<cdcnt; ++i)
1789
ASSERT(VOLNUM_IS_VALID(n));
1790
cdv = & _cdvol[n-1];
1793
else if (!CdVolume_IsMounted(cdvol) && CdVolume_IsMounted(cdv))
1795
else if (cdv->timestamp > cdvol->timestamp)
1799
ASSERT(cdvol != NULL);
1801
if ((cddev=cdvol->device) ==NULL)
1803
if ((cddev=CdVolume_Mount(cdvol,NULL,TRUE)) ==NULL)
1805
VERBOSE(" * CdVolume_Mount failed\n");
1809
fd = CdDevice_FileOpen(cddev,_dir[dirnum].dir,fname,fmode);
1818
unsigned short m[4];
1820
if (FileReadSwapShort(m,4,fd) != 4)
1826
fseek(fd,0,SEEK_SET);
1827
/**VERBOSE("HEADER %s: %d %d %d %d\n",fname,m[0],m[1],m[2],m[3]);**/
1829
if (m[0] && m[0] != _finfo[ftype].magic)
1831
else if (m[1] && m[1] > _finfo[ftype].format)
1832
FileNotRecognized(fname);
1833
else if (m[2] && m[2] != (unsigned short) _cdinfo->version)
1834
FileOutOfDate(fname);
1835
else if (m[3] && m[3] != (unsigned short) _cdinfo->issue && ftype != HCA)
1836
FileOutOfDate(fname);
1846
static void CdEntrez_FileClose (CdEntrezDir dirnum, int doctype, FILE *fd)
1849
/************ NOT IMPLEMENTED *************/
1852
/* This function will close some files and leave others
1853
open depending on whether the device on which they
1854
reside is ejectable or not. Right now it just closes
1863
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
1864
/* UidIndex Functions. Schuler 06-13-94 */
1865
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
1866
#define UIDX_KEY(a,b) (((unsigned long)(a) << 24) | (b))
1869
static UidIndex* UidIndex_Construct (UidIndex *uidx, DocType type, EntrezTypeData *info)
1874
uidx->uid_ct = info->num_uids;
1875
uidx->uid_min = info->minuid;
1876
uidx->uid_max = info->maxuid;
1877
uidx->pages = info->num_bucket;
1884
static UidIndex* UidIndex_Destruct (UidIndex *uidx)
1887
MemFree((void*)uidx->index);
1893
static int UidIndex_ReadPageMap (UidIndex *uidx)
1899
ASSERT(uidx != NULL);
1900
ASSERT(TYPE_IS_VALID(uidx->type));
1901
ASSERT(uidx->index == NULL);
1903
if ((index = (long*) MemNew(sizeof(long) * uidx->pages)) ==NULL)
1906
sprintf(fname,"%s.oix",TYPTAG(uidx->type));
1907
if ((fd = CdEntrez_FileOpen(CdDir_idx,uidx->type,0,OIX,fname,"rb")) ==NULL)
1909
fseek(fd,8,SEEK_SET); /* to skip over header */
1910
if (FileReadSwapLong((unsigned long*)index,uidx->pages,fd) != uidx->pages)
1911
return CatastrophicFailure(1);
1913
uidx->index = index;
1918
static long* UidIndex_ReadPage (UidIndex *uidx, int pagenum)
1926
ASSERT(uidx != NULL);
1927
ASSERT(pagenum < uidx->pages && pagenum >= 0);
1929
/*----- open file, check magic value, version, etc -----*/
1930
sprintf(fname,"%s.ofs",TYPTAG(uidx->type));
1931
if ((fd = CdEntrez_FileOpen(CdDir_idx,uidx->type,0,OFS,fname,"rb")) ==NULL)
1933
fseek(fd,8,SEEK_SET); /* to skip over header */
1935
/*----- seek to the right position, allocate memory, read the page -----*/
1936
if (fseek(fd,(long)pagenum*_idx_page_size,SEEK_CUR) != 0)
1937
return (long*)CatastrophicFailure(1);
1938
recs = (pagenum < uidx->pages-1) ? _idx_page_slots :
1939
(int)(uidx->uid_ct - (long)pagenum*_idx_page_slots);
1941
bytes = vals * sizeof(long);
1942
if ((page = MemGet(bytes,MGET_ERRPOST)) ==NULL)
1944
if (FileReadSwapLong((unsigned long*)page,vals,fd) != vals)
1945
return (long*)CatastrophicFailure(1);
1951
static int UidIndex_Lookup (UidIndex *uidx, DocUid uid, UidIndexRec *rec)
1954
int page_num, page_slots;
1955
unsigned long cache_key;
1957
Boolean missed =FALSE;
1959
ASSERT(rec != NULL);
1960
memset((void*)rec,0,sizeof(UidIndexRec));
1962
if (uid < uidx->uid_min || uid > uidx->uid_max)
1965
/*----- load the index, if necessary -----*/
1966
if (uidx->index == NULL)
1968
if (!UidIndex_ReadPageMap(uidx))
1972
/*----- binary search the index -----*/
1974
hi = (int)uidx->pages -1;
1978
p = uidx->index + mid;
1986
page_num = (uid < *p && mid >0) ? mid-1 : mid;
1987
page_slots = (page_num < uidx->pages -1) ? _idx_page_slots :
1988
(int)(uidx->uid_ct - (long)page_num * _idx_page_slots);
1991
/*----- check to see if desired page is in cache -----*/
1992
cache_key = UIDX_KEY(uidx->type,page_num);
1993
page = (long*) Cache_Lock(_idx_cache,cache_key);
1997
if ((page = UidIndex_ReadPage(uidx,page_num)) ==NULL)
1999
if (!Cache_Insert(_idx_cache,cache_key,page))
2000
return CatastrophicFailure(1);
2004
/*----- Binary search the page using the uid as a key -----*/
2015
rec->divnum = (short) ((*p & 0x0FFF0000) >>16);
2016
rec->filnum = (short) (*p++ & 0x0000FFFF);
2017
rec->hca_offset = *p++;
2018
rec->sum_offset = *p++;
2019
rec->lnk_offset = *p;
2028
Cache_Unlock(_idx_cache,cache_key);
2029
return (rec->uid != 0);
2033
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2034
/* TrmIndex Functions. Schuler 07-02-94 */
2035
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2036
#define TIDX_KEY(a,b,c) (((unsigned long)(a) << 24) | ((unsigned long)(b) << 16) | (c))
2037
#define T_HEAD_SIZE 16
2040
static TrmIndex* TrmIndex_Construct (TrmIndex *tidx, int type, int fld,
2041
const char *tag, EntrezFieldData *info)
2047
strcpy(tidx->tag,tag);
2048
tidx->trm_ct = info->num_terms;
2049
tidx->page_ct = info->num_bucket;
2055
static TrmIndex* TrmIndex_Destruct (TrmIndex *tidx)
2059
char **p = tidx->index;
2063
for (i=0; i<tidx->page_ct; ++i, ++p)
2065
MemFree((void*)tidx->index);
2073
static int TrmIndex_ReadPageMap (TrmIndex *tidx)
2076
unsigned short m[8];
2081
ASSERT(tidx != NULL);
2082
ASSERT(tidx->index == NULL);
2084
sprintf(fname,"%s%s.tix",TYPTAG(tidx->type),FLDTAG(tidx->fld));
2085
if ((fd = CdEntrez_FileOpen(CdDir_trm,tidx->type,0,TIX,fname,"rb")) ==NULL)
2087
FileReadSwapShort(m,8,fd);
2088
tidx->page_size = (m[4]==0) ? _trm_page_size : m[4];
2089
if ((tidx->index = (char**) MemNew(sizeof(char*) * tidx->page_ct)) !=NULL)
2091
for (i=0, p=tidx->index; i<tidx->page_ct; ++i, ++p)
2093
if ((*p = FileReadStr(fd,1)) ==NULL)
2095
TrmIndex_Destruct(tidx);
2101
return (tidx->index != NULL);
2105
static Byte* TrmIndex_ReadPage (TrmIndex *tidx, int pagenum)
2112
ASSERT(tidx != NULL);
2113
ASSERT(pagenum < tidx->page_ct);
2115
sprintf(fname,"%s%s.trm",TYPTAG(tidx->type),FLDTAG(tidx->fld));
2116
if ((fd = CdEntrez_FileOpen(CdDir_trm,tidx->type,0,TRM,fname,"rb")) ==NULL)
2118
offset = (long)T_HEAD_SIZE + (long)tidx->page_size * pagenum;
2119
VERIFY(fseek(fd,offset,SEEK_SET) ==0);
2121
page = MemGet(tidx->page_size+1, MGET_ERRPOST);
2124
size_t n = fread((void*)page,1,tidx->page_size,fd); /*check for error*/
2125
*(page+n) = '\0'; /* sentinel */
2134
static int TrmIndex_Lookup (TrmIndex *tidx, const char *stem)
2136
int lo, hi, mid, len, d;
2140
ASSERT(stem != NULL);
2143
/*----- load the index, if necessary -----*/
2144
if (tidx->index == NULL)
2146
if (!TrmIndex_ReadPageMap(tidx))
2150
/*----- binary search the index -----*/
2152
hi = (int)tidx->page_ct -1;
2156
term = *(tidx->index + mid);
2157
d = trmncmp(stem,term,len);
2166
for ( ; d <= 0 && mid >0; --mid)
2168
if (d==0 && len == (int)strlen(term))
2170
term = *(tidx->index + (mid-1));
2171
d = trmncmp(stem,term,len);
2177
static CdTerm* TrmIndex_GetCdTerm (TrmIndex *tidx, const char *term)
2182
ASSERT(tidx != NULL);
2184
if ((page_num = TrmIndex_Lookup(tidx,term)) >=0)
2186
unsigned long cache_key = TIDX_KEY(tidx->type,tidx->fld,page_num);
2187
Byte *page = Cache_Lock(_trm_cache,cache_key);
2194
page = TrmIndex_ReadPage(tidx,page_num);
2198
Byte *ptr = page +1;
2201
while ((flags = *ptr++) != 0)
2204
d = trmcmp(term,(char*)ptr);
2208
trm = getcdtrm(tidx,page_num,&ptr);
2212
if (flags & 0x01) ptr +=4;
2213
if (flags & 0x02) ptr +=4;
2218
Cache_Insert(_trm_cache,cache_key,page);
2220
Cache_Unlock(_trm_cache,cache_key);
2227
static int TrmIndex_ScanPages (TrmIndex *tidx, int start, int count, CdTermProc proc)
2229
int page_num = start;
2233
/*----- load the index, if necessary -----*/
2234
if (tidx->index == NULL)
2236
if (!TrmIndex_ReadPageMap(tidx))
2240
for (ct=0; ct<count && page_num<tidx->page_ct && !cancel; ++ct, ++page_num)
2242
unsigned long cache_key = TIDX_KEY(tidx->type,tidx->fld,page_num);
2243
Byte *page = Cache_Lock(_trm_cache,cache_key);
2250
page = TrmIndex_ReadPage(tidx,page_num);
2254
Byte *ptr = page +1;
2256
while ((trm = getcdtrm(tidx,page_num,&ptr)) != NULL)
2266
Cache_Insert(_trm_cache,cache_key,page);
2268
Cache_Unlock(_trm_cache,cache_key);
2274
static FILE * TrmIndex_PostingsFileOpen (TrmIndex *tidx)
2279
ASSERT(tidx != NULL);
2281
sprintf(fname,"%s%s.pst",TYPTAG(tidx->type),FLDTAG(tidx->fld));
2282
if ((fd = CdEntrez_FileOpen(CdDir_trm,tidx->type,0,PST,fname,"rb")) ==NULL)
2288
#define DECODE_LONG(ptr,val) { int i; \
2289
for (i=0, val = 0; i<4; ++i) \
2290
{ val <<= 8; val |= (unsigned long)*ptr++; } }
2293
static CdTerm* getcdtrm (TrmIndex *tidx, int pagenum, Byte **pptr)
2301
char *str = MemGet(1+len,MGET_ERRPOST);
2302
if (str!=NULL && (trm = MemNew(sizeof(CdTerm))) != NULL)
2306
ASSERT((flags & 0xF0) ==0xE0);
2307
trm->type = tidx->type;
2308
trm->field = tidx->fld;
2309
trm->page = pagenum;
2311
for (i=0; i<len; ++i)
2312
*str++ = (char) *ptr++;
2317
DECODE_LONG(ptr,val);
2318
trm->total_count = (long)val;
2322
DECODE_LONG(ptr,val);
2323
trm->special_count = (long)val;
2325
DECODE_LONG(ptr,val);
2326
trm->offset = (long)val;
2334
static int trmcmp (const char *term1, const char *term2)
2336
const char *p1 = term1;
2337
const char *p2 = term2;
2343
if (isalpha(c1)) c1 = tolower(c1);
2345
if (isalpha(c2)) c2 = tolower(c2);
2349
return (c2 == '/') ? 0 : -1;
2355
return ((int)*p1 - (int)*p2);
2358
static int trmncmp (const char *term1, const char *term2, int n)
2360
const char *p1 = term1;
2361
const char *p2 = term2;
2367
if (isalpha(c1)) c1=tolower(c1);
2369
if (isalpha(c2)) c2=tolower(c2);
2370
if (c1==0 || c2==0 || c1!=c2)
2376
return (c2 == '/') ? 0 : -1;
2384
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2385
/* CdVolume Functions. Schuler 05-21-94 */
2386
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2388
static CdVolume* CdVolume_Construct (CdVolume *cdvol, int number)
2396
sprintf(volname,"entrez%d",number);
2397
cdvol->volume_name = StrSave(volname);
2398
cdvol->volume_num = number;
2399
for (i=0, cddev=_cddev; i<_device_ct; ++i, ++cddev)
2401
if (cddev->bound_cd == number)
2403
CdVolume_Mount(cdvol,cddev,TRUE);
2406
if (cddev->hint == number)
2409
CdVolume_Mount(cdvol,cddev,FALSE);
2418
static CdVolume* CdVolume_Destruct (CdVolume *cdvol)
2422
MemFree((void*)cdvol->volume_name);
2423
cdvol->volume_name = NULL;
2430
static CdDevice* GetLruDevice (void)
2432
CdDevice *dev_lru =NULL;
2437
for (i=0, dev=_cddev; i<_device_ct; ++i, ++dev)
2439
if (dev->is_ejectable)
2441
if (dev->volume == NULL)
2446
if (dev_lru == NULL || dev->timestamp < time_lru)
2449
time_lru = dev->timestamp;
2453
if (dev_lru != NULL && dev_lru->volume != NULL)
2455
CdVolume *vol_to_eject = dev_lru->volume;
2456
CdVolume_Unmount(dev_lru->volume);
2457
if (dev_lru->is_ejectable)
2459
if (!(*_hookEject)(vol_to_eject->volume_name,&dev_lru->inf))
2460
ErrPostEx(SEV_INFO,0,0,"Unable to eject %s",vol_to_eject->volume_name);
2467
static CdDevice* CdVolume_Mount (CdVolume *cdvol, CdDevice *cddev, int verify)
2469
ASSERT(cdvol != NULL);
2473
cddev = GetLruDevice();
2474
ASSERT(cddev != NULL);
2475
ASSERT(cddev->volume == NULL);
2478
if (!cddev->is_ejectable)
2480
if (cdvol->device != NULL)
2482
ErrPostEx(SEV_INFO,0,0,"CdVolume_Mount; Device busy");
2485
if (!cddev->is_inited)
2487
if (!CdDevice_Init(cddev)) return NULL;
2489
cdvol->device = cddev;
2490
cddev->volume = cdvol;
2494
while (cdvol->device == NULL)
2498
if (! (*_hookInsert)(cdvol->volume_name,&cddev->inf))
2502
if (!cddev->is_inited)
2504
if (CdDevice_Init(cddev) && cddev->hint == cdvol->volume_num)
2506
cdvol->device = cddev;
2507
cddev->volume = cdvol;
2514
if (cddev->inf.root == NULL)
2517
strcpy(fpath,cddev->inf.root);
2518
if (cddev->ins_volname)
2519
FileBuildPath(fpath,cdvol->volume_name,NULL);
2520
if (!CdTestPath(fpath,&info))
2522
ErrLogPrintf("CdTestPath [%s] FAILED\n",fpath);
2523
ErrPostEx(SEV_INFO,0,0,"Unable to get CD-ROM volume info");
2527
/*ErrLogPrintf("CdTestPath [%s] OK; rel %d.%d; cd %d of %d\n", fpath,
2528
info.rel_major, info.rel_minor, info.cd_num, info.cd_count);*/
2529
cddev->upper_case = info.upper_case;
2530
cddev->semicolon_one = info.semicolon_one;
2531
if (info.rel_major != _rel_major || info.rel_minor != _rel_minor)
2532
ErrPostEx(SEV_INFO,0,0,"The inserted CD-ROM is from the wrong release");
2533
else if (cdvol->volume_num == info.cd_num)
2535
cdvol->device = cddev;
2536
cddev->volume = cdvol;
2539
if (cdvol->device == NULL && cddev->is_ejectable)
2541
char volume_to_eject[32];
2542
volume_to_eject[0] = '\0';
2543
if (cddev->ins_volname)
2545
int ct, freecds[CDVOL_MAX];
2546
ct = FindFloatingEntrezVolumes(freecds);
2548
sprintf(volume_to_eject,"entrez%d",freecds[0]);
2550
else if (cdvol->volume_name != NULL)
2551
strcpy(volume_to_eject,cdvol->volume_name);
2553
if (!(*_hookEject)(volume_to_eject,&cddev->inf))
2554
ErrPostEx(SEV_INFO,0,0,"Unable to eject %s",cdvol->volume_name);
2559
cdvol->device = cddev;
2560
cddev->volume = cdvol;
2564
CdDevice_Touch(cdvol->device);
2565
return cdvol->device;
2569
static int CdVolume_Unmount (CdVolume *cdvol)
2573
ASSERT(cdvol != NULL);
2575
cddev=cdvol->device;
2576
if (cddev != NULL && cddev->is_ejectable)
2578
cddev->volume = NULL;
2579
cdvol->device = NULL;
2580
CdDevice_Touch(cddev);
2587
static int CdVolume_IsMounted (CdVolume *cdvol)
2589
ASSERT(cdvol != NULL);
2590
return cdvol->device != NULL;
2594
static int FindFloatingEntrezVolumes (int *outlist)
2600
for (i=0; i<_volume_ct; ++i)
2602
if (_cdvol[i].device == NULL)
2604
sprintf(testpath,"entrez%d",i+1);
2605
if (CdTestPath(testpath,&info))
2607
VERBOSE("FindFloatingEntrezVolumes: Entrez%d found\n",info.cd_num);
2608
outlist[ct++] = info.cd_num;
2617
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2618
/* CdDevice Functions Schuler 05-21-94 */
2619
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2621
static CdDevice* CdDevice_Construct (CdDevice *cddev, int number)
2628
sprintf(section,"CdEntrez.Device.%d",number);
2629
cddev->inf.root = GetAppParamStr(_rcfile,section,"Root",NULL);
2630
cddev->inf.formal_name = GetAppParamStr(_rcfile,section,"Formal_Name",NULL);
2631
cddev->inf.device_name = GetAppParamStr(_rcfile,section,"Device_Name",NULL);
2632
cddev->inf.raw_device_name = GetAppParamStr(_rcfile,section,"Raw_Device_Name",NULL);
2633
cddev->inf.mount_point = GetAppParamStr(_rcfile,section,"Mount_Point",NULL);
2634
cddev->inf.mount_cmd = GetAppParamStr(_rcfile,section,"Mount_Cmd",NULL);
2635
cddev->is_ejectable = GetAppParamBoolean(_rcfile,section,"Ejectable",TRUE);
2636
cddev->ins_volname = GetAppParamBoolean(_rcfile,section,"Insert_Volname",FALSE);
2638
if (GetAppParam(_rcfile,section,"Bind",NULL,buffer,sizeof buffer))
2640
if (StrNICmp(buffer,"entrez",6) ==0)
2641
cddev->bound_cd = atoi(buffer+6);
2647
static CdDevice* CdDevice_Destruct (CdDevice *cddev)
2651
MemFree((void*)cddev->inf.root);
2652
MemFree((void*)cddev->inf.formal_name);
2653
MemFree((void*)cddev->inf.device_name);
2654
MemFree((void*)cddev->inf.raw_device_name);
2655
MemFree((void*)cddev->inf.mount_point);
2656
MemFree((void*)cddev->inf.mount_cmd);
2662
static int CdDevice_FileBuildPath (CdDevice *cddev, char *fpath, const char *fdir, const char *fname)
2664
ASSERT(cddev != NULL);
2665
ASSERT(fpath != NULL);
2668
if (cddev->is_inited)
2672
if (cddev->inf.root != NULL)
2673
strcpy(fpath,cddev->inf.root);
2674
if (cddev->ins_volname)
2678
if (cddev->volume != NULL)
2679
strncat(volname,cddev->volume->volume_name,sizeof volname);
2681
sprintf(volname,"entrez%d",cddev->hint);
2682
if (!FileBuildPath(fpath,volname,NULL))
2685
VERIFY(p = strchr(fpath,'\0'));
2686
if (!FileBuildPath(fpath,(char*)fdir,(char*)fname))
2688
if (cddev->upper_case)
2690
if (cddev->semicolon_one)
2698
static FILE * CdDevice_FileOpen (CdDevice *cddev, const char *fdir, const char *fname, const char *fmode)
2705
ASSERT(cddev != NULL);
2707
if (cddev->volume == NULL)
2710
if (!cddev->is_inited)
2712
if (!CdDevice_Init(cddev))
2715
if (cddev->inf.root == NULL)
2718
strcpy(fpath,cddev->inf.root);
2719
if (cddev->ins_volname)
2720
FileBuildPath(fpath,cddev->volume->volume_name,NULL);
2722
strcpy(lname,fname);
2723
if (cddev->upper_case)
2728
FileBuildPath(fpath,ldir,lname);
2729
if (cddev->semicolon_one)
2731
if ((fd = FileOpen(fpath,fmode)) != NULL)
2732
CdDevice_Touch(cddev);
2737
static int CdDevice_Init (CdDevice *cddev)
2743
ASSERT(cddev != NULL);
2744
if (cddev->is_inited)
2747
cd_num = cddev->bound_cd;
2748
memset((void*)&info,0,sizeof info);
2750
if (cddev->inf.root !=NULL)
2751
strncat(fpath,cddev->inf.root,sizeof fpath);
2753
if (cddev->ins_volname)
2756
if (cddev->bound_cd !=0)
2758
sprintf(volname,"entrez%d",cddev->bound_cd);
2759
FileBuildPath(fpath,volname,NULL);
2763
int vol_ct = (_volume_ct ==0) ? 3 : _volume_ct;
2765
for (j=0; j<vol_ct; ++j)
2768
if (cddev->inf.root !=NULL)
2769
strncat(fpath,cddev->inf.root,sizeof fpath);
2770
sprintf(volname,"entrez%d",j+1);
2771
FileBuildPath(fpath,volname,NULL);
2772
if (CdTestPath(fpath,&info))
2778
if (info.cd_num == 0)
2780
if (!(CdTestPath(fpath,&info)))
2784
cddev->upper_case = info.upper_case;
2785
cddev->semicolon_one = info.semicolon_one;
2786
cddev->hint = info.cd_num;
2787
cddev->is_inited = TRUE;
2788
CdDevice_Touch(cddev);
2793
static void CdDevice_Touch (CdDevice *cddev)
2795
time_t timestamp = time(NULL);
2796
ASSERT(cddev != NULL);
2797
cddev->timestamp = timestamp;
2798
if (cddev->volume != NULL)
2799
cddev->volume->timestamp = timestamp;
2803
static int LIBCALLBACK default_CdInsertProc (const char *volname, const CdDevInfo *dev)
2807
ASSERT(volname != NULL);
2808
ASSERT(dev != NULL);
2810
sprintf(msg,"Please insert volume \"%s\"",volname);
2811
if (dev->formal_name)
2812
sprintf(strchr(msg,0)," into %s",dev->formal_name);
2813
if (MsgAlert(KEY_OKC,SEV_INFO,GetProgramName(),msg) == ANS_CANCEL)
2815
if (dev->mount_cmd != NULL)
2817
return MountCd((char*)volname, dev->device_name,
2818
dev->mount_point, dev->mount_cmd);
2824
static int LIBCALLBACK default_CdEjectProc (const char *volname, const CdDevInfo *dev)
2826
return EjectCd((char*)volname, dev->device_name,
2827
dev->raw_device_name, dev->mount_point, dev->mount_cmd);
2832
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2833
/* CdMap Schuler 7-29-94 */
2834
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
2836
static CdMap* CdMap_Construct (CdMap *map, int array_size)
2840
map->array_size = (short)array_size;
2842
map->list = (CdMap*) MemNew((size_t)array_size * sizeof(CdMap));
2847
static CdMap* CdMap_Destruct (CdMap *map)
2855
for (m=map->list; m; m=m2)
2865
for (i=0, m=map->list; i<map->array_size; ++i, ++m)
2867
MemFree((void*)map->list);
2869
MemFree((void*)map->cd_list);
2870
MemFree((void*)map->user_path);
2871
memset((void*)map,0,sizeof(CdMap));
2877
static void CdMap_ParseCdNums (CdMap *map, char *nums)
2881
char *p, *p2 = nums;
2883
ASSERT(map != NULL);
2884
ASSERT(nums != NULL);
2886
while ((p = p2) != NULL)
2888
if ((p2 = strpbrk(p,",\10")) != NULL)
2891
ASSERT(VOLNUM_IS_VALID(cd));
2892
cd_list[n++] = (short) cd;
2897
map->multicd = TRUE;
2899
map->cd_list = (short*) MemGet(n*sizeof(short),MGET_ERRPOST);
2900
ASSERT(map->cd_list != NULL);
2901
memcpy((void*)map->cd_list,(void*)cd_list,n*sizeof(short));
2905
map->multicd = FALSE;
2906
map->cd_num = cd_list[0];
2907
map->cd_list = NULL;
2912
static CdMap* CdMap_GetChild (CdMap *map, int nkid)
2914
ASSERT(map != NULL);
2919
for (m2=map->list; m2; m2=m2->list)
2921
if (m2->id_num == nkid)
2925
else if (map->list != NULL)
2927
return &(map->list[nkid]);
2933
static int CdMap_GetSpecs (CdMap *map, int *cdlist, char *fdir)
2937
ASSERT(map != NULL);
2938
ASSERT(cdlist != NULL);
2939
ASSERT(fdir != NULL);
2941
if (map->user_path != NULL)
2942
strcpy(fdir,map->user_path);
2944
if (map->cd_num != 0)
2949
count = map->cd_num;
2950
ASSERT(map->cd_num < CDVOL_MAX);
2951
for (i=0; i<count; ++i)
2953
cdlist[i] = map->cd_list[i];
2959
*cdlist = map->cd_num;
2966
static void CdMap_FindPath (CdMap *map, const char *key)
2969
if (FindPath(_rcfile,"CdEntrez.Paths",(char*)key,fpath,sizeof fpath))
2971
map->user_set = TRUE;
2972
map->user_path = StrSave(fpath);
2979
static Boolean ReadCdLayout (FILE *fd)
2982
char line[64], key[32];
2985
for (dir=CdDir_FIRST; dir<=CdDir_LAST; ++dir)
2987
CdMap_FindPath(&_map[dir],_dir[dir].key);
2988
if (dir == CdDir_sys)
2989
CdMap_Construct(&_map[dir],0);
2992
CdMap_Construct(&_map[dir],_type_ct);
2993
for (i=0; i<_type_ct; ++i)
2995
CdMap_Construct(&_map[dir].list[i],0);
2996
sprintf(key,"%s-%s",_dir[dir].key,TYPTAG(i));
2997
CdMap_FindPath(&_map[dir].list[i],key);
3002
while (UnixFileGets(line,sizeof line,fd))
3004
if (isalpha(line[0]))
3009
VERIFY((pn = strchr(line,'\t')) != NULL);
3010
*pn++ = '\0'; /* pn points to the number(s) */
3012
if ((pt = strchr(line,'-')) != NULL)
3013
*pt++ = '\0'; /* pt points to the type tag */
3015
for (dir=CdDir_FIRST; dir<=CdDir_LAST; ++dir)
3017
if (strcmp(line,_dir[dir].key)==0)
3020
ASSERT(dir <= CdDir_LAST);
3025
if ((pd = strchr(pt,'-')) != NULL)
3026
*pd++ = '\0'; /* pd points to the division tag */
3028
for (i=0; i<_type_ct; ++i)
3030
if (strcmp(pt,TYPTAG(i)) ==0)
3033
ASSERT(i < _type_ct);
3034
map = &(map->list[i]);
3038
/* lookup division tag */
3039
for (j=0; j<_div_ct; ++j)
3041
if (strcmp(pd,DIVTAG(j)) ==0)
3044
ASSERT(j < _div_ct);
3045
if (_cdinfo->div_info[j].docs[i] != 0)
3049
/* create node and link into list */
3050
map->lnklist = TRUE;
3053
m2->list = map->list;
3056
sprintf(key,"%s-%s-%s",_dir[dir].key,TYPTAG(i),DIVTAG(j));
3057
CdMap_FindPath(map,key);
3061
CdMap_ParseCdNums(map,pn);
3065
if (_map[CdDir_sys].cd_num == 0)
3067
/* The list of filenames and filesizes for the sysinfo directory
3068
was inadvertently omitted from the cdlayout.inf file on the
3069
sample CD-ROMs distributed to developers. This section of
3070
code should never be executed in the final release. */
3072
VERBOSE(" HACK (faking cdlayout.inf information for SYSINFO directory)\n");
3073
_map[CdDir_sys].cd_list = (short*) MemNew(_volume_ct * sizeof(short));
3074
for (i=0; i<_volume_ct; ++i)
3076
_map[CdDir_sys].cd_list[i] = i +1;
3078
_map[CdDir_sys].cd_num = _volume_ct;
3079
_map[CdDir_sys].multicd = TRUE;
3086
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3087
/* LSet (similar to LinkSet) Schuler 06-01-94 */
3088
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3091
static LSet* LSet_Construct (LSet *lset, short sorc_type, short dest_type, int link_max)
3095
lset->link = (DocLink*) Malloc(FLUFF*sizeof(DocLink));
3096
if (lset->link == NULL)
3098
MemFree((void*)lset);
3101
lset->slots = FLUFF;
3102
lset->sorc_type = sorc_type;
3103
lset->dest_type = dest_type;
3104
lset->link_max = link_max;
3109
static LSet * LSet_Destruct (LSet *lset)
3112
Free((void*)lset->link);
3117
static int LSet_Read (LSet *lset, FILE *fd)
3119
unsigned short m[TYPE_MAX];
3121
int link_ct, max_ct;
3123
DocLink *link, *p1, *p2, *p3;
3125
ASSERT(lset != NULL);
3127
ASSERT(link != NULL);
3129
/* read the link counts */
3130
FileReadSwapShort(m,_type_ct,fd);
3131
link_ct = m[lset->dest_type];
3132
max_ct = MIN(lset->link_max,lset->count+link_ct);
3134
/* grow the array, if necessary */
3135
if (max_ct > lset->slots)
3137
int cd3_slots = max_ct + FLUFF;
3138
size_t bytes = sizeof(DocLink) * cd3_slots;
3139
void *array = Realloc((void*)link,bytes);
3142
ErrPostEx(SEV_FATAL,0,0,"Out of memory");
3145
lset->link = link = (DocLink*)array;
3146
lset->slots = max_ct + FLUFF;
3149
/* skip over link lists for other types that preceed this one */
3150
for (i=0; i<lset->dest_type; ++i)
3152
fseek(fd,4*m[i],SEEK_CUR);
3153
if (i==lset->sorc_type)
3154
fseek(fd,m[i],SEEK_CUR);
3157
/* process links, one at a time */
3158
for (i=0; i<link_ct; ++i)
3160
/* read next link from the file */
3161
/* NEED TO CHECK FOR ERROR HERE! */
3162
FileReadSwapInt4((Uint4*)&uid,1,fd);
3163
wt = (lset->sorc_type == lset->dest_type) ? fgetc(fd) : 1;
3164
if (lset->count == lset->link_max) continue;
3166
/* insert into array, keeping sorted by UID and summing weights */
3167
for (j=0, p1=link; j<lset->count; ++j, ++p1)
3173
p2 = link + lset->count;
3175
for (k=j; k<lset->count; ++k)
3180
if (j==lset->count || p1->uid != uid)
3191
static int LIBCALLBACK linkcmp (VoidPtr ptr1, VoidPtr ptr2);
3193
static int linkcmp (const void *ptr1, const void *ptr2);
3196
static LinkSet* LSet_Convert (LSet *lset)
3198
LinkSet *lnkset = NULL;
3199
ASSERT(lset != NULL);
3200
if ((lnkset = (LinkSet*) MemNew(sizeof(LinkSet))) != NULL)
3203
DocLink *p = lset->link;
3206
qsort((void*)p,lset->count,sizeof(DocLink),linkcmp);
3208
HeapSort ((VoidPtr) p,lset->count,sizeof(DocLink),linkcmp);
3209
lnkset->num = lset->count;
3210
lnkset->uids = (Int4*) MemGet(sizeof(Int4)*lset->count, MGET_ERRPOST);
3211
lnkset->weights = (Int4*) MemGet(sizeof(Int4)*lset->count, MGET_ERRPOST);
3212
for (i=0; i<lset->count; ++i, ++p)
3214
lnkset->uids[i] = p->uid;
3215
lnkset->weights[i] = p->wt;
3222
static int LIBCALLBACK linkcmp (VoidPtr ptr1, VoidPtr ptr2)
3224
static int linkcmp (const void *ptr1, const void *ptr2)
3227
DocLink *lnk1 = (DocLink*)ptr1;
3228
DocLink *lnk2 = (DocLink*)ptr2;
3231
if ((d = lnk2->wt - lnk1->wt) ==0)
3232
d = (lnk1->uid > lnk2->uid) ? -1 : 1;
3237
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3238
/* HuffTable Functions. Schuler 06-13-94 */
3239
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3241
static HuffTable* HuffTable_Construct (HuffTable *huff, int n)
3246
if ( ((huff->left = (short*)MemGet(sizeof(short)*n,MGET_ERRPOST)) != NULL)
3247
&& ((huff->right= (short*)MemGet(sizeof(short)*n,MGET_ERRPOST)) != NULL) )
3254
static HuffTable* HuffTable_Destruct (HuffTable *huff)
3258
MemFree((void*)huff->right);
3259
MemFree((void*)huff->left);
3260
memset((void*)huff,0,sizeof(HuffTable));
3265
static HuffTable* HuffTable_Read (FILE *fd)
3268
if (FileReadSwapShort((unsigned short*)&n,1,fd))
3270
HuffTable *huff = HuffTable_New(n);
3273
if ( (FileReadSwapShort((unsigned short*)huff->left,n,fd) == n)
3274
&& FileReadSwapShort((unsigned short*)huff->right,n,fd) == n )
3278
HuffTable_Free(huff);
3284
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3285
/* DecompInfo Functions Schuler 06-21-94 */
3286
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3288
static DecompInfo* DecompInfo_Construct (DecompInfo *info, HuffTable *huff)
3295
static AsnIo* DecompInfo_Attach (DecompInfo *info, FILE *fd)
3297
AsnIo *aio = AsnIoNew(ASNIO_BIN_IN,fd,info,DecompReadProc,NULL);
3307
static FILE* DecompInfo_Detach (DecompInfo *info)
3309
FILE *fd = info->fd;
3311
info->aio->fp = NULL;
3312
AsnIoClose(info->aio);
3317
static Int2 LIBCALLBACK DecompReadProc (void *opaque, char *buff, Uint2 count)
3319
DecompInfo *dcp = (DecompInfo*)opaque;
3320
register unsigned int mask = dcp->mask;
3321
register unsigned int byte = dcp->byte;
3326
FILE *fd1 = dcp->fd;
3327
int sentinel = dcp->huff->count;
3329
while (cnt < (int) count)
3335
if ((c = fgetc(fd1)) == EOF)
3337
/* should never reach this point */
3338
ErrPostEx(SEV_INFO,0,0,"Unexpected EOF");
3344
byte = (unsigned int) c;
3350
i = dcp->huff->left[i];
3352
i = dcp->huff->right[i];
3357
if ((k = i + 257) == sentinel)
3359
mask = 0; /* to skip remaining bits in current byte */
3372
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
3373
* CACHE FUNCTIONS. Schuler 05-17-94
3375
* Functions for caching arbitrary pages of data. Pages are uniquely
3376
* identified by a long integer.
3380
* -------- -------- ------------------------------------------------------
3381
* 06-01-94 Schuler Added new argument to Cache_New() that is a pointer to
3382
* a function to be called to free cached data items.
3384
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3386
static CachePage * Cache_FindPage (Cache *cache, long id, int *index);
3387
static void Cache_Delete_ByIndex (Cache *cache, int index);
3388
static void Cache_Touch_ByIndex (Cache *cache, int index);
3389
static int Cache_DeleteLRU (Cache *cache);
3391
#define Cache_ISVALID(x) ((x) != NULL && (x)->magic == Cache_MAGIC_VALUE )
3393
static int Cache_IsValid (Cache *cache)
3395
return Cache_ISVALID(cache);
3398
static void PASCAL DefCacheDataFreeProc (void *data)
3403
static Cache* Cache_Construct (Cache *cache, int slots, CacheDataFreeProc fproc)
3407
size_t bytes = (size_t)slots * sizeof(CachePage);
3408
CachePage *p = (CachePage*) MemGet(bytes,MGET_ERRPOST);
3415
cache->magic = Cache_MAGIC_VALUE;
3417
cache->page_slots = slots;
3418
cache->fproc = fproc;
3424
static Cache* Cache_Destruct (Cache *cache)
3429
CacheDataFreeProc fproc;
3431
ASSERT(Cache_ISVALID(cache));
3433
if ((fproc = cache->fproc) != NULL)
3435
for (i=0; i<cache->page_count; ++i)
3436
(*fproc)(cache->page[i].data);
3438
(void)MemFree((void*)cache->page);
3444
static CachePage * Cache_FindPage (Cache *cache, long id, int *index)
3446
CachePage *p = cache->page;
3448
for (i=0; i<cache->page_count; ++i, ++p)
3460
static int Cache_Insert (Cache *cache, long id, void *data)
3464
ASSERT(Cache_ISVALID(cache));
3466
if ((Cache_FindPage(cache,id,NULL)) != NULL)
3468
ErrPostEx(SEV_INFO,0,0,"Cache_Insert; Duplicate IDs");
3472
if (cache->page_count == cache->page_slots)
3474
if (!Cache_DeleteLRU(cache))
3476
ErrPostEx(SEV_INFO,0,0,"Cache_Insert; All pages locked");
3481
i = cache->page_count;
3482
cache->page[i].id = id;
3483
cache->page[i].lock = 0;
3484
cache->page[i].data = data;
3485
cache->page_count ++;
3487
Cache_Touch_ByIndex(cache,i);
3491
static void Cache_Delete_ByIndex (Cache *cache, int index)
3493
CacheDataFreeProc fproc = cache->fproc;
3494
CachePage temp = cache->page[index];
3496
cache->page_count--;
3497
for (i=index; i<cache->page_count; ++i)
3499
cache->page[i] = cache->page[i+1];
3502
(*fproc)(temp.data);
3506
static int Cache_Delete (Cache *cache, long id)
3509
ASSERT(Cache_ISVALID(cache));
3510
if (Cache_FindPage(cache,id,&index) != NULL)
3512
Cache_Delete_ByIndex(cache,index);
3519
static int Cache_DeleteLRU (Cache *cache)
3522
for (i=cache->page_count-1; i>=0; --i)
3524
if (cache->page[i].lock ==0)
3526
Cache_Delete_ByIndex(cache,i);
3534
static void* Cache_Lock (Cache *cache, long id)
3538
ASSERT(Cache_ISVALID(cache));
3539
if ((page = Cache_FindPage(cache,id,NULL)) != NULL)
3549
static int Cache_Unlock (Cache *cache, long id)
3554
ASSERT(Cache_ISVALID(cache));
3555
if ((page = Cache_FindPage(cache,id,&index)) != NULL)
3561
Cache_Touch_ByIndex(cache,index);
3564
ErrPostEx(SEV_INFO,0,0,"Cache_Unlock; Page(%ld) was not locked",id);
3569
static int Cache_Touch (Cache *cache, long id)
3572
ASSERT(Cache_ISVALID(cache));
3573
if (Cache_FindPage(cache,id,&index) != NULL)
3575
Cache_Touch_ByIndex(cache,index);
3581
static void Cache_Touch_ByIndex (Cache *cache, int index)
3583
CachePage temp = cache->page[index];
3585
for (i=index; i>0; --i)
3587
cache->page[i] = cache->page[i-1];
3589
cache->page[0] = temp;
3592
static void* Cache_Peek (Cache *cache, long id)
3596
ASSERT(Cache_ISVALID(cache));
3597
if ((page = Cache_FindPage(cache,id,NULL)) != NULL)
3605
static void Cache_Purge (Cache *cache)
3607
ASSERT(Cache_ISVALID(cache));
3609
while (Cache_DeleteLRU(cache))
3610
/* empty statement */ ;
3614
/**** get rid of this function! use Cache_ReportStats instead ****/
3615
static void Cache_LogStats (Cache *cache, const char *name)
3620
ASSERT(Cache_ISVALID(cache));
3621
total = cache->hits + cache->misses;
3622
pct1 = (total==0) ? 0 : (int)((cache->hits*100L)/total);
3623
pct2 = (total==0) ? 0 : (int)((cache->misses*100L)/total);
3625
VERBOSE("\n Cache Statistics: %s\n",name);
3626
VERBOSE(" %d slots, %d of them currently occupied\n",
3627
cache->page_slots, cache->page_count);
3628
VERBOSE(" %ld hits (%d%%)\n",cache->hits,pct1);
3629
VERBOSE(" %ld misses (%d%%)\n",cache->misses,pct2);
3630
VERBOSE(" %ld total access attempts\n", total);
3634
#define LONGDIV(x,y) (long)((0.5 + (double)(x)/(double)(y)))
3635
#define PERCENT(x,y) ((y)==0) ? 0 : (int)LONGDIV((x)*100L,(y))
3637
static char * Cache_ReportStats (Cache *cache, char *buffer)
3641
ASSERT(buffer != NULL);
3643
if (Cache_ISVALID(cache))
3645
long total = cache->hits + cache->misses;
3646
if (cache->page_size != 0)
3648
int kbytes_total, kbytes_used;
3649
kbytes_total = (int) LONGDIV(cache->page_size*cache->page_slots, KBYTE);
3650
sprintf(p=strchr(p,0)," cache memory: %5d K\n", kbytes_total);
3651
kbytes_used = (int) LONGDIV(cache->page_size*cache->page_count, KBYTE);
3652
sprintf(p=strchr(p,0)," memory in use: %5d K (%d%%)\n", kbytes_used,
3653
PERCENT(kbytes_used,kbytes_total));
3655
sprintf(p=strchr(p,0)," cache hits: %5ld (%d%%)\n",
3656
cache->hits, PERCENT(cache->hits,total));
3657
sprintf(p=strchr(p,0)," cache misses: %5ld (%d%%)\n",
3658
cache->misses, PERCENT(cache->misses,total));
3659
sprintf(p=strchr(p,0)," total attempts: %5ld\n",total);
3665
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3666
/* Error reporting functions */
3667
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3669
static int InvalidConfiguration (int code)
3671
#ifdef _OLD_CdEntrez_
3672
ErrSev sev = SEV_INFO;
3674
ErrSev sev = SEV_ERROR;
3676
ErrPostEx(sev,ERR_ConfigFile,code,"CdEntrez module is not configured correctly. "
3677
"Please run EntrezCf to correct the problem.");
3681
static int FileOutOfDate (const char *fname)
3683
ErrPostEx(SEV_ERROR,ERR_BadFile,SUB_BadVersion,
3684
"The file %s does not come from the expected "
3685
"Entrez version (%d.%d).",fname,_rel_major,_rel_minor);
3689
static int FileCorrupt (const char *fname)
3691
ErrPostEx(SEV_ERROR,ERR_BadFile,SUB_Corrupt,
3692
"The file %s appears to be corrupted",fname);
3696
static int FileNotRecognized (const char *fname)
3698
ErrPostEx(SEV_ERROR,ERR_BadFile,SUB_NeedUpdate,
3699
"The file %s cannot be read by this release of "
3700
"the software. Please obtain a newer version.", fname);
3704
static int CatastrophicFailure (int code)
3706
ErrPostEx(SEV_ERROR,ERR_DeepDooDoo,code,
3707
"Catastrophic Failure in CdEntrez module");
3712
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3713
/* Misc. Utility Functions. Schuler 05-16-94 */
3714
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
3716
static char * _GetAppParamStr (const char *filebase, const char *section,
3717
const char *key, const char *dflt)
3720
GetAppParam((char*)filebase,(char*)section,(char*)key,
3721
(char*)dflt,buffer,sizeof buffer);
3722
return buffer[0] ? StrSave(buffer) : NULL;
3726
static int FileReadSwapShort (unsigned short *buffer, int count, FILE *fd)
3729
if (sizeof(short) != 2)
3731
unsigned short *ptr, val;
3734
for (ptr=buffer, n=0; n<count; ++n)
3736
for (i=0, val=0; i<2; ++i)
3738
if ((c = fgetc(fd)) ==EOF)
3741
val |= (unsigned short)c;
3750
n = FileRead((void*)buffer,sizeof(short),count,fd);
3751
SwapUint2Buff(buffer,n);
3757
static int FileReadSwapLong (unsigned long *buffer, int count, FILE *fd)
3760
if (sizeof(long) != 4)
3762
unsigned long *ptr, val;
3765
for (ptr=buffer, n=0; n<count; ++n)
3767
for (i=0, val=0; i<4; ++i)
3769
if ((c = fgetc(fd)) ==EOF)
3772
val |= (unsigned long)c;
3781
n = FileRead((void*)buffer,sizeof(long),count,fd);
3782
SwapLongBuff(buffer,n);
3788
static int FileReadSwapInt4 (Uint4Ptr buffer, int count, FILE *fd)
3791
if (sizeof(Uint4) != 4)
3796
for (ptr=buffer, n=0; n<count; ++n)
3798
for (i=0, val=0; i<4; ++i)
3800
if ((c = fgetc(fd)) ==EOF)
3812
n = FileRead((void*)buffer,sizeof(Uint4),count,fd);
3813
SwapUint4Buff(buffer,n);
3819
static char * FileReadStr (FILE *fd, int lbyte)
3824
FileReadSwapShort(&len,1,fd);
3826
len = (unsigned short) fgetc(fd);
3830
char *str = MemGet(1+len,MGET_ERRPOST);
3833
if (fread(str,1,len,fd) != (size_t)len)
3835
MemFree((void*)str);
3836
ErrPostEx(SEV_INFO,0,0,"Unexpected EOF");