namespace.c 8.25 KB
Newer Older
Thomas Jahns's avatar
Thomas Jahns committed
1
2
3
4
5
6
7
8
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600 /* PTHREAD_MUTEX_RECURSIVE */
#endif

9
#include <limits.h>
10
#include <stdlib.h>
11
#include <stdio.h>
Thomas Jahns's avatar
Thomas Jahns committed
12

13
#include "cdi.h"
14
#include "dmemory.h"
15
#include "namespace.h"
Thomas Jahns's avatar
Thomas Jahns committed
16
#include "resource_handle.h"
17
#include "serialize.h"
Thomas Jahns's avatar
Thomas Jahns committed
18
#include "error.h"
19
#include "cdf_int.h"
20
#include "file.h"
21
#include "cdi_int.h"
Thomas Jahns's avatar
Thomas Jahns committed
22
#include "stream_cdf.h"
23

24
static unsigned nNamespaces = 1;
25
static int activeNamespace = 0;
26

27
#ifdef HAVE_LIBNETCDF
28
29
30
31
32
33
#define CDI_NETCDF_SWITCHES                     \
  { .func = (void (*)()) nc__create },          \
  { .func = (void (*)()) cdf_def_var_serial },  \
  { .func = (void (*)()) cdfDefTimestep },      \
  { .func = (void (*)()) cdfDefVars }

34
35
36
37
#else
#define CDI_NETCDF_SWITCHES
#endif

38
39
#define defaultSwitches {                                   \
    { .func = (void (*)()) cdiAbortC_serial },              \
40
    { .func = (void (*)()) cdiWarning },                    \
41
42
43
44
45
46
47
48
    { .func = (void (*)()) serializeGetSizeInCore },        \
    { .func = (void (*)()) serializePackInCore },           \
    { .func = (void (*)()) serializeUnpackInCore },         \
    { .func = (void (*)()) fileOpen_serial },               \
    { .func = (void (*)()) fileWrite },                     \
    { .func = (void (*)()) fileClose_serial },              \
    { .func = (void (*)()) cdiStreamOpenDefaultDelegate },  \
    { .func = (void (*)()) cdiStreamDefVlist_ },            \
49
    { .func = (void (*)()) cdiStreamSetupVlist_ },          \
50
    { .func = (void (*)()) cdiStreamWriteVar_ },            \
Thomas Jahns's avatar
Thomas Jahns committed
51
    { .func = (void (*)()) cdiStreamWriteVarChunk_ },       \
52
    { .func = (void (*)()) 0 },                             \
53
    { .func = (void (*)()) 0 },                             \
54
    { .func = (void (*)()) cdiStreamCloseDefaultDelegate }, \
Thomas Jahns's avatar
Thomas Jahns committed
55
    { .func = (void (*)()) cdiStreamDefTimestep_ }, \
56
57
58
    { .func = (void (*)()) cdiStreamSync_ },                \
    CDI_NETCDF_SWITCHES                        \
    }
59

60
#if defined (SX) || defined (__cplusplus)
61
62
static const union namespaceSwitchValue
  defaultSwitches_[NUM_NAMESPACE_SWITCH] = defaultSwitches;
63
#endif
64

65
static struct Namespace
66
{
Thomas Jahns's avatar
Thomas Jahns committed
67
  enum namespaceStatus resStage;
68
  union namespaceSwitchValue switches[NUM_NAMESPACE_SWITCH];
69
} initialNamespace = {
Thomas Jahns's avatar
Thomas Jahns committed
70
  .resStage = NAMESPACE_STATUS_INUSE,
71
72
  .switches = defaultSwitches
};
73

74
static struct Namespace *namespaces = &initialNamespace;
75

76
static unsigned namespacesSize = 1;
Thomas Jahns's avatar
Thomas Jahns committed
77
78
79
80

#if  defined  (HAVE_LIBPTHREAD)
#  include <pthread.h>

Thomas Jahns's avatar
Thomas Jahns committed
81
82
83
84
85
86
87
88
89
90
91
92
static pthread_once_t  namespaceOnce = PTHREAD_ONCE_INIT;
static pthread_mutex_t namespaceMutex;

static void
namespaceInitialize(void)
{
  pthread_mutexattr_t ma;
  pthread_mutexattr_init(&ma);
  pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(&namespaceMutex, &ma);
  pthread_mutexattr_destroy(&ma);
}
Thomas Jahns's avatar
Thomas Jahns committed
93
94
95

#  define NAMESPACE_LOCK()         pthread_mutex_lock(&namespaceMutex)
#  define NAMESPACE_UNLOCK()       pthread_mutex_unlock(&namespaceMutex)
Thomas Jahns's avatar
Thomas Jahns committed
96
97
98
#  define NAMESPACE_INIT()         pthread_once(&namespaceOnce, \
                                                namespaceInitialize)

Thomas Jahns's avatar
Thomas Jahns committed
99
100
101

#else

Thomas Jahns's avatar
Thomas Jahns committed
102
#  define NAMESPACE_INIT() do { } while (0)
Thomas Jahns's avatar
Thomas Jahns committed
103
104
105
106
107
108
#  define NAMESPACE_LOCK()
#  define NAMESPACE_UNLOCK()

#endif


109
110
111
enum {
  intbits = sizeof(int) * CHAR_BIT,
  nspbits = 4,
112
  idxbits = intbits - nspbits,
Thomas Jahns's avatar
Thomas Jahns committed
113
  nspmask = (int)((( (unsigned)1 << nspbits ) - 1) << idxbits),
Deike Kleberg's avatar
Deike Kleberg committed
114
  idxmask = ( 1 << idxbits ) - 1,
115
116
117
118
};

enum {
  NUM_NAMESPACES = 1 << nspbits,
119
  NUM_IDX = 1 << idxbits,
120
};
121

122
123
124

int namespaceIdxEncode ( namespaceTuple_t tin )
{
Deike Kleberg's avatar
Deike Kleberg committed
125
  xassert ( tin.nsp < NUM_NAMESPACES && tin.idx < NUM_IDX);
126
  return ( tin.nsp << idxbits ) + tin.idx;
127
}
128

129
int namespaceIdxEncode2 ( int nsp, int idx )
130
{
Deike Kleberg's avatar
Deike Kleberg committed
131
  xassert(nsp < NUM_NAMESPACES && idx < NUM_IDX);
132
133
134
  return ( nsp << idxbits ) + idx;
}

135

Deike Kleberg's avatar
Deike Kleberg committed
136
namespaceTuple_t namespaceResHDecode ( int resH )
137
138
139
{
  namespaceTuple_t tin;

Deike Kleberg's avatar
Deike Kleberg committed
140
141
  tin.idx = resH & idxmask;
  tin.nsp = (int)(((unsigned)( resH & nspmask )) >> idxbits);
142
143
144
145

  return tin;
}

Thomas Jahns's avatar
Thomas Jahns committed
146
int
147
namespaceNew()
148
{
Thomas Jahns's avatar
Thomas Jahns committed
149
  int newNamespaceID = -1;
Thomas Jahns's avatar
Thomas Jahns committed
150
  NAMESPACE_INIT();
Thomas Jahns's avatar
Thomas Jahns committed
151
152
  NAMESPACE_LOCK();
  if (namespacesSize > nNamespaces)
153
    {
Thomas Jahns's avatar
Thomas Jahns committed
154
      /* namespace is already available and only needs reinitialization */
155
      for (unsigned i = 0; i < namespacesSize; ++i)
Thomas Jahns's avatar
Thomas Jahns committed
156
        if (namespaces[i].resStage == NAMESPACE_STATUS_UNUSED)
Thomas Jahns's avatar
Thomas Jahns committed
157
          {
158
            newNamespaceID = (int)i;
Thomas Jahns's avatar
Thomas Jahns committed
159
160
            break;
          }
161
    }
Thomas Jahns's avatar
Thomas Jahns committed
162
163
164
  else if (namespacesSize == 1)
    {
      /* make room for additional namespace */
165
      struct Namespace *newNameSpaces
166
        = (struct Namespace *) Malloc(((size_t)namespacesSize + 1) * sizeof (namespaces[0]));
Thomas Jahns's avatar
Thomas Jahns committed
167
168
169
170
171
172
173
174
      memcpy(newNameSpaces, namespaces, sizeof (namespaces[0]));
      namespaces = newNameSpaces;
      ++namespacesSize;
      newNamespaceID = 1;
    }
  else if (namespacesSize < NUM_NAMESPACES)
    {
      /* make room for additional namespace */
175
      newNamespaceID = (int)namespacesSize;
176
      namespaces
177
        = (struct Namespace *) Realloc(namespaces, ((size_t)namespacesSize + 1) * sizeof (namespaces[0]));
Thomas Jahns's avatar
Thomas Jahns committed
178
179
180
181
182
183
184
185
186
      ++namespacesSize;
    }
  else /* implicit: namespacesSize >= NUM_NAMESPACES */
    {
      NAMESPACE_UNLOCK();
      return -1;
    }
  xassert(newNamespaceID >= 0 && newNamespaceID < NUM_NAMESPACES);
  ++nNamespaces;
Thomas Jahns's avatar
Thomas Jahns committed
187
188
  namespaces[newNamespaceID].resStage = NAMESPACE_STATUS_INUSE;
#if defined (SX) || defined (__cplusplus)
189
190
  memcpy(namespaces[newNamespaceID].switches,
         defaultSwitches_,
191
         sizeof (namespaces[newNamespaceID].switches));
Thomas Jahns's avatar
Thomas Jahns committed
192
#else
193
194
195
    memcpy(namespaces[newNamespaceID].switches,
           (union namespaceSwitchValue[NUM_NAMESPACE_SWITCH])defaultSwitches,
           sizeof (namespaces[newNamespaceID].switches));
Thomas Jahns's avatar
Thomas Jahns committed
196
#endif
Thomas Jahns's avatar
Thomas Jahns committed
197
198
199
  reshListCreate(newNamespaceID);
  NAMESPACE_UNLOCK();
  return newNamespaceID;
200
201
}

Thomas Jahns's avatar
Thomas Jahns committed
202
203
204
void
namespaceDelete(int namespaceID)
{
Thomas Jahns's avatar
Thomas Jahns committed
205
  NAMESPACE_INIT();
Thomas Jahns's avatar
Thomas Jahns committed
206
  NAMESPACE_LOCK();
207
208
  xassert(namespaceID >= 0 && (unsigned)namespaceID < namespacesSize
          && nNamespaces);
Thomas Jahns's avatar
Thomas Jahns committed
209
  reshListDestruct(namespaceID);
Thomas Jahns's avatar
Thomas Jahns committed
210
  namespaces[namespaceID].resStage = NAMESPACE_STATUS_UNUSED;
Thomas Jahns's avatar
Thomas Jahns committed
211
212
213
  --nNamespaces;
  NAMESPACE_UNLOCK();
}
214

215
216
int namespaceGetNumber ()
{
217
  return (int)nNamespaces;
218
219
220
}


221
void namespaceSetActive ( int nId )
222
{
223
  xassert((unsigned)nId < namespacesSize
Thomas Jahns's avatar
Thomas Jahns committed
224
          && namespaces[nId].resStage != NAMESPACE_STATUS_UNUSED);
225
226
227
  activeNamespace = nId;
}

228

229
230
231
232
int namespaceGetActive ()
{
  return activeNamespace;
}
233

234
int namespaceAdaptKey ( int originResH, int originNamespace )
235
236
237
238
{
  namespaceTuple_t tin;
  int nsp;

239
  if ( originResH == CDI_UNDEFID ) return CDI_UNDEFID;
240

241
242
  tin.idx = originResH & idxmask;
  tin.nsp = (int)(((unsigned)( originResH & nspmask )) >> idxbits);
243

244
  xassert ( tin.nsp == originNamespace );
245
246

  nsp = namespaceGetActive ();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
247

248
249
  return namespaceIdxEncode2 ( nsp, tin.idx );
}
Deike Kleberg's avatar
Deike Kleberg committed
250
251


252
int namespaceAdaptKey2 ( int originResH )
Deike Kleberg's avatar
Deike Kleberg committed
253
254
255
256
{
  namespaceTuple_t tin;
  int nsp;

257
  if ( originResH == CDI_UNDEFID ) return CDI_UNDEFID;
Deike Kleberg's avatar
Deike Kleberg committed
258

259
260
  tin.idx = originResH & idxmask;
  tin.nsp = (int)(((unsigned)( originResH & nspmask )) >> idxbits);
Deike Kleberg's avatar
Deike Kleberg committed
261
262

  nsp = namespaceGetActive ();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
263

Deike Kleberg's avatar
Deike Kleberg committed
264
265
266
  return namespaceIdxEncode2 ( nsp, tin.idx );
}

267

Thomas Jahns's avatar
Thomas Jahns committed
268
void namespaceDefResStatus (enum namespaceStatus argResStatus )
269
270
{
  int nsp = namespaceGetActive ();
271
  namespaces[nsp].resStage = argResStatus;
272
273
274
}


Thomas Jahns's avatar
Thomas Jahns committed
275
enum namespaceStatus namespaceInqResStatus ( void )
276
277
{
  int nsp = namespaceGetActive ();
278
  return namespaces[nsp].resStage;
279
280
}

281
void namespaceSwitchSet(enum namespaceSwitch sw, union namespaceSwitchValue value)
282
283
284
285
286
287
{
  xassert(sw > NSSWITCH_NO_SUCH_SWITCH && sw < NUM_NAMESPACE_SWITCH);
  int nsp = namespaceGetActive();
  namespaces[nsp].switches[sw] = value;
}

288
union namespaceSwitchValue namespaceSwitchGet(enum namespaceSwitch sw)
289
290
291
292
293
294
{
  xassert(sw > NSSWITCH_NO_SUCH_SWITCH && sw < NUM_NAMESPACE_SWITCH);
  int nsp = namespaceGetActive();
  return namespaces[nsp].switches[sw];
}

Thomas Jahns's avatar
Thomas Jahns committed
295
296
void cdiReset(void)
{
Thomas Jahns's avatar
Thomas Jahns committed
297
  NAMESPACE_INIT();
Thomas Jahns's avatar
Thomas Jahns committed
298
  NAMESPACE_LOCK();
299
  for (unsigned namespaceID = 0; namespaceID < namespacesSize; ++namespaceID)
Thomas Jahns's avatar
Thomas Jahns committed
300
    if (namespaces[namespaceID].resStage != NAMESPACE_STATUS_UNUSED)
301
      namespaceDelete((int)namespaceID);
Thomas Jahns's avatar
Thomas Jahns committed
302
303
  if (namespaces != &initialNamespace)
    {
304
      Free(namespaces);
Thomas Jahns's avatar
Thomas Jahns committed
305
306
      namespaces = &initialNamespace;
    }
Thomas Jahns's avatar
Thomas Jahns committed
307
308
309
310
311
312
  namespacesSize = 1;
  nNamespaces = 1;
  activeNamespace = 0;
  NAMESPACE_UNLOCK();
}

313
314
315
316
317
318
319
320
321
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */