namespace.c 9.5 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 int 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#if defined (SX)
static const union namespaceSwitchValue defaultSwitches[NUM_NAMESPACE_SWITCH] = {
    { .func = (void (*)()) cdiAbortC_serial },
    { .func = (void (*)()) cdiWarning },
    { .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_ },
    { .func = (void (*)()) cdiStreamWriteVar_ },
    { .func = (void (*)()) cdiStreamwriteVarChunk_ },
    { .func = (void (*)()) 0 },
    { .func = (void (*)()) 0 },
    { .func = (void (*)()) cdiStreamCloseDefaultDelegate },
    { .func = (void (*)()) cdiStreamDefTimestep_ },
    { .func = (void (*)()) cdiStreamSync_ },
    CDI_NETCDF_SWITCHES
};
#else
60
61
#define defaultSwitches {                                   \
    { .func = (void (*)()) cdiAbortC_serial },              \
62
    { .func = (void (*)()) cdiWarning },                    \
63
64
65
66
67
68
69
70
71
72
    { .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_ },            \
    { .func = (void (*)()) cdiStreamWriteVar_ },            \
    { .func = (void (*)()) cdiStreamwriteVarChunk_ },       \
73
    { .func = (void (*)()) 0 },                             \
74
    { .func = (void (*)()) 0 },                             \
75
    { .func = (void (*)()) cdiStreamCloseDefaultDelegate }, \
Thomas Jahns's avatar
Thomas Jahns committed
76
    { .func = (void (*)()) cdiStreamDefTimestep_ }, \
77
78
79
    { .func = (void (*)()) cdiStreamSync_ },                \
    CDI_NETCDF_SWITCHES                        \
    }
80
#endif
81

82
83
84
struct namespace
{
  statusCode resStage;
85
  union namespaceSwitchValue switches[NUM_NAMESPACE_SWITCH];
86
87
} initialNamespace = {
  .resStage = STAGE_DEFINITION,
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#if defined (SX)
  .switches = {
    { .func = (void (*)()) cdiAbortC_serial },
    { .func = (void (*)()) cdiWarning },
    { .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_ },
    { .func = (void (*)()) cdiStreamWriteVar_ },
    { .func = (void (*)()) cdiStreamwriteVarChunk_ },
    { .func = (void (*)()) 0 },
    { .func = (void (*)()) 0 },
    { .func = (void (*)()) cdiStreamCloseDefaultDelegate },
    { .func = (void (*)()) cdiStreamDefTimestep_ },
    { .func = (void (*)()) cdiStreamSync_ },
    CDI_NETCDF_SWITCHES
}
#else
110
  .switches = defaultSwitches
111
#endif
112
};
113
114

struct namespace *namespaces = &initialNamespace;
115

Thomas Jahns's avatar
Thomas Jahns committed
116
117
118
119
120
static int namespacesSize = 1;

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

Thomas Jahns's avatar
Thomas Jahns committed
121
122
123
124
125
126
127
128
129
130
131
132
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
133
134
135

#  define NAMESPACE_LOCK()         pthread_mutex_lock(&namespaceMutex)
#  define NAMESPACE_UNLOCK()       pthread_mutex_unlock(&namespaceMutex)
Thomas Jahns's avatar
Thomas Jahns committed
136
137
138
#  define NAMESPACE_INIT()         pthread_once(&namespaceOnce, \
                                                namespaceInitialize)

Thomas Jahns's avatar
Thomas Jahns committed
139
140
141

#else

Thomas Jahns's avatar
Thomas Jahns committed
142
#  define NAMESPACE_INIT() do { } while (0)
Thomas Jahns's avatar
Thomas Jahns committed
143
144
145
146
147
148
#  define NAMESPACE_LOCK()
#  define NAMESPACE_UNLOCK()

#endif


149
150
151
enum {
  intbits = sizeof(int) * CHAR_BIT,
  nspbits = 4,
152
  idxbits = intbits - nspbits,
Deike Kleberg's avatar
Deike Kleberg committed
153
154
  nspmask = (( 1 << nspbits ) - 1) << idxbits,
  idxmask = ( 1 << idxbits ) - 1,
155
156
157
158
};

enum {
  NUM_NAMESPACES = 1 << nspbits,
159
  NUM_IDX = 1 << idxbits,
160
};
161

162
163
164

int namespaceIdxEncode ( namespaceTuple_t tin )
{
Deike Kleberg's avatar
Deike Kleberg committed
165
  xassert ( tin.nsp < NUM_NAMESPACES && tin.idx < NUM_IDX);
166
  return ( tin.nsp << idxbits ) + tin.idx;
167
}
168

169
int namespaceIdxEncode2 ( int nsp, int idx )
170
{
Deike Kleberg's avatar
Deike Kleberg committed
171
  xassert(nsp < NUM_NAMESPACES && idx < NUM_IDX);
172
173
174
  return ( nsp << idxbits ) + idx;
}

175

Deike Kleberg's avatar
Deike Kleberg committed
176
namespaceTuple_t namespaceResHDecode ( int resH )
177
178
179
{
  namespaceTuple_t tin;

Deike Kleberg's avatar
Deike Kleberg committed
180
181
  tin.idx = resH & idxmask;
  tin.nsp = (int)(((unsigned)( resH & nspmask )) >> idxbits);
182
183
184
185

  return tin;
}

Thomas Jahns's avatar
Thomas Jahns committed
186
int
187
namespaceNew()
188
{
Thomas Jahns's avatar
Thomas Jahns committed
189
  int newNamespaceID = -1;
Thomas Jahns's avatar
Thomas Jahns committed
190
  NAMESPACE_INIT();
Thomas Jahns's avatar
Thomas Jahns committed
191
192
  NAMESPACE_LOCK();
  if (namespacesSize > nNamespaces)
193
    {
Thomas Jahns's avatar
Thomas Jahns committed
194
195
196
197
198
199
200
      /* namespace is already available and only needs reinitialization */
      for (int i = 0; i < namespacesSize; ++i)
        if (namespaces[i].resStage == STAGE_UNUSED)
          {
            newNamespaceID = i;
            break;
          }
201
    }
Thomas Jahns's avatar
Thomas Jahns committed
202
203
204
  else if (namespacesSize == 1)
    {
      /* make room for additional namespace */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
      struct namespace *newNameSpaces = (struct namespace*) xmalloc((namespacesSize + 1) * sizeof (namespaces[0]));
Thomas Jahns's avatar
Thomas Jahns committed
206
207
208
209
210
211
212
213
214
      memcpy(newNameSpaces, namespaces, sizeof (namespaces[0]));
      namespaces = newNameSpaces;
      ++namespacesSize;
      newNamespaceID = 1;
    }
  else if (namespacesSize < NUM_NAMESPACES)
    {
      /* make room for additional namespace */
      newNamespaceID = namespacesSize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
215
      namespaces = (struct namespace*) xrealloc(namespaces, (namespacesSize + 1) * sizeof (namespaces[0]));
Thomas Jahns's avatar
Thomas Jahns committed
216
217
218
219
220
221
222
223
224
225
      ++namespacesSize;
    }
  else /* implicit: namespacesSize >= NUM_NAMESPACES */
    {
      NAMESPACE_UNLOCK();
      return -1;
    }
  xassert(newNamespaceID >= 0 && newNamespaceID < NUM_NAMESPACES);
  ++nNamespaces;
  namespaces[newNamespaceID].resStage = STAGE_DEFINITION;
226
227
228
229
#if defined (SX)
  memcpy(namespaces[newNamespaceID].switches, defaultSwitches,
         sizeof (namespaces[newNamespaceID].switches));
#else
230
  memcpy(namespaces[newNamespaceID].switches,
231
         (union namespaceSwitchValue[NUM_NAMESPACE_SWITCH])defaultSwitches,
232
         sizeof (namespaces[newNamespaceID].switches));
233
#endif
Thomas Jahns's avatar
Thomas Jahns committed
234
235
236
  reshListCreate(newNamespaceID);
  NAMESPACE_UNLOCK();
  return newNamespaceID;
237
238
}

Thomas Jahns's avatar
Thomas Jahns committed
239
240
241
void
namespaceDelete(int namespaceID)
{
Thomas Jahns's avatar
Thomas Jahns committed
242
  NAMESPACE_INIT();
Thomas Jahns's avatar
Thomas Jahns committed
243
244
245
246
247
248
249
  NAMESPACE_LOCK();
  xassert(namespaceID < namespacesSize && nNamespaces);
  reshListDestruct(namespaceID);
  namespaces[namespaceID].resStage = STAGE_UNUSED;
  --nNamespaces;
  NAMESPACE_UNLOCK();
}
250

251
252
253
254
255
256
int namespaceGetNumber ()
{
  return nNamespaces;
}


257
void namespaceSetActive ( int nId )
258
{
Thomas Jahns's avatar
Thomas Jahns committed
259
260
  xassert(nId < namespacesSize && nId >= 0
          && namespaces[nId].resStage != STAGE_UNUSED);
261
262
263
  activeNamespace = nId;
}

264

265
266
267
268
int namespaceGetActive ()
{
  return activeNamespace;
}
269

270
271
272
273
274
275
276
277
278
279
int namespaceAdaptKey ( int key, int nspTarget )
{
  namespaceTuple_t tin;
  int nsp;

  if ( key == CDI_UNDEFID ) return CDI_UNDEFID;

  tin.idx = key & idxmask;
  tin.nsp = (int)(((unsigned)( key & nspmask )) >> idxbits);

Deike Kleberg's avatar
Deike Kleberg committed
280
  xassert ( tin.nsp == nspTarget );
281
282

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

284
285
  return namespaceIdxEncode2 ( nsp, tin.idx );
}
Deike Kleberg's avatar
Deike Kleberg committed
286
287
288
289
290
291
292
293
294
295
296
297
298


int namespaceAdaptKey2 ( int key )
{
  namespaceTuple_t tin;
  int nsp;

  if ( key == CDI_UNDEFID ) return CDI_UNDEFID;

  tin.idx = key & idxmask;
  tin.nsp = (int)(((unsigned)( key & nspmask )) >> idxbits);

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

Deike Kleberg's avatar
Deike Kleberg committed
300
301
302
  return namespaceIdxEncode2 ( nsp, tin.idx );
}

303

304
void namespaceDefResStatus ( statusCode argResStatus )
305
306
{
  int nsp = namespaceGetActive ();
307
  namespaces[nsp].resStage = argResStatus;
308
309
310
}


311
statusCode namespaceInqResStatus ( void )
312
313
{
  int nsp = namespaceGetActive ();
314
  return namespaces[nsp].resStage;
315
316
}

317
void namespaceSwitchSet(enum namespaceSwitch sw, union namespaceSwitchValue value)
318
319
320
321
322
323
{
  xassert(sw > NSSWITCH_NO_SUCH_SWITCH && sw < NUM_NAMESPACE_SWITCH);
  int nsp = namespaceGetActive();
  namespaces[nsp].switches[sw] = value;
}

324
union namespaceSwitchValue namespaceSwitchGet(enum namespaceSwitch sw)
325
326
327
328
329
330
{
  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
331
332
void cdiReset(void)
{
Thomas Jahns's avatar
Thomas Jahns committed
333
  NAMESPACE_INIT();
Thomas Jahns's avatar
Thomas Jahns committed
334
335
  NAMESPACE_LOCK();
  for (int namespaceID = 0; namespaceID < namespacesSize; ++namespaceID)
Thomas Jahns's avatar
Thomas Jahns committed
336
337
338
339
340
341
342
    if (namespaces[namespaceID].resStage != STAGE_UNUSED)
      namespaceDelete(namespaceID);
  if (namespaces != &initialNamespace)
    {
      free(namespaces);
      namespaces = &initialNamespace;
    }
Thomas Jahns's avatar
Thomas Jahns committed
343
344
345
346
347
348
  namespacesSize = 1;
  nNamespaces = 1;
  activeNamespace = 0;
  NAMESPACE_UNLOCK();
}

349
350
351
352
353
354
355
356
357
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */