1 /*********************************************************************
2    Copyright 2010, UCAR/Unidata See netcdf/COPYRIGHT file for
3    copying and redistribution conditions.
4  *********************************************************************/
5 
6 #include "config.h"
7 #include <stdlib.h>
8 #include <string.h>
9 #include <assert.h>
10 #include "nc.h"
11 
12 #define ID_SHIFT (16)
13 #define NCFILELISTLENGTH 0x10000
14 
15 /* Version one just allocates the max space (sizeof(NC*)*2^16)*/
16 static NC** nc_filelist = NULL;
17 
18 static int numfiles = 0;
19 
20 /* Common */
21 int
count_NCList(void)22 count_NCList(void)
23 {
24     return numfiles;
25 }
26 
27 
28 void
free_NCList(void)29 free_NCList(void)
30 {
31     if(numfiles > 0) return; /* not empty */
32     if(nc_filelist != NULL) free(nc_filelist);
33     nc_filelist = NULL;
34 }
35 
36 int
add_to_NCList(NC * ncp)37 add_to_NCList(NC* ncp)
38 {
39     int i;
40     int new_id;
41     if(nc_filelist == NULL) {
42 	if (!(nc_filelist = calloc(1, sizeof(NC*)*NCFILELISTLENGTH)))
43 	    return NC_ENOMEM;
44 	numfiles = 0;
45     }
46 #ifdef USE_REFCOUNT
47     /* Check the refcount */
48     if(ncp->refcount > 0)
49 	return NC_NOERR;
50 #endif
51 
52     new_id = 0; /* id's begin at 1 */
53     for(i=1; i < NCFILELISTLENGTH; i++) {
54 	if(nc_filelist[i] == NULL) {new_id = i; break;}
55     }
56     if(new_id == 0) return NC_ENOMEM; /* no more slots */
57     nc_filelist[new_id] = ncp;
58     numfiles++;
59     new_id = (new_id << ID_SHIFT);
60     ncp->ext_ncid = new_id;
61     return NC_NOERR;
62 }
63 
64 void
del_from_NCList(NC * ncp)65 del_from_NCList(NC* ncp)
66 {
67    unsigned int ncid = ((unsigned int)ncp->ext_ncid) >> ID_SHIFT;
68    if(numfiles == 0 || ncid == 0 || nc_filelist == NULL) return;
69    if(nc_filelist[ncid] != ncp) return;
70 #ifdef USE_REFCOUNT
71    /* Check the refcount */
72    if(ncp->refcount > 0)
73 	return; /* assume caller has decrecmented */
74 #endif
75 
76    nc_filelist[ncid] = NULL;
77    numfiles--;
78 
79    /* If all files have been closed, release the filelist memory. */
80    if (numfiles == 0)
81       free_NCList();
82 }
83 
84 NC *
find_in_NCList(int ext_ncid)85 find_in_NCList(int ext_ncid)
86 {
87    NC* f = NULL;
88    unsigned int ncid = ((unsigned int)ext_ncid) >> ID_SHIFT;
89    if(numfiles > 0 && nc_filelist != NULL && ncid < NCFILELISTLENGTH)
90 	f = nc_filelist[ncid];
91    return f;
92 }
93 
94 /*
95 Added to support open by name
96 */
97 NC*
find_in_NCList_by_name(const char * path)98 find_in_NCList_by_name(const char* path)
99 {
100    int i;
101    NC* f = NULL;
102    if(nc_filelist == NULL)
103 	return NULL;
104    for(i=1; i < NCFILELISTLENGTH; i++) {
105 	if(nc_filelist[i] != NULL) {
106 	    if(strcmp(nc_filelist[i]->path,path)==0) {
107 		f = nc_filelist[i];
108 		break;
109 	    }
110 	}
111    }
112    return f;
113 }
114 
115 int
iterate_NCList(int index,NC ** ncp)116 iterate_NCList(int index, NC** ncp)
117 {
118     /* Walk from 0 ...; 0 return => stop */
119     if(index < 0 || index >= NCFILELISTLENGTH)
120 	return NC_ERANGE;
121     if(ncp) *ncp = nc_filelist[index];
122     return NC_NOERR;
123 }
124 
125