stream_int.c 11.6 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <stdio.h>
#include <stdarg.h>
#include <string.h> 
#include <errno.h>
#include <math.h>
#include <ctype.h>

#include "dmemory.h"

#include "cdi.h"
#include "stream_int.h"


int cdiDefaultInstID  = CDI_UNDEFID;
int cdiDefaultModelID = CDI_UNDEFID;
int cdiDefaultTableID = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
21
int cdiNcMissingValue = CDI_UNDEFID;
22
int cdiSplitLtype105  = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
23

24
25
int cdiIgnoreAttCoordinates = FALSE;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
26
27
28
char *cdiPartabPath   = NULL;
int   cdiPartabIntern = 1;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
29
30
31
32
33
34
35
36
37
double cdiDefaultMissval = -9.E33;


char *Filetypes[] = {
  "UNKNOWN",
  "GRIB",
  "GRIB2",
  "netCDF",
  "netCDF2",
38
  "netCDF4",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
40
41
  "SERVICE",
  "EXTRA",
  "IEG",
42
  "HDF5",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
};

#undef  UNDEFID
#define UNDEFID  CDI_UNDEFID


int CDI_Debug   = 0;    /* If set to 1, debugging           */


int cdiDefaultLeveltype = -1;
static int cdiDataUnreduced = 0;


long cdiGetenvInt(char *envName)
{
  static char func[] = "cdiGetenv";
  char *envString;
  long envValue = -1;
  long fact = 1;

  envString = getenv(envName);

  if ( envString )
    {
      int loop, len;

      len = (int) strlen(envString);
      for ( loop = 0; loop < len; loop++ )
	{
	  if ( ! isdigit((int) envString[loop]) )
	    {
	      switch ( tolower((int) envString[loop]) )
		{
		case 'k':  fact = 1024;        break;
		case 'm':  fact = 1048576;     break;
		case 'g':  fact = 1073741824;  break;
		default:
		  fact = 0;
		  Message(func, "Invalid number string in %s: %s", envName, envString);
		  Warning(func, "%s must comprise only digits [0-9].",envName);
		}
	      break;
	    }
	}

      if ( fact ) envValue = fact*atol(envString);

      if ( CDI_Debug ) Message(func, "set %s to %ld", envName, envValue);
    }

  return (envValue);
}


void cdiInitialize(void)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
  static char func[] = "cdiInitialize";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  static int Init_CDI = FALSE;
  char *envString;
  long value;

  if ( ! Init_CDI )
    {
      Init_CDI = TRUE;

      value = cdiGetenvInt("CD_REGULARGRID");
      if ( value >= 0 ) cdiDataUnreduced = (int) value;

      value = cdiGetenvInt("CD_LEVELTYPE");
      if ( value >= 0 ) cdiDefaultLeveltype = (int) value;

      envString = getenv("CD_MISSVAL");
      if ( envString ) cdiDefaultMissval = atof(envString);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
116
117

      envString = getenv("NC_MISSING_VALUE");
118
      if ( envString ) cdiNcMissingValue = atoi(envString);
119
120
121

      envString = getenv("SPLIT_LTYPE_105");
      if ( envString ) cdiSplitLtype105 = atoi(envString);
122
123
124

      envString = getenv("IGNORE_ATT_COORDINATES");
      if ( envString ) cdiIgnoreAttCoordinates = atoi(envString);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
125
126
127
128
129
130

      envString = getenv("PARTAB_INTERN");
      if ( envString ) cdiPartabIntern = atoi(envString);

      envString = getenv("PARTAB_PATH");
      if ( envString ) cdiPartabPath = strdup(envString);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
131
132
133
134
    }
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
135
char *strfiletype(int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
136
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
137
138
  char *name;
  int size = (int) (sizeof(Filetypes)/sizeof(char *));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
139

Uwe Schulzweida's avatar
Uwe Schulzweida committed
140
141
142
143
  if ( filetype > 0 && filetype < size )
    name = Filetypes[filetype];
  else
    name = Filetypes[0];  
Uwe Schulzweida's avatar
Uwe Schulzweida committed
144

Uwe Schulzweida's avatar
Uwe Schulzweida committed
145
  return (name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
146
147
148
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
149
150
static int  STREAM_Debug = 0;   /* If set to 1, debugging */

151
static int _stream_max = MAX_STREAMS;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

static void stream_initialize(void);

static int _stream_init = FALSE;

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

static pthread_once_t _stream_init_thread = PTHREAD_ONCE_INIT;
static pthread_mutex_t _stream_mutex;

#  define STREAM_LOCK           pthread_mutex_lock(&_stream_mutex);
#  define STREAM_UNLOCK         pthread_mutex_unlock(&_stream_mutex);
#  define STREAM_INIT                               \
   if ( _stream_init == FALSE ) pthread_once(&_stream_init_thread, stream_initialize);

#else

#  define STREAM_LOCK
#  define STREAM_UNLOCK
#  define STREAM_INIT                               \
   if ( _stream_init == FALSE ) stream_initialize();

#endif


typedef struct _streamPtrToIdx {
  int idx;
  STREAM *ptr;
  struct _streamPtrToIdx *next;
} streamPtrToIdx;


Uwe Schulzweida's avatar
Uwe Schulzweida committed
185
186
static streamPtrToIdx *_streamList  = NULL;
static streamPtrToIdx *_streamAvail = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
188
189


static void stream_list_new(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
190
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
191
  static char func[] = "stream_list_new";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
192

Uwe Schulzweida's avatar
Uwe Schulzweida committed
193
194
  assert(_streamList == NULL);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
195
  _streamList = (streamPtrToIdx *) malloc(_stream_max*sizeof(streamPtrToIdx));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
196
197
198
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
199
static void stream_list_delete(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
200
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
201
  static char func[] = "stream_list_delete";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
202

Uwe Schulzweida's avatar
Uwe Schulzweida committed
203
204
  if ( _streamList ) free(_streamList);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
206


Uwe Schulzweida's avatar
Uwe Schulzweida committed
207
208
209
210
211
212
213
214
215
216
217
218
219
220
static void stream_init_pointer(void)
{
  int  i;
  
  for ( i = 0; i < _stream_max; i++ )
    {
      _streamList[i].next = _streamList + i + 1;
      _streamList[i].idx  = i;
      _streamList[i].ptr  = 0;
    }

  _streamList[_stream_max-1].next = 0;

  _streamAvail = _streamList;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
221
222
223
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
224
STREAM *stream_to_pointer(int idx)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
225
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
226
227
228
229
230
231
  static char func[] = "stream_to_pointer";
  STREAM *streamptr = NULL;

  STREAM_INIT

  if ( idx >= 0 && idx < _stream_max )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
232
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
233
      STREAM_LOCK
Uwe Schulzweida's avatar
Uwe Schulzweida committed
234

Uwe Schulzweida's avatar
Uwe Schulzweida committed
235
      streamptr = _streamList[idx].ptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236

Uwe Schulzweida's avatar
Uwe Schulzweida committed
237
      STREAM_UNLOCK
Uwe Schulzweida's avatar
Uwe Schulzweida committed
238
239
    }
  else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    Error(func, "stream index %d undefined!", idx);

  return (streamptr);
}


/* Create an index from a pointer */
static int stream_from_pointer(STREAM *ptr)
{
  static char func[] = "stream_from_pointer";
  int      idx = -1;
  streamPtrToIdx *newptr;

  if ( ptr )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
254
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
255
256
257
      STREAM_LOCK

      if ( _streamAvail )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
258
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
259
260
261
262
263
264
265
266
	  newptr       = _streamAvail;
	  _streamAvail   = _streamAvail->next;
	  newptr->next = 0;
	  idx	       = newptr->idx;
	  newptr->ptr  = ptr;
      
	  if ( STREAM_Debug )
	    Message(func, "Pointer %p has idx %d from stream list", ptr, idx);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
267
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
268
269
270
271
      else
	Warning(func, "Too many open streams (limit is %d)!", _stream_max);

      STREAM_UNLOCK
Uwe Schulzweida's avatar
Uwe Schulzweida committed
272
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
273
274
  else
    Error(func, "Internal problem (pointer %p undefined)", ptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275

Uwe Schulzweida's avatar
Uwe Schulzweida committed
276
277
  return (idx);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
278
279


Uwe Schulzweida's avatar
Uwe Schulzweida committed
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
static void stream_init_entry(STREAM *streamptr)
{
  int i;

  streamptr->self         = stream_from_pointer(streamptr);

  streamptr->accesstype        = UNDEFID;
  streamptr->accessmode        = 0;
  streamptr->filetype          = UNDEFID;
  streamptr->byteorder         = UNDEFID;
  streamptr->fileID            = 0;
  streamptr->dimgroupID        = UNDEFID;
  streamptr->filemode          = 0;
  streamptr->numvals           = 0;
  streamptr->filename          = NULL;
  streamptr->ctlname           = NULL;
  streamptr->ctlfp             = NULL;
  streamptr->record            = NULL;
  streamptr->varsAllocated     = 0;
  streamptr->nrecs             = 0;
  streamptr->nvars             = 0;
  streamptr->vars              = NULL;
  streamptr->varinit           = 0;
  streamptr->ncmode            = 0;
  streamptr->curTsID           = UNDEFID;
  streamptr->rtsteps           = 0;
  streamptr->ntsteps           = UNDEFID;
  streamptr->numTimestep       = 0;
  streamptr->tsteps            = NULL;
  streamptr->tstepsTableSize   = 0;
  streamptr->tstepsNextID      = 0;
  streamptr->historyID         = UNDEFID;
  streamptr->vlistID           = UNDEFID;
  streamptr->globalatts        = 0;
  streamptr->localatts         = 0;
  streamptr->vct.ilev          = 0;
  streamptr->vct.mlev          = 0;
  streamptr->vct.ilevID        = UNDEFID;
  streamptr->vct.mlevID        = UNDEFID;
  streamptr->unreduced         = cdiDataUnreduced;
320
321
  streamptr->ztype             = COMPRESS_NONE;
  streamptr->zlevel            = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
322
323
324

  basetimeInit(&streamptr->basetime);

325
326
327
328
329
330
  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->xdimID[i]   = UNDEFID;
  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ydimID[i]   = UNDEFID;
  for ( i = 0; i < MAX_ZAXIS_PS; i++ ) streamptr->zaxisID[i]  = UNDEFID;
  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncxvarID[i] = UNDEFID;
  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncyvarID[i] = UNDEFID;
  for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncavarID[i] = UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
331
332
333
334

  streamptr->curfile           = 0;
  streamptr->nfiles            = 0;
  streamptr->fnames            = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
335
336
337
338
339
340
341
342
}


STREAM *stream_new_entry(void)
{
  static char func[] = "stream_new_entry";
  STREAM *streamptr;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
343
  cdiInitialize(); /* ***************** make MT version !!! */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

  STREAM_INIT

  streamptr = (STREAM *) malloc(sizeof(STREAM));

  if ( streamptr ) stream_init_entry(streamptr);

  return (streamptr);
}


void stream_delete_entry(STREAM *streamptr)
{
  static char func[] = "stream_delete_entry";
  int idx;

  idx = streamptr->self;

  STREAM_LOCK

  free(streamptr);

  _streamList[idx].next = _streamAvail;
  _streamList[idx].ptr  = 0;
  _streamAvail          = &_streamList[idx];

  STREAM_UNLOCK

  if ( STREAM_Debug )
    Message(func, "Removed idx %d from stream list", idx);
}


static void stream_initialize(void)
{
  char *env;

#if  defined  (HAVE_LIBPTHREAD)
  /* initialize global API mutex lock */
  pthread_mutex_init(&_stream_mutex, NULL);
#endif

  env = getenv("STREAM_DEBUG");
  if ( env ) STREAM_Debug = atoi(env);

  stream_list_new();
  atexit(stream_list_delete);

392
393
  STREAM_LOCK

Uwe Schulzweida's avatar
Uwe Schulzweida committed
394
395
  stream_init_pointer();

396
397
  STREAM_UNLOCK

Uwe Schulzweida's avatar
Uwe Schulzweida committed
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  _stream_init = TRUE;
}


void stream_check_ptr(const char *func, STREAM *streamptr)
{
  if ( streamptr == NULL )
    Error(func, "stream undefined!");
}


int streamSize(void)
{
  int streamsize = 0;
  int i;
  
  STREAM_INIT

  STREAM_LOCK

  for ( i = 0; i < _stream_max; i++ )
    if ( _streamList[i].ptr ) streamsize++;

  STREAM_UNLOCK

  return (streamsize);
}


int cdiDefGlobal(const char *string, int val)
{
  int ret = 0;

  if ( strcmp(string, "CD_REGULARGRID") == 0 )
    {
      cdiDataUnreduced = val;
      ret = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
435
436
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
437
438
  return (ret);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
439
440


Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
442
443
444
445
446
447
448
449
450
451
452
453
454
void cdiDefMissval(double missval)
{
  cdiInitialize();

  cdiDefaultMissval = missval;

}


double cdiInqMissval(void)
{
  cdiInitialize();

  return (cdiDefaultMissval);;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
455
456
457
458
459
460
461
462
}


void cdiCheckContents(int streamID)
{
  static char func[] = "cdiCheckContents";
  int index, nzaxis, zaxisID;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
463
  STREAM *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
464

Uwe Schulzweida's avatar
Uwe Schulzweida committed
465
466
467
  streamptr = stream_to_pointer(streamID);

  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483

  vlistID = streamInqVlist(streamID);
  nzaxis = vlistNzaxis(vlistID);

  for ( index = 0; index < nzaxis; index++ )
    {
      zaxisID = vlistZaxis(vlistID, index);
      if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC )
	cdiCheckZaxis(zaxisID);
    }
    
}


int streamInqFileID(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
485
486
487
488
  STREAM *streamptr;

  streamptr = stream_to_pointer(streamID);

  return (streamptr->fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
489
490
491
492
493
494
}


void streamDefineTaxis(int streamID)
{
  static char func[] = "streamDefineTaxis";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
495
  STREAM *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496

Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
498
499
  streamptr = stream_to_pointer(streamID);

  if ( streamptr->tsteps == NULL )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
    {
      int varID, nvars;
      int vlistID;
  
      vlistID = streamInqVlist(streamID);

      nvars = vlistNvars(vlistID);
      for ( varID = 0; varID < nvars; varID++ )
	if ( vlistInqVarTime(vlistID, varID) == TIME_VARIABLE ) break;

      if ( varID == nvars )
	{
	  int taxisID;

	  taxisID = vlistInqTaxis(vlistID);
	  if ( taxisID == CDI_UNDEFID )
	    {
517
	      taxisID = taxisCreate(TAXIS_ABSOLUTE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
519
520
521
522
523
524
525
526
527
528
529
530
	      vlistDefTaxis(vlistID, taxisID);
	    }
	    
	  (void) streamDefTimestep(streamID, 0);
	}
      else
	Error(func, "time axis undefined");
    }
}


void streamDefDimgroupID(int streamID, int dimgroupID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
531
532
533
534
535
  STREAM *streamptr;

  streamptr = stream_to_pointer(streamID);

  streamptr->dimgroupID = dimgroupID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
537
538
539
540
}


int streamInqDimgroupID(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
541
542
543
544
545
  STREAM *streamptr;

  streamptr = stream_to_pointer(streamID);

  return (streamptr->dimgroupID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546
547
548
549
550
551
}


void cdiDefAccesstype(int streamID, int type)
{
  static char func[] = "cdiDefAccesstype";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
553
554
  STREAM *streamptr;

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
555

Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
  if ( streamptr->accesstype == UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
      streamptr->accesstype = type;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
559
560
561
    }
  else
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
      if ( streamptr->accesstype != type )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
563
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
564
	  if ( streamptr->accesstype == TYPE_REC )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
565
566
567
568
569
570
571
572
573
574
	    Error(func, "Change access type from REC to VAR not allowed!");
	  else
	    Error(func, "Change access type from VAR to REC not allowed!");
	}
    }
}


int cdiInqAccesstype(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
575
576
577
578
579
  STREAM *streamptr;

  streamptr = stream_to_pointer(streamID);

  return (streamptr->accesstype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
580
}