~ubuntu-branches/ubuntu/dapper/ncbi-tools6/dapper

« back to all changes in this revision

Viewing changes to cdromlib/cdconfig.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2002-04-04 22:13:09 UTC
  • Revision ID: james.westby@ubuntu.com-20020404221309-vfze028rfnlrldct
Tags: upstream-6.1.20011220a
ImportĀ upstreamĀ versionĀ 6.1.20011220a

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * ===========================================================================
 
3
 *
 
4
 *                             COPYRIGHT NOTICE
 
5
 *               National Center for Biotechnology Information
 
6
 *
 
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 Government employee and thus cannot
 
10
 *  be copyrighted.  This software/database is freely available to the
 
11
 *  public for use without a copyright notice.  Restrictions cannot be
 
12
 *  placed on its present or future use.
 
13
 *
 
14
 *  Although all reasonable efforts have been taken to ensure the accuracy
 
15
 *  and reliability of the software and data, the National Library of
 
16
 *  Medicine (NLM) and the U. S. Government do not and cannot warrant the
 
17
 *  performance or results that may be obtained by using this software or
 
18
 *  data.  The NLM and the U. S. Government disclaim all warranties as to
 
19
 *  performance, merchantability or fitness for any particular purpose.
 
20
 *
 
21
 *  Please see that the author is suitably cited in any work or product
 
22
 *  based on this material.
 
23
 *
 
24
 * ===========================================================================
 
25
 *
 
26
 * RCS $Id: cdconfig.c,v 6.1 1998/12/04 23:35:07 kans Exp $
 
27
 *
 
28
 * Author:   Jonathan Epstein
 
29
 * 
 
30
 * Version Creation Date:   11-92
 
31
 *
 
32
 * File Description: 
 
33
 *  Complex configuration mechanism used in conjunction with the low-level
 
34
 *  data access library for the Molecular Sequence Data CD-ROM library produced 
 
35
 *  by the NCBI.
 
36
 *
 
37
 * Modifications:  
 
38
 * --------------------------------------------------------------------------
 
39
 * Rev   Date      Name      Description of modification
 
40
 * ----  --------  --------  ------------------------------------------------
 
41
 * 1.17  08-22-94  Schuler   Fixed one function not returning a value
 
42
 *
 
43
 *
 
44
 * 05-19-95 Schuler     Added rcs Log directive for automatic insertion of
 
45
 *                      modification comments.
 
46
 *
 
47
 * Revision $Log: cdconfig.c,v $
 
48
 * Revision Revision 6.1  1998/12/04 23:35:07  kans
 
49
 * Revision KludgeCdromlibGetAppParam supplies ncbi config values for psrventr
 
50
 * Revision
 
51
 * Revision Revision 6.0  1997/08/25 18:12:45  madden
 
52
 * Revision Revision changed to 6.0
 
53
 * Revision
 
54
 * Revision Revision 5.1  1997/06/26 21:55:25  vakatov
 
55
 * Revision [PC] DLL'd "ncbicdr.lib", "ncbiacc.lib", "ncbinacc.lib" and "ncbicacc.lib"
 
56
 * Revision
 
57
 * Revision Revision 5.0  1996/05/28 13:55:34  ostell
 
58
 * Revision Set to revision 5.0
 
59
 * Revision
 
60
 * Revision 4.1  1995/08/24  20:44:01  epstein
 
61
 * add more stuff for genomes
 
62
 *
 
63
 * Revision 4.0  1995/07/26  13:50:32  ostell
 
64
 * force revision to 4.0
 
65
 *
 
66
 * Revision 1.22  1995/05/16  14:36:20  schuler
 
67
 * Automatic comment insertion enabled
 
68
 *
 
69
 *
 
70
 * ==========================================================================
 
71
 */
 
72
 
 
73
#define REVISION_STR  "$Revision: 6.1 $"
 
74
 
 
75
#include <ncbi.h>
 
76
#include <cdromlib.h>
 
77
 
 
78
/*****************************************************************************
 
79
*
 
80
*   Kludge to eliminate need for old entries in ncbi config file
 
81
*
 
82
*****************************************************************************/
 
83
 
 
84
static CharPtr kludgecdromstrings [] = {
 
85
  "ENTR_LINK.CHANNELS", "LINKS_FROM_NET",
 
86
  "ENTR_REF.CHANNELS", "REFERENCE_FROM_NET",
 
87
  "ENTR_SEQ.CHANNELS", "SEQUENCE_FROM_NET",
 
88
  "ENTREZ_NET.FORMAL_NAME", "",
 
89
  "ENTREZ_NET.RESOURCE_NAME", "Entrez",
 
90
  "ENTREZ_NET.RESOURCE_TYPE", "Entrez",
 
91
  "ENTREZ_NET.SERVICE_NAME", "Entrez",
 
92
  "ENTREZ_NET.TYPE", "NET",
 
93
  "LINKS_FROM_NET.ENTR_REF__ENTR_REF", "1",
 
94
  "LINKS_FROM_NET.ENTR_REF__ENTR_SEQ", "1",
 
95
  "LINKS_FROM_NET.ENTR_SEQ__ENTR_REF", "1",
 
96
  "LINKS_FROM_NET.ENTR_SEQ__ENTR_SEQ", "1",
 
97
  "LINKS_FROM_NET.INFO", "1",
 
98
  "LINKS_FROM_NET.MEDIA", "ENTREZ_NET",
 
99
  "NCBI.MEDIA", "ENTREZ_NET",
 
100
  "REFERENCE_FROM_NET.BOOLEANS", "1",
 
101
  "REFERENCE_FROM_NET.DOCSUMS", "1",
 
102
  "REFERENCE_FROM_NET.MEDIA", "ENTREZ_NET",
 
103
  "REFERENCE_FROM_NET.RECORDS", "1",
 
104
  "REFERENCE_FROM_NET.TERMS", "1",
 
105
  "SEQUENCE_FROM_NET.BOOLEANS", "1",
 
106
  "SEQUENCE_FROM_NET.DOCSUMS", "1",
 
107
  "SEQUENCE_FROM_NET.MEDIA", "ENTREZ_NET",
 
108
  "SEQUENCE_FROM_NET.RECORDS", "1",
 
109
  "SEQUENCE_FROM_NET.TERMS", "1",
 
110
  NULL, NULL
 
111
};
 
112
 
 
113
/*
 
114
#include <stdarg.h>
 
115
void CDECL   Nlm_WriteLog VPROTO((char *format, ...));
 
116
*/
 
117
 
 
118
static Int2 KludgeCdromlibGetAppParam (CharPtr file, CharPtr section, CharPtr type,
 
119
                                       CharPtr dflt, CharPtr buf, Int2 buflen)
 
120
 
 
121
{
 
122
  Int2  i;
 
123
  Char  str [256];
 
124
 
 
125
  if (buf == NULL || buflen < 1) return 0;
 
126
  *buf = '\0';
 
127
  if (dflt != NULL) {
 
128
    StringNCpy_0 (buf, dflt, buflen);
 
129
  }
 
130
  if (StringICmp (file, "NCBI") != 0) return 0;
 
131
  if (StringLen (section) > 127 || StringLen (type) > 127) return 0;
 
132
  StringCpy (str, section);
 
133
  StringCat (str, ".");
 
134
  StringCat (str, type);
 
135
  for (i = 0; kludgecdromstrings [i] != NULL; i += 2) {
 
136
    if (StringICmp (kludgecdromstrings [i], str) == 0) {
 
137
      StringNCpy_0 (buf, kludgecdromstrings [i + 1], buflen);
 
138
      return StringLen (buf);
 
139
    }
 
140
  }
 
141
  /*
 
142
  GetAppParam (file, section, type, dflt, buf, buflen);
 
143
  Nlm_WriteLog ("  \"%s.%s\", \"%s\",\n", section, type, buf);
 
144
  */
 
145
  return StringLen (buf);
 
146
}
 
147
 
 
148
/*  =========================================================================
 
149
 *      VARIABLES
 
150
 */
 
151
 
 
152
 
 
153
static MediaPtr CurMedia = NULL;
 
154
static MediaPtr LRUMediaList = NULL;
 
155
 
 
156
static MediaPtr MediaList = NULL;
 
157
static DrasticActionsPtr DrasticList = NULL;
 
158
static DataSourceDbPtr DataSourceDbList = NULL;
 
159
static DataSourceDbPtr CurDataSourceDb = NULL;
 
160
static int numcfginits = 0;
 
161
static EntrezInfoPtr MergedEntrezInfo = NULL;
 
162
static Boolean SoleMedia = FALSE;
 
163
 
 
164
static char * sCdConfError[] =
 
165
{
 
166
#ifdef WIN_MSWIN
 
167
    "No data source %Fs for section %Fs field %Fs"
 
168
#else
 
169
    "No data source %s for section %s field %s"
 
170
#endif
 
171
};
 
172
 
 
173
int _nouveau;
 
174
 
 
175
 
 
176
/*****************************************************************************
 
177
*
 
178
*   Private Function Prototypes
 
179
*
 
180
*****************************************************************************/
 
181
 
 
182
static void     FreeConfig                PROTO((void));
 
183
static Boolean  ChangeMedia               PROTO((MediaPtr newmedia));
 
184
static Boolean  IsDrasticAction           PROTO((MediaPtr fromMedia,
 
185
                                                MediaPtr toMedia));
 
186
static DataSourceDbPtr LoadDataSourceInfo PROTO((CharPtr section,
 
187
                                              CharPtr field1, CharPtr field2));
 
188
static void     MarkMRU                   PROTO((MediaPtr m));
 
189
static MediaPtr FindLRU                   PROTO((void));
 
190
static void     MarkLRUineligible         PROTO((MediaPtr media));
 
191
static void     UnMarkLRUineligible       PROTO((void));
 
192
static void     InitLRUeligibility        PROTO((Int2 mask));
 
193
static Boolean  AllCdDrivesAreFull        PROTO((void));
 
194
static Boolean  IsLiveMedia               PROTO((MediaPtr media));
 
195
 
 
196
 
 
197
 
 
198
/***************************************************************************
 
199
*
 
200
*   ConfigInit()
 
201
*
 
202
*
 
203
***************************************************************************/
 
204
 
 
205
NLM_EXTERN void ConfigInit(void)
 
206
{
 
207
    numcfginits++;
 
208
}
 
209
 
 
210
/***************************************************************************
 
211
*
 
212
*   ConfigFini()
 
213
*
 
214
*
 
215
***************************************************************************/
 
216
 
 
217
NLM_EXTERN void ConfigFini(void)
 
218
{
 
219
    if (numcfginits > 0)
 
220
        numcfginits--;
 
221
 
 
222
    if (numcfginits == 0)
 
223
        FreeConfig();
 
224
}
 
225
 
 
226
/***************************************************************************
 
227
*
 
228
*   LoadDataSourceInfo()
 
229
*
 
230
*   Called to load from the config file the information for a given
 
231
*   section/field1/field2 combination, e.g., "ENTR_LINK"/"ENTR_REF"/"ENTR_SEQ",
 
232
*   or "ENTR_REF"/"DOCSUMS"/NULL.
 
233
*
 
234
*   The resulting data is stored as a linked list, sorted by decreasing
 
235
*   priority. These "DataSourceDb" lists in turn are stored, in no particular
 
236
*   order, in a master list, headed by DataSourceDbList.
 
237
*
 
238
***************************************************************************/
 
239
 
 
240
static DataSourceDbPtr LoadDataSourceInfo (CharPtr section, CharPtr field1,
 
241
                                           CharPtr field2)
 
242
{
 
243
    DataSourceDbPtr dsdp;
 
244
    DataSourcePtr   dsp;
 
245
    char            channels[100];
 
246
    CharPtr         d1;
 
247
    CharPtr         d2;
 
248
    CharPtr         d3;
 
249
    CharPtr         d4;
 
250
    CharPtr         word;
 
251
    CharPtr         channel;
 
252
    Boolean         no_drastic_action;
 
253
    Boolean         done;
 
254
    DataSourcePtr   trailptr;
 
255
    char            buf[100];
 
256
    Int2            priority;
 
257
    MediaPtr        media;
 
258
    char            field[100];
 
259
    char            priostr[20];
 
260
 
 
261
    /* search the existing "data source database" to see if this entry is    */
 
262
    /* already loaded                                                        */
 
263
    for (dsdp = DataSourceDbList; dsdp != NULL; dsdp = dsdp->next)
 
264
    {
 
265
        if ((section != NULL || dsdp->key.section != NULL) &&
 
266
            StringCmp(section, dsdp->key.section) != 0)
 
267
            continue;
 
268
        if ((field1 != NULL || dsdp->key.field1 != NULL) &&
 
269
            StringCmp(field1, dsdp->key.field1) != 0)
 
270
            continue;
 
271
        if ((field2 != NULL || dsdp->key.field2 != NULL) &&
 
272
            StringCmp(field2, dsdp->key.field2) != 0)
 
273
            continue;
 
274
        
 
275
        /* already loaded */
 
276
        return dsdp;
 
277
    }
 
278
 
 
279
    if (KludgeCdromlibGetAppParam("NCBI", section, "CHANNELS", "", channels, 
 
280
                        sizeof(channels)) == 0)
 
281
    {
 
282
        return NULL; /* can't find CHANNELS keyword */
 
283
    }
 
284
 
 
285
    /* insert at head of DB list (for simplicity) */
 
286
    dsdp = (DataSourceDbPtr) MemNew(sizeof(DataSourceDb));
 
287
    dsdp->next = DataSourceDbList;
 
288
    DataSourceDbList = dsdp;
 
289
 
 
290
    dsdp->key.section = section == NULL ? NULL : StringSave(section);
 
291
    dsdp->key.field1 = field1 == NULL ? NULL : StringSave(field1);
 
292
 
 
293
    StrCpy(field, field1);
 
294
    if (field2 == NULL)
 
295
    { /* normal case */
 
296
        dsdp->key.field2 = NULL;
 
297
    }
 
298
    else { /* contraction of two fields */
 
299
        dsdp->key.field2 = StringSave(field2);
 
300
        StrCat(field, "__");
 
301
        StrCat(field, field2);
 
302
    }
 
303
 
 
304
    dsdp->list = NULL;
 
305
 
 
306
    d2 = channels;
 
307
    StrCat (d2, "\n");
 
308
    done = FALSE;
 
309
 
 
310
    /* Note that we don't use strtok() because it's not re-entrant */
 
311
    while ((d1 = StringPBrk(d2, ",\n\r")) != NULL && !done)
 
312
    {
 
313
        if (*d1 == '\n' || *d1 == '\r' || *d1 == '\0')
 
314
            done = TRUE;
 
315
        *d1 = '\0';
 
316
        word = d2;
 
317
        d2 = d1 + 1;
 
318
        d2 += StringSpn(d2, " \t"); /* remove leading spaces and tabs from next word */
 
319
        KludgeCdromlibGetAppParam("NCBI", word, field, field2 == NULL ? "1" : "0", buf, sizeof(buf));
 
320
        no_drastic_action = FALSE;
 
321
        
 
322
        /* Fields with field2 != NULL represent an NxN matrix of values; therefore,  */
 
323
        /* we default the priorities to 0, to avoid having to declare all NxN values */
 
324
        /* in the configuration file.                                                */
 
325
        if (field2 == NULL)
 
326
            priority = 1;
 
327
        else
 
328
            priority = 0;
 
329
        channel = StringSave(word);
 
330
 
 
331
        /* Parse the field which was just read, which contains a priority    */
 
332
        /* and may contain some other things as well.                        */
 
333
        d4 = buf;
 
334
        StrCat (d4, "\n");
 
335
        if ((d3 = StringPBrk(d4, ",\n\r")) != NULL)
 
336
        {
 
337
            *d3 = '\0';
 
338
            word = d4;
 
339
            d4 = d3 + 1;
 
340
            StrCpy(priostr, word); /* workaround for Windows */
 
341
            priority = atoi(priostr);
 
342
            d4 += StringSpn(d4, " \t"); /* remove leading spaces and tabs from next word */
 
343
            if (StrCmp(d4, "NO_DRASTIC_ACTION\n") == 0)
 
344
                no_drastic_action = TRUE;
 
345
        }
 
346
            
 
347
        if (KludgeCdromlibGetAppParam("NCBI", channel, "MEDIA", "", buf, sizeof(buf)) == 0)
 
348
        {
 
349
            return NULL; /* media not specified */
 
350
        }
 
351
        media = PreInitMedia(buf);
 
352
 
 
353
        /* override kludge for MEDIA; this enables a caller to make a     */
 
354
        /* particular CHANNEL active, without needing to know any of the  */
 
355
        /* names of the fields in that channel, except for "MEDIA"        */
 
356
        if (StrCmp(field, "MEDIA") == 0)
 
357
        {
 
358
            /* the really kludgy part of the kludge is to give preference to */
 
359
            /* network-based media; there's no good reason for this ... it   */
 
360
            /* just makes it possible to run the multi-CD/network combo      */
 
361
            /* version without ejecting CD-ROMs upon startup                 */
 
362
            if (media->media_type == MEDIUM_NETWORK)
 
363
                priority = 1;
 
364
            else
 
365
                priority = 0;
 
366
        }
 
367
 
 
368
        dsp = (DataSourcePtr) MemNew(sizeof(DataSource));
 
369
 
 
370
        /* order list by decreasing priorities */
 
371
        dsp->next = NULL;
 
372
        if (dsdp->list == NULL)
 
373
            dsdp->list = dsp;
 
374
        else {
 
375
            if (dsdp->list->next == NULL) /* one-element list */
 
376
            {
 
377
                if (dsdp->list->priority < priority)
 
378
                {
 
379
                    dsp->next = dsdp->list;
 
380
                    dsdp->list = dsp;
 
381
                }
 
382
                else { /* inserted element had lower priority; place at end of list */
 
383
                    dsdp->list->next = dsp;
 
384
                }
 
385
            }
 
386
            else {
 
387
                /* The "trailptr" points one element behind the element       */
 
388
                /* which is being examined, so that the new element can be    */
 
389
                /* inserted BEFORE the element with lower priority            */
 
390
                for (trailptr = dsdp->list; trailptr->next != NULL;
 
391
                     trailptr = trailptr->next)
 
392
                {
 
393
                    if (trailptr->next->priority < priority)
 
394
                    {
 
395
                        dsp->next = trailptr->next;
 
396
                        trailptr->next = dsp;
 
397
                        break;
 
398
                    }
 
399
                }
 
400
                if (trailptr->next == NULL) /* lowest priority in list */
 
401
                { /* insert at end */
 
402
                    trailptr->next = dsp;
 
403
                }
 
404
                    
 
405
            }
 
406
        }
 
407
 
 
408
        dsp->channel = channel;
 
409
        dsp->priority = priority;
 
410
        dsp->no_drastic_action = no_drastic_action;
 
411
        dsp->media = media;
 
412
    }
 
413
 
 
414
    return dsdp;
 
415
}
 
416
 
 
417
    
 
418
/***************************************************************************
 
419
*
 
420
*   SetSoleMedia()
 
421
*
 
422
*   For backwards-compatability with "old-style" configuration files,
 
423
*   we need the ability to specify a "sole media". A sole-media, by implication,
 
424
*   is the "valid" medium for all requested data sources, and should never
 
425
*   be ejected (if it is a CD-ROM, which is likely).
 
426
*
 
427
***************************************************************************/
 
428
 
 
429
NLM_EXTERN void SetSoleMedia(void)
 
430
{
 
431
    SoleMedia = TRUE;
 
432
}
 
433
 
 
434
 
 
435
/***************************************************************************
 
436
*
 
437
*   SelectDataSource()
 
438
*
 
439
*   Find a "data source" for the specified section/field1/field2 combination,
 
440
*   e.g., "ENTR_LINK"/"ENTR_REF"/"ENTR_SEQ", or "ENTR_REF"/"DOCSUMS"/NULL.
 
441
*
 
442
*   Returns TRUE if we are able to satisfy the request.
 
443
*
 
444
***************************************************************************/
 
445
 
 
446
NLM_EXTERN Boolean SelectDataSource (CharPtr section, CharPtr field1, CharPtr field2)
 
447
{
 
448
    DataSourceDbPtr dsdp;
 
449
    DataSourcePtr dsp;
 
450
    
 
451
#ifdef _NEW_CdEntrez_
 
452
        if (_nouveau)
 
453
                return TRUE;    /***** KLUDGE *****/
 
454
#endif
 
455
 
 
456
    /* for backwards compatability with "old-style" config files */
 
457
    if (SoleMedia)
 
458
    { /* use a single medium, rather than traversing a list */
 
459
        CurDataSourceDb = NULL;
 
460
        if (CurMedia == NULL)
 
461
        { /* no media yet initialized; so initialize it */
 
462
            if (MediaList != NULL)
 
463
            { /* MediaList points to single media entry */
 
464
                return ChangeMedia(MediaList);
 
465
            }
 
466
            return FALSE;
 
467
        }
 
468
        else { /* already set-up */
 
469
            return TRUE;
 
470
        }
 
471
    }
 
472
 
 
473
    if ((dsdp = LoadDataSourceInfo(section, field1, field2)) == NULL)
 
474
    {
 
475
        ErrPost (CTX_NCBICD, ERR_CD_NO_DATASRC, sCdConfError[0], "", section,
 
476
                 field1);
 
477
        CurDataSourceDb = NULL;
 
478
        return FALSE;
 
479
    }
 
480
 
 
481
    CurDataSourceDb = dsdp;
 
482
 
 
483
    if (dsdp->list == NULL)
 
484
    {
 
485
        ErrPost (CTX_NCBICD, ERR_CD_NO_DATASRC, sCdConfError[0], "list ",
 
486
                 section, field1);
 
487
        return FALSE;
 
488
    }
 
489
 
 
490
    /* Mark all entries as being "not yet searched", except for "invalid" */
 
491
    /* entries                                                            */
 
492
    for (dsp = dsdp->list; dsp != NULL; dsp = dsp->next)
 
493
    {
 
494
        dsp->already_searched = dsp->media == NULL || dsp->media->invalid;
 
495
    }
 
496
 
 
497
    return SelectNextDataSource();
 
498
}
 
499
 
 
500
/***************************************************************************
 
501
*
 
502
*   SelectDataSourceByType()
 
503
*                  *   A short-hand mechanism for selecting the appropriate SelectDataSource()
 
504
*   section.
 
505
*
 
506
****************************************************************************/
 
507
 
 
508
NLM_EXTERN Boolean SelectDataSourceByType (DocType type, CharPtr field1, CharPtr field2)
 
509
{
 
510
    CharPtr section;
 
511
 
 
512
#ifdef _NEW_CdEntrez_
 
513
        if (_nouveau)
 
514
                return TRUE;    /***** KLUDGE *****/
 
515
#endif
 
516
 
 
517
    switch (type) {
 
518
    case TYP_AA:
 
519
    case TYP_NT:
 
520
    case TYP_SEQ:
 
521
    case TYP_ST:
 
522
    case TYP_CH:
 
523
        section = ENTR_SEQ_CHAN;
 
524
        break;
 
525
    case TYP_ML:
 
526
        section = ENTR_REF_CHAN;
 
527
        break;
 
528
    default:
 
529
        return FALSE;
 
530
    }
 
531
 
 
532
    return SelectDataSource(section, field1, field2);
 
533
}
 
534
 
 
535
/***************************************************************************
 
536
*
 
537
*   SelectDataSourceByType()
 
538
*
 
539
*   A short-hand mechanism for specifying the SelectDataSource() arguments
 
540
*   for the "ENTR_LINK" section. Note that entries in the "ENTR_LINK" section
 
541
*   are specified by the "from-type" name, followed by two underscores, followed
 
542
*   by the "to-type" name.
 
543
*
 
544
****************************************************************************/
 
545
 
 
546
NLM_EXTERN Boolean SelectDataLinksByTypes (DocType type, DocType link_to_type)
 
547
{
 
548
    CharPtr field1;
 
549
    CharPtr field2;
 
550
 
 
551
#ifdef _NEW_CdEntrez_
 
552
        if (_nouveau)
 
553
                return TRUE;    /***** KLUDGE *****/
 
554
#endif
 
555
 
 
556
    switch (type) {
 
557
    case TYP_AA:
 
558
    case TYP_NT:
 
559
    case TYP_SEQ:
 
560
    case TYP_ST:
 
561
    case TYP_CH:
 
562
        field1 = ENTR_SEQ_CHAN;
 
563
        break;
 
564
    case TYP_ML:
 
565
        field1 = ENTR_REF_CHAN;
 
566
        break;
 
567
    default:
 
568
        return FALSE;
 
569
    }
 
570
 
 
571
    switch (link_to_type) {
 
572
    case TYP_AA:
 
573
    case TYP_NT:
 
574
    case TYP_SEQ:
 
575
    case TYP_ST:
 
576
    case TYP_CH:
 
577
        field2 = ENTR_SEQ_CHAN;
 
578
        break;
 
579
    case TYP_ML:
 
580
        field2 = ENTR_REF_CHAN;
 
581
        break;
 
582
    default:
 
583
        return FALSE;
 
584
    }
 
585
 
 
586
    return SelectDataSource(ENTR_LINKS_CHAN, field1, field2);
 
587
}
 
588
 
 
589
/***************************************************************************
 
590
*
 
591
*   SelectNextDataSource()
 
592
*
 
593
*   Called subsequent to SelectDataSource(), to find the next {or first,
 
594
*   when called by SelectDataSource()} available data source for the
 
595
*   previously selected section/field1/field2 combination.
 
596
*
 
597
****************************************************************************/
 
598
 
 
599
NLM_EXTERN Boolean SelectNextDataSource (void)
 
600
{
 
601
    DataSourceDbPtr dsdp = CurDataSourceDb;
 
602
    DataSourcePtr dsp;
 
603
    DataSourcePtr best_entry;
 
604
    DataSourcePtr best_on_live_media;
 
605
    
 
606
#ifdef _NEW_CdEntrez_
 
607
        if (_nouveau)
 
608
                return FALSE;    /***** KLUDGE *****/
 
609
#endif
 
610
 
 
611
    if (dsdp == NULL)
 
612
    { /* no current data source "database" */
 
613
        return FALSE;
 
614
    }
 
615
 
 
616
    /* loop forever (until return) */
 
617
    while (TRUE)
 
618
    {
 
619
        best_on_live_media = NULL;
 
620
        
 
621
        /* Try to find an entry associated with the current media, provided  */
 
622
        /* the current media is a live media (select the one which appears   */
 
623
        /* first in the list, and thus has the highest priority              */
 
624
        for (dsp = dsdp->list; dsp != NULL; dsp = dsp->next)
 
625
        {
 
626
            if (dsp->priority > 0 && !dsp->already_searched &&
 
627
                dsp->media == CurMedia && IsLiveMedia(dsp->media))
 
628
            {
 
629
                best_on_live_media = dsp;
 
630
                break;
 
631
            }
 
632
        }
 
633
    
 
634
        /* Try to find an entry associated with a live media (select         */
 
635
        /* the one which appears first in the list, and thus has the highest */
 
636
        /* priority).                                                        */
 
637
        for (dsp = dsdp->list; best_on_live_media == NULL && dsp != NULL;
 
638
             dsp = dsp->next)
 
639
        {
 
640
            if (dsp->priority > 0 && !dsp->already_searched &&
 
641
                IsLiveMedia(dsp->media))
 
642
            {
 
643
                best_on_live_media = dsp;
 
644
                break;
 
645
            }
 
646
        }
 
647
    
 
648
        /* Search for an entry with a higher priority than that associated   */
 
649
        /* with best_on_live_media, for which drastic-actions are not         */
 
650
        /* disallowed (unless switching to that media is not a "drastic      */
 
651
        /* action")                                                          */
 
652
        best_entry = best_on_live_media;
 
653
 
 
654
        for (dsp = dsdp->list; dsp != NULL && dsp->priority > 0; dsp = dsp->next)
 
655
        {
 
656
            if (dsp->already_searched)
 
657
                continue;
 
658
    
 
659
            if (best_on_live_media != NULL &&
 
660
                dsp->priority <= best_on_live_media->priority)
 
661
            {
 
662
                break; /* nothing found better than the "live" media */
 
663
            }
 
664
    
 
665
            if (!(dsp->no_drastic_action) || best_on_live_media == NULL ||
 
666
                !IsDrasticAction(CurMedia, dsp->media))
 
667
            { /* found a better medium */
 
668
                best_entry = dsp;
 
669
                break;
 
670
            }
 
671
        }
 
672
    
 
673
        if (best_entry == NULL)
 
674
        {
 
675
            return FALSE;
 
676
        }
 
677
    
 
678
        for (dsp = dsdp->list; dsp != NULL; dsp = dsp->next)
 
679
        { /* mark all entries associated with this media as "already searched" */
 
680
            if (dsp->media == best_entry->media)
 
681
                dsp->already_searched = TRUE;
 
682
        }
 
683
    
 
684
        if (best_entry->media != CurMedia)
 
685
        {
 
686
            if (ChangeMedia (best_entry->media))
 
687
                return TRUE;
 
688
        }
 
689
        else { /* the current Media was fine */
 
690
            return TRUE;
 
691
        }
 
692
    }
 
693
}
 
694
 
 
695
/***************************************************************************
 
696
*
 
697
*   FreeConfig()
 
698
*
 
699
*   Free and reset all configuration data. This should be used sparingly
 
700
*   since it resets all configuration information gathered to date.
 
701
*
 
702
****************************************************************************/
 
703
 
 
704
static void FreeConfig(void)
 
705
{
 
706
    MediaPtr mp, nextmp;
 
707
    DataSourceDbPtr dsdp, nextdsdp;
 
708
    DataSourcePtr dsp, nextdsp;
 
709
    DrasticActionsPtr dap, nextdap;
 
710
    CdMediaInfoPtr cmip;
 
711
    Int2 i;
 
712
 
 
713
    /* Free all the dynamically allocated lists of config data */
 
714
 
 
715
    for (mp = MediaList; mp != NULL; mp = nextmp)
 
716
    {
 
717
        MemFree(mp->media_alias);
 
718
        MemFree(mp->formal_name);
 
719
 
 
720
        if (mp != CurMedia)
 
721
        { /* CdFini()/NetFini() will take care of this for us for CurMedia */
 
722
            EntrezInfoFree(mp->entrez_info);
 
723
        }
 
724
 
 
725
        switch(mp->media_type) {
 
726
        case MEDIUM_CD:
 
727
        case MEDIUM_DISK:
 
728
            cmip = (CdMediaInfoPtr) mp->media_info;
 
729
 
 
730
            if (cmip == NULL)
 
731
                break;
 
732
            if (cmip->device_name != NULL)
 
733
                MemFree (cmip->device_name);
 
734
            if (cmip->mount_point != NULL)
 
735
                MemFree (cmip->mount_point);
 
736
            if (cmip->mount_cmd != NULL)
 
737
                MemFree (cmip->mount_cmd);
 
738
            if (mp != CurMedia)
 
739
            { /* CdFini() will take care of this for us for CurMedia */
 
740
                for (i = 0; i < NDIR; i++)
 
741
                {
 
742
                    if (cmip->sPath[i] != NULL)
 
743
                        MemFree(cmip->sPath[i]);
 
744
                }
 
745
            } else {
 
746
                /* to avoid future references to a freed data structure */
 
747
                CurMedia = NULL;
 
748
            }
 
749
 
 
750
            break;
 
751
        default:
 
752
            break;
 
753
        }
 
754
        MemFree(mp->media_info);
 
755
        nextmp = mp->next;
 
756
        MemFree(mp);
 
757
    }
 
758
 
 
759
    MediaList = NULL;
 
760
    CurMedia = NULL;
 
761
    LRUMediaList = NULL;
 
762
 
 
763
    for (dsdp = DataSourceDbList; dsdp != NULL; dsdp = nextdsdp)
 
764
    {
 
765
        MemFree(dsdp->key.section);
 
766
        MemFree(dsdp->key.field1);
 
767
        MemFree(dsdp->key.field2);
 
768
        /* Each DataSourceDbList entry references one or more DataSource */
 
769
        /* entries                                                       */
 
770
        for (dsp = dsdp->list; dsp != NULL; dsp = nextdsp)
 
771
        {
 
772
            MemFree(dsp->channel);
 
773
            nextdsp = dsp->next;
 
774
            MemFree(dsp);
 
775
        }
 
776
        nextdsdp = dsdp->next;
 
777
        MemFree(dsdp);
 
778
    }
 
779
 
 
780
    DataSourceDbList = NULL;
 
781
 
 
782
    for (dap = DrasticList; dap != NULL; dap = nextdap)
 
783
    {
 
784
        nextdap = dap->next;
 
785
        MemFree(dap);
 
786
    }
 
787
 
 
788
    DrasticList = NULL;
 
789
 
 
790
    if (MergedEntrezInfo != NULL)
 
791
        EntrezInfoFree (MergedEntrezInfo);
 
792
    MergedEntrezInfo = NULL;
 
793
    SoleMedia = FALSE;
 
794
}
 
795
 
 
796
/***************************************************************************
 
797
*
 
798
*   GetCurMedia()
 
799
*
 
800
*   Obtain the current media. Provided to allow the CurMedia variable to be
 
801
*   "hidden" within this file.
 
802
*
 
803
****************************************************************************/
 
804
 
 
805
NLM_EXTERN MediaPtr GetCurMedia (void)
 
806
{
 
807
    return CurMedia;
 
808
}
 
809
 
 
810
/***************************************************************************
 
811
*
 
812
*   CurMediaType()
 
813
*
 
814
*   Obtain the current media type, or MEDIUM_UNKNOWN, if the media type has
 
815
*   not yet been set.
 
816
*
 
817
****************************************************************************/
 
818
 
 
819
NLM_EXTERN Int2 CurMediaType (void)
 
820
{
 
821
 
 
822
#ifdef _NEW_CdEntrez_
 
823
        if (_nouveau)
 
824
                return MEDIUM_CD;    /***** KLUDGE *****/
 
825
#endif
 
826
 
 
827
 
 
828
    if (CurMedia == NULL)
 
829
        return MEDIUM_UNKNOWN;
 
830
 
 
831
    return CurMedia->media_type;
 
832
}
 
833
 
 
834
/***************************************************************************
 
835
*
 
836
*   SetCurMedia()
 
837
*
 
838
*   Set the current media. Provided to allow the CurMedia variable to be
 
839
*   "hidden" within this file. To be used cautiously.
 
840
*
 
841
****************************************************************************/
 
842
 
 
843
NLM_EXTERN MediaPtr SetCurMedia (MediaPtr NewMedia)
 
844
{
 
845
    CurMedia = NewMedia;
 
846
    return CurMedia;
 
847
}
 
848
 
 
849
/***************************************************************************
 
850
*
 
851
*   IsDrasticAction()
 
852
*
 
853
*   Used to see whether a switch between two media is considered to be a
 
854
*   "drastic action", i.e., something to be avoided. When it becomes known
 
855
*   whether a given switch is considered to be "drastic", that information
 
856
*   is stored in a linked list. Requests which cannot be satisfied from that
 
857
*   list are searched in the configuration file, and the results are 
 
858
*   subsequently stored in that list.
 
859
*
 
860
****************************************************************************/
 
861
 
 
862
static Boolean IsDrasticAction(MediaPtr fromMedia, MediaPtr toMedia)
 
863
{
 
864
    DrasticActionsPtr d;
 
865
    char drastic_to[60];
 
866
    char buf[10];
 
867
 
 
868
    /* First try to obtain "drastic" information from a cached list */
 
869
    for (d = DrasticList; d != NULL; d = d->next)
 
870
    {
 
871
        if (d->from_media == fromMedia && d->to_media == toMedia)
 
872
            return d->is_drastic;
 
873
    }
 
874
 
 
875
    /* If unable to find it on the cached list, search the config file */
 
876
    /* and then add the information to the cached list                 */
 
877
 
 
878
    StrCpy(drastic_to, "DRASTIC_TO_");
 
879
    StrCat(drastic_to, toMedia->media_alias);
 
880
 
 
881
    d = (DrasticActionsPtr) MemNew(sizeof(DrasticActions));
 
882
    d->from_media = fromMedia;
 
883
    d->to_media = toMedia;
 
884
    d->is_drastic = KludgeCdromlibGetAppParam("NCBI", fromMedia->media_alias, drastic_to,
 
885
                                     "", buf, sizeof(buf)) > 0;
 
886
    d->next = DrasticList;
 
887
    DrasticList = d;
 
888
    return d->is_drastic;
 
889
}
 
890
 
 
891
/***************************************************************************
 
892
*
 
893
*   ChangeMedia()
 
894
*
 
895
*   Make the specified media the "active" media. This requires "swapping out"
 
896
*   the old media, if one is active, and may require, e.g., ejecting a CD-ROM
 
897
*   to make room for a new one.
 
898
*
 
899
****************************************************************************/
 
900
 
 
901
static Boolean ChangeMedia(MediaPtr newMedia)
 
902
{
 
903
    if (newMedia == NULL)
 
904
        return FALSE;
 
905
 
 
906
    if (newMedia == CurMedia)
 
907
        return TRUE;
 
908
    
 
909
    if (CurMedia != NULL)
 
910
    {
 
911
        CurMedia->is_live = FALSE;
 
912
    }
 
913
 
 
914
    if (newMedia->media_type == MEDIUM_CD)
 
915
    {
 
916
        MediaPtr toBeEjected;
 
917
        CdMediaInfoPtr cdm;
 
918
        char msg[100];
 
919
        Int2 numTries = 0;
 
920
 
 
921
        InitLRUeligibility(MEDIUM_CD);
 
922
        /* the media which we want to be inserted is ineligible for ejection */
 
923
        MarkLRUineligible(newMedia);
 
924
 
 
925
        while (! CdIsInserted(newMedia))
 
926
        {
 
927
            if (numTries++ > 3)
 
928
                return FALSE;
 
929
            if (AllCdDrivesAreFull())
 
930
            {
 
931
                if ((toBeEjected = FindLRU()) != NULL)
 
932
                { /* it's the user's problem if there are none to be ejected */
 
933
                    MarkLRUineligible(toBeEjected);
 
934
                    if (toBeEjected->media_type == MEDIUM_CD &&
 
935
                        CdIsInserted(toBeEjected) &&
 
936
                        (cdm = (CdMediaInfoPtr) toBeEjected->media_info) !=
 
937
                        NULL)
 
938
                    {
 
939
                        if (toBeEjected->entrez_info != NULL)
 
940
                        {
 
941
                            EjectCd(toBeEjected->entrez_info->volume_label,
 
942
                                    cdm->device_name, cdm->raw_device_name,
 
943
                                    cdm->mount_point, cdm->mount_cmd);
 
944
                        }
 
945
                    }
 
946
                }
 
947
            }
 
948
 
 
949
            StrCpy (msg, "Please insert <");
 
950
            StrCat (msg, newMedia->formal_name);
 
951
            StrCat (msg, ">; select OK when ready");
 
952
            if (Message(MSG_OKC, msg) == ANS_CANCEL)
 
953
            {
 
954
                return FALSE;
 
955
            }
 
956
 
 
957
            if ((cdm = (CdMediaInfoPtr) newMedia->media_info) != NULL &&
 
958
                newMedia->entrez_info != NULL)
 
959
            {
 
960
                MountCd(newMedia->entrez_info->volume_label, cdm->device_name,
 
961
                        cdm->mount_point, cdm->mount_cmd);
 
962
            }
 
963
        }
 
964
    }
 
965
 
 
966
    if (CurMedia != NULL && CurMedia->swapOutMedia != NULL)
 
967
    {
 
968
        CurMedia->swapOutMedia(CurMedia);
 
969
    }
 
970
    if (newMedia->swapInMedia != NULL)
 
971
    {
 
972
        newMedia->swapInMedia(newMedia);
 
973
    }
 
974
    MarkMRU(newMedia);
 
975
 
 
976
    CurMedia = newMedia;
 
977
    CurMedia->is_live = TRUE;
 
978
    return TRUE;
 
979
}
 
980
 
 
981
/***************************************************************************
 
982
*
 
983
*   PreInitMedia()
 
984
*
 
985
*   Perform the pre-initialization of a media. This is the initialization which
 
986
*   which may be performed when, e.g., a Network Service is not yet available,
 
987
*   or a CD-ROM is not yet inserted into a CD-ROM drive. Subsequently 
 
988
*   initialization may be performed at a later time  when the media becomes
 
989
*   fully available.
 
990
*
 
991
****************************************************************************/
 
992
 
 
993
NLM_EXTERN MediaPtr PreInitMedia (CharPtr mediaName)
 
994
{
 
995
    char buf[80];
 
996
    MediaPtr m;
 
997
 
 
998
    for (m = MediaList; m != NULL; m = m->next)
 
999
    {
 
1000
        if (StrCmp(mediaName, m->media_alias) == 0)
 
1001
            return m; /* already have it */
 
1002
    }
 
1003
 
 
1004
    if (KludgeCdromlibGetAppParam("NCBI", mediaName, "TYPE", "", buf, sizeof(buf)) == 0 && !SoleMedia)
 
1005
        return NULL;
 
1006
 
 
1007
    m = (MediaPtr) MemNew(sizeof(Media));
 
1008
 
 
1009
    m->media_type = MEDIUM_UNKNOWN;
 
1010
    if (SoleMedia)
 
1011
        m->media_type = MEDIUM_DISK;
 
1012
        
 
1013
    if (StrCmp(buf, "CD") == 0)
 
1014
        m->media_type = MEDIUM_CD;
 
1015
    if (StrCmp(buf, "NET") == 0)
 
1016
        m->media_type = MEDIUM_NETWORK;
 
1017
    if (StrCmp(buf, "HARDDISK") == 0)
 
1018
        m->media_type = MEDIUM_DISK;
 
1019
    
 
1020
    if (KludgeCdromlibGetAppParam("NCBI", mediaName, "FORMAL_NAME", "", buf, sizeof(buf)) != 0)
 
1021
    {
 
1022
        m->formal_name = StringSave(buf);
 
1023
    }
 
1024
    else {
 
1025
        m->formal_name = StringSave(mediaName);
 
1026
    }
 
1027
    
 
1028
    m->inited_partial = FALSE;
 
1029
    m->inited_total = FALSE;
 
1030
    m->invalid = FALSE;
 
1031
    m->in_use = FALSE;
 
1032
    m->is_live = FALSE;
 
1033
    m->media_info = NULL;
 
1034
    m->swapOutMedia = NULL;
 
1035
    m->swapInMedia = NULL;
 
1036
    m->finiMedia = NULL;
 
1037
    m->media_alias = StringSave(mediaName);
 
1038
    m->next = MediaList;
 
1039
    m->LRUineligible = FALSE;
 
1040
    if (LRUMediaList == NULL)
 
1041
    { /* now a single element in the list */
 
1042
        m->next_lru = m;
 
1043
        m->prev_lru = m;
 
1044
    }
 
1045
    else { /* insert into double-linked circular list */
 
1046
        m->prev_lru = LRUMediaList->prev_lru;
 
1047
        m->next_lru = LRUMediaList;
 
1048
        LRUMediaList->prev_lru->next_lru = m;
 
1049
        LRUMediaList->prev_lru = m;
 
1050
    }
 
1051
    LRUMediaList = m;
 
1052
    MediaList = m;
 
1053
 
 
1054
    return m;
 
1055
}
 
1056
 
 
1057
/***************************************************************************
 
1058
*
 
1059
*   CdIsInserted()
 
1060
*
 
1061
*   Test to see whether the specified CD-ROM is currently inserted into a
 
1062
*   CD-ROM drive.
 
1063
*
 
1064
****************************************************************************/
 
1065
 
 
1066
NLM_EXTERN Boolean CdIsInserted(MediaPtr media)
 
1067
{
 
1068
    Boolean retval = FALSE;
 
1069
#ifdef _OLD_CdEntrez_
 
1070
    CdMediaInfoPtr cdm;
 
1071
    AsnIoPtr aip;
 
1072
    EntrezInfoPtr vi;
 
1073
    EntrezInfoPtr pre_init_vi;
 
1074
    ErrDesc err;
 
1075
    short erract;
 
1076
#endif
 
1077
 
 
1078
#ifdef _NEW_CdEntrez_
 
1079
        if (_nouveau)
 
1080
                retval = TRUE;    /***** KLUDGE *****/
 
1081
#endif
 
1082
 
 
1083
#ifdef _OLD_CdEntrez_
 
1084
    if (media == NULL)
 
1085
        return FALSE;
 
1086
    if (media->is_live)
 
1087
        return TRUE;
 
1088
    if ( (cdm = (CdMediaInfoPtr) media->media_info) == NULL)
 
1089
        return FALSE;
 
1090
    if ( (pre_init_vi = media->entrez_info) == NULL)
 
1091
        return FALSE;
 
1092
    
 
1093
    ErrGetOpts(&erract, NULL);
 
1094
    ErrSetOpts(ERR_IGNORE, 0);
 
1095
 
 
1096
    if ((aip = EntrezInfoOpen(cdm->sPath[DIR_ROOT])) != NULL)
 
1097
    {
 
1098
        vi = EntrezInfoAsnRead(aip, NULL);
 
1099
        AsnIoClose(aip);
 
1100
        if (vi != NULL)
 
1101
        {
 
1102
            if (StrCmp(vi->volume_label, pre_init_vi->volume_label) ==
 
1103
                0 &&
 
1104
                vi->version == pre_init_vi->version &&
 
1105
                vi->issue == pre_init_vi->issue &&
 
1106
                vi->format == pre_init_vi->format)
 
1107
                retval = TRUE;
 
1108
            EntrezInfoFree(vi);
 
1109
        }
 
1110
    }
 
1111
    else {
 
1112
        ErrFetch(&err); /* discard error */
 
1113
    }
 
1114
    
 
1115
    ErrSetOpts(erract, 0); /* restore previous error status */
 
1116
 
 
1117
#endif
 
1118
    return retval;
 
1119
}
 
1120
 
 
1121
/***************************************************************************
 
1122
*
 
1123
*   EntrezInfoMerge()
 
1124
*
 
1125
*   Perform an "optomistic merge" of all the available EntrezInfo data
 
1126
*   from the different known media. If there is only a single known medium,
 
1127
*   then this degrades to returning the EntrezInfo for that medium. Otherwise,
 
1128
*   the "type" entries with the maximum amount of sub-entries are selected.
 
1129
*
 
1130
****************************************************************************/
 
1131
 
 
1132
NLM_EXTERN  EntrezInfoPtr EntrezInfoMerge(void)
 
1133
{
 
1134
    EntrezInfoPtr new;
 
1135
    Int2 MaxTypes = 0;
 
1136
    MediaPtr mp;
 
1137
    Int2 i;
 
1138
    Int2 f;
 
1139
    EntrezInfoPtr cip;
 
1140
    EntrezInfoPtr InfoWithMaxTypes;
 
1141
    EntrezTypeDataPtr besttype;
 
1142
    Int4 count;
 
1143
    Int2 mediaCount = 0;
 
1144
 
 
1145
    /* first, find out how many types there are, and save a pointer to an */
 
1146
    /* entry which has that many types                                    */
 
1147
    for (mp = MediaList; mp != NULL; mp = mp->next)
 
1148
    {
 
1149
        if ( (cip = mp->entrez_info) == NULL)
 
1150
            continue;
 
1151
        mediaCount++;
 
1152
        if (cip->type_count <= MaxTypes)
 
1153
            continue;
 
1154
        MaxTypes = cip->type_count;
 
1155
        InfoWithMaxTypes = cip;
 
1156
    }
 
1157
 
 
1158
    if (MaxTypes == 0)
 
1159
        return NULL;
 
1160
 
 
1161
    if (MergedEntrezInfo != NULL)
 
1162
        EntrezInfoFree(MergedEntrezInfo);
 
1163
 
 
1164
    new = (EntrezInfoPtr) MemNew(sizeof(EntrezInfo));
 
1165
    MergedEntrezInfo = new;
 
1166
    new->volume_label = StringSave(InfoWithMaxTypes->volume_label);
 
1167
    new->version = InfoWithMaxTypes->version;
 
1168
    new->issue = InfoWithMaxTypes->issue;
 
1169
    new->format = InfoWithMaxTypes->format;
 
1170
    new->descr = StringSave(InfoWithMaxTypes->descr);
 
1171
 
 
1172
    /* there is no way to merge compression information if there is more than */
 
1173
    /* one medium                                                             */
 
1174
    if (mediaCount <= 1 && ! InfoWithMaxTypes->no_compression) {
 
1175
        new->no_compression = InfoWithMaxTypes->no_compression;
 
1176
        new->huff_count = InfoWithMaxTypes->huff_count;
 
1177
        new->huff_left = MemDup (InfoWithMaxTypes->huff_left,
 
1178
                                 sizeof(new->huff_left[0]) * new->huff_count);
 
1179
        new->huff_right = MemDup (InfoWithMaxTypes->huff_right,
 
1180
                                  sizeof(new->huff_right[0]) * new->huff_count);
 
1181
    } else {
 
1182
        new->no_compression = TRUE;
 
1183
        new->huff_count = 0;
 
1184
        new->huff_left = NULL;
 
1185
        new->huff_right = NULL;
 
1186
    }
 
1187
 
 
1188
    new->type_count = MaxTypes;
 
1189
    new->type_bucket_size = InfoWithMaxTypes->type_bucket_size;
 
1190
    new->field_count = InfoWithMaxTypes->field_count;
 
1191
    new->field_bucket_size = InfoWithMaxTypes->field_bucket_size;
 
1192
 
 
1193
    new->type_names = (CharPtr PNTR) MemNew(sizeof(CharPtr) * MaxTypes);
 
1194
    new->field_names = (CharPtr PNTR) MemNew(sizeof(CharPtr) *
 
1195
                        new->field_count);
 
1196
    new->types = (EntrezTypeDataPtr) MemNew(sizeof(EntrezTypeData) * MaxTypes);
 
1197
    if (InfoWithMaxTypes->type_info != NULL)
 
1198
    {
 
1199
        new->type_info = (EntrezTypeInfo PNTR) MemNew(sizeof(EntrezTypeInfo) * MaxTypes);
 
1200
    }
 
1201
    if (InfoWithMaxTypes->field_info != NULL)
 
1202
    {
 
1203
        new->field_info = (EntrezFieldInfo PNTR)
 
1204
                             MemNew(sizeof(EntrezFieldInfo) *
 
1205
                             InfoWithMaxTypes->field_count);
 
1206
    }
 
1207
 
 
1208
    for (i = 0; i < InfoWithMaxTypes->field_count; i++)
 
1209
    {
 
1210
        new->field_names[i] = StringSave(InfoWithMaxTypes->field_names[i]);
 
1211
        if (new->field_info != NULL)
 
1212
        {
 
1213
            new->field_info[i] = InfoWithMaxTypes->field_info[i];
 
1214
            new->field_info[i].name = StringSave(InfoWithMaxTypes->field_info[i].name);
 
1215
            new->field_info[i].descr = StringSave(InfoWithMaxTypes->field_info[i].descr);
 
1216
        }
 
1217
    }
 
1218
 
 
1219
    for (i = 0; i < MaxTypes; i++)
 
1220
    {
 
1221
        new->type_names[i] = StringSave(InfoWithMaxTypes->type_names[i]);
 
1222
        if (new->type_info != NULL)
 
1223
        {
 
1224
            new->type_info[i].id = InfoWithMaxTypes->type_info[i].id;
 
1225
            StrCpy(new->type_info[i].tag,InfoWithMaxTypes->type_info[i].tag);
 
1226
            new->type_info[i].name = StringSave(InfoWithMaxTypes->type_info[i].name);
 
1227
            new->type_info[i].descr = StringSave(InfoWithMaxTypes->type_info[i].descr);
 
1228
            new->type_info[i].asntype = StringSave(InfoWithMaxTypes->type_info[i].asntype);
 
1229
        }
 
1230
 
 
1231
        count = 0;
 
1232
 
 
1233
        /* for each "type", traverse the media list and find the "best" one */
 
1234
        for (mp = MediaList; mp != NULL; mp = mp->next)
 
1235
        {
 
1236
            if ( (cip = mp->entrez_info) == NULL)
 
1237
                continue;
 
1238
            if (cip->type_count < i)
 
1239
                continue;
 
1240
            if (cip->types[i].num < count)
 
1241
                continue;
 
1242
            /* the "best" type is the one with the most entries */
 
1243
            besttype = &(cip->types[i]);
 
1244
            count = besttype->num;
 
1245
        }
 
1246
        new->types[i].num = besttype->num;
 
1247
        new->types[i].num_uids = besttype->num_uids;
 
1248
        new->types[i].minuid = besttype->minuid;
 
1249
        new->types[i].maxuid = besttype->maxuid;
 
1250
        new->types[i].num_bucket = besttype->num_bucket;
 
1251
        new->types[i].fields = (EntrezFieldDataPtr) MemNew(
 
1252
                                sizeof(EntrezFieldData) *
 
1253
                                InfoWithMaxTypes->field_count);
 
1254
        for (f = 0; f < InfoWithMaxTypes->field_count; f++)
 
1255
        {
 
1256
            new->types[i].fields[f].num_terms =
 
1257
                                    besttype->fields[f].num_terms;
 
1258
            new->types[i].fields[f].num_bucket =
 
1259
                                    besttype->fields[f].num_bucket;
 
1260
        }
 
1261
 
 
1262
    }
 
1263
 
 
1264
    return new;
 
1265
}
 
1266
 
 
1267
/***************************************************************************
 
1268
*
 
1269
*   FindLRU()
 
1270
*
 
1271
*   Find the "least-recently-used" entry in a doubly-linked-queue of media,
 
1272
*   with the additional constraint that the selected medium may not be marked
 
1273
*   as "ineligible".
 
1274
*
 
1275
****************************************************************************/
 
1276
 
 
1277
static MediaPtr FindLRU(void)
 
1278
{
 
1279
    MediaPtr media;
 
1280
    
 
1281
    if (LRUMediaList == NULL)
 
1282
        return NULL;
 
1283
    
 
1284
    media = LRUMediaList;
 
1285
    
 
1286
    /* traverse media list, beginning with Least-Recently-Used, searching for an */
 
1287
    /* eligible candidate                                                        */
 
1288
    do {
 
1289
        media = media->prev_lru;
 
1290
        if (! media->LRUineligible)
 
1291
            return media;
 
1292
    } while (media != NULL && media != LRUMediaList);
 
1293
    
 
1294
    return NULL;
 
1295
}
 
1296
 
 
1297
/***************************************************************************
 
1298
*
 
1299
*   MarkLRUineligible()
 
1300
*
 
1301
*   Mark a medium as "ineligible" to be considered in a search for a
 
1302
*   least-recently-used medium.
 
1303
*
 
1304
****************************************************************************/
 
1305
 
 
1306
static void MarkLRUineligible(MediaPtr media)
 
1307
{
 
1308
    if (media != NULL)
 
1309
    {
 
1310
        media->LRUineligible = TRUE;
 
1311
    }
 
1312
}
 
1313
 
 
1314
/***************************************************************************
 
1315
*
 
1316
*   InitLRUeligibility()
 
1317
*
 
1318
*   Mark all media as not-"ineligible", i.e., eligible, to be considered
 
1319
*   in a search for the least-recently-used medium ... provided that they
 
1320
*   are of the specified media-type. All other media are ineligible.
 
1321
*
 
1322
****************************************************************************/
 
1323
 
 
1324
static void InitLRUeligibility(Int2 mask)
 
1325
{
 
1326
    MediaPtr m = LRUMediaList;
 
1327
 
 
1328
    if (m == NULL)
 
1329
        return;
 
1330
 
 
1331
    do {
 
1332
        if (m->media_type & mask)
 
1333
            m->LRUineligible = FALSE;
 
1334
        else
 
1335
            m->LRUineligible = TRUE;
 
1336
        m = m->next_lru;
 
1337
    } while (m != LRUMediaList);
 
1338
}
 
1339
 
 
1340
/***************************************************************************
 
1341
*
 
1342
*   MarkMRU()
 
1343
*
 
1344
*   Mark this medium as the "most-recently-used" by moving it to the
 
1345
*   head (or tail, depending upon how you look at it) of a doubly-linked
 
1346
*   queue.
 
1347
*
 
1348
****************************************************************************/
 
1349
 
 
1350
static void MarkMRU(MediaPtr m)
 
1351
{ /* mark this entry as most recently used by moving to head of Queue */
 
1352
 
 
1353
    if (m == NULL || LRUMediaList == NULL)
 
1354
        return;
 
1355
    
 
1356
    /* already Most-Recently-Used; and besides, the algorithm that follows  */
 
1357
    /* will produce spaghetti if m already points to the head of the queue  */
 
1358
    if (m == LRUMediaList)
 
1359
        return;
 
1360
 
 
1361
    /* delete entry from neighbors' links */
 
1362
    m->prev_lru->next_lru = m->next_lru;
 
1363
    m->next_lru->prev_lru = m->prev_lru;
 
1364
 
 
1365
    /* insert at beginning of list */
 
1366
    m->prev_lru = LRUMediaList->prev_lru;
 
1367
    m->next_lru = LRUMediaList;
 
1368
    LRUMediaList->prev_lru->next_lru = m;
 
1369
    LRUMediaList->prev_lru = m;
 
1370
    LRUMediaList = m;
 
1371
}
 
1372
 
 
1373
/***************************************************************************
 
1374
*
 
1375
*   AllCdDrivesAreFull()
 
1376
*
 
1377
*   Returns TRUE if all availabe CD-ROM drives are currently full. This
 
1378
*   should be done by searching the known CD-ROM drives for a "vacancy",
 
1379
*   but this is currently difficult to perform. 
 
1380
*
 
1381
****************************************************************************/
 
1382
 
 
1383
static Boolean AllCdDrivesAreFull(void)
 
1384
{ /* for now, be pessimistic */
 
1385
    return TRUE;
 
1386
}
 
1387
 
 
1388
/***************************************************************************
 
1389
*
 
1390
*   IsLiveMedia()
 
1391
*
 
1392
*   Indicates whether the specified media is "live". This means either,
 
1393
*   e.g., a currently inserted CD-ROM, or a currently active network service,
 
1394
*   etc.
 
1395
*
 
1396
****************************************************************************/
 
1397
 
 
1398
static Boolean  IsLiveMedia (MediaPtr media)
 
1399
{
 
1400
    if (media == NULL)
 
1401
        return FALSE;
 
1402
 
 
1403
    if (media->invalid)
 
1404
        return FALSE;
 
1405
 
 
1406
    if (media->media_type == MEDIUM_DISK)
 
1407
        return CdIsInserted(media);
 
1408
 
 
1409
    if (media->media_type == MEDIUM_CD)
 
1410
        return CdIsInserted(media);
 
1411
 
 
1412
    if (media->media_type == MEDIUM_NETWORK)
 
1413
        return TRUE;
 
1414
 
 
1415
    /* else */
 
1416
    return FALSE;
 
1417
}
 
1418
 
 
1419
NLM_EXTERN Int2 ParseMedia(ConfCtlProc initfunc, Int2 media_mask)
 
1420
{
 
1421
    char media[256];
 
1422
    CharPtr m1,m2;
 
1423
    CharPtr word;
 
1424
    Boolean done;
 
1425
    MediaPtr mp;
 
1426
    Int2 numProcessed = 0;
 
1427
 
 
1428
    KludgeCdromlibGetAppParam ("ncbi", "NCBI", "MEDIA", "", media, sizeof media);
 
1429
 
 
1430
    /* This is a work-around to provide backwards compatibility for old       */
 
1431
    /* config files which do not specify MEDIA                                */
 
1432
    if (media[0] == '\0')
 
1433
    {
 
1434
        StrCpy(media, "NCBI");
 
1435
        SetSoleMedia();
 
1436
    }
 
1437
 
 
1438
    m2 = media;
 
1439
    StrCat(m2, "\n");
 
1440
    done = FALSE;
 
1441
 
 
1442
    /* parse "MEDIA", looking for all data sources; note that we don't use */
 
1443
    /* strtok(), because it's not re-entrant                               */
 
1444
    while ((m1 = StringPBrk(m2, ",\n\r")) != NULL && !done)
 
1445
    {
 
1446
        if (*m1 == '\n' || *m1 == '\r' || *m1 == '\0')
 
1447
            done = TRUE;
 
1448
        *m1 = '\0';
 
1449
        word = m2;
 
1450
        m2 = m1 + 1;
 
1451
        m2 += StringSpn(m2, " \t"); /* remove leading spaces and tabs from next word */
 
1452
 
 
1453
        mp = PreInitMedia(word);
 
1454
        if (mp->media_type & media_mask)
 
1455
        {
 
1456
            if (initfunc != NULL)
 
1457
            {
 
1458
                if (initfunc(word))
 
1459
                {
 
1460
                    mp->in_use = TRUE;
 
1461
                    mp->invalid = FALSE;
 
1462
                    numProcessed++;
 
1463
                }
 
1464
            }
 
1465
            else {
 
1466
                mp->in_use = TRUE;
 
1467
                mp->invalid = FALSE;
 
1468
                numProcessed++;
 
1469
            }
 
1470
        }
 
1471
        else {
 
1472
            if (! mp->in_use)
 
1473
                mp->invalid = TRUE;
 
1474
        }
 
1475
    }
 
1476
 
 
1477
    return numProcessed;
 
1478
}