stream_srv.c 18.9 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
#ifdef HAVE_CONFIG_H
#include "config.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
3
4
5
6
7
8
9
#endif

#include "dmemory.h"

#include "error.h"
#include "file.h"
#include "cdi.h"
10
#include "cdi_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
11
12
13
#include "varscan.h"
#include "datetime.h"
#include "service.h"
14
#include "stream_scan.h"
15
#include "stream_srv.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
16
#include "exse.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
17
18


Uwe Schulzweida's avatar
Uwe Schulzweida committed
19
#ifdef HAVE_LIBSERVICE
Uwe Schulzweida's avatar
Uwe Schulzweida committed
20

21
typedef struct {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
22
  int param;
23
  int level;
24
} srvcompvar_t;
25
26


27
28
static
int srvInqDatatype(int prec)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
29
{
30
  return (prec == EXSE_DOUBLE_PRECISION) ? CDI_DATATYPE_FLT64 : CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
31
32
}

33
34
static
int srvDefDatatype(int datatype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35
{
36
  if ( datatype == CDI_DATATYPE_CPX32 || datatype == CDI_DATATYPE_CPX64 )
37
    Error("CDI/SERVICE library does not support complex numbers!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
38

39
40
  if ( datatype != CDI_DATATYPE_FLT32 && datatype != CDI_DATATYPE_FLT64 )
    datatype = CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41

42
  return (datatype == CDI_DATATYPE_FLT64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
43
44
}

45
/* not used
46
int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
47
48
49
{
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
50
  int icode, ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51
52
53
  int zaxisID = -1;
  int header[8];
  int vlistID;
54
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
55

56
57
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
58
59
60
61
62
63
64
65
66

  *varID   = -1;
  *levelID = -1;

  status = srvRead(fileID, srvp);
  if ( status != 0 ) return (0);

  srvInqHeader(srvp, header);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
67
  icode  = header[0];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
68
69
  ilevel = header[1];

Uwe Schulzweida's avatar
Uwe Schulzweida committed
70
  *varID = vlistInqVarID(vlistID, icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
71

72
  if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
73
74
75
76

  zaxisID = vlistInqVarZaxis(vlistID, *varID);

  *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
77

78
  return 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
}
80
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
81

82
void srvReadRecord(stream_t *streamptr, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
83
{
84
85
86
87
88
89
90
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
  int tsID     = streamptr->curTsID;
  int vrecID   = streamptr->tsteps[tsID].curRecID;
  int recID    = streamptr->tsteps[tsID].recIDs[vrecID];
  int varID    = streamptr->tsteps[tsID].records[recID].varID;
  off_t recpos = streamptr->tsteps[tsID].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
91
92
93

  fileSetPos(fileID, recpos, SEEK_SET);

94
  void *srvp = streamptr->record->exsep;
95
  int status = srvRead(fileID, srvp);
96
  if ( status != 0 ) Error("Failed to read record from SRV file");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
97

98
  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
100
101
  srvInqHeader(srvp, header);
  srvInqDataDP(srvp, data);

102
103
  double missval = vlistInqVarMissval(vlistID, varID);
  int gridID  = vlistInqVarGrid(vlistID, varID);
104
  size_t size = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
105

Uwe Schulzweida's avatar
Uwe Schulzweida committed
106
  streamptr->numvals += size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
107
108

  *nmiss = 0;
109
  for ( size_t i = 0; i < size; i++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
110
111
112
113
114
115
116
117
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }
}


118
void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
119
{
120
  streamFCopyRecord(streamptr2, streamptr1, "SRV");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121
122
123
}


124
void srvDefRecord(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
125
{
126
  Record *record = streamptr->record;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
127

128
129
  int pdis, pcat, pnum;
  cdiDecodeParam(record->param, &pnum, &pcat, &pdis);
130
131

  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
132
  header[0] = pnum;
133
134
135
  header[1] = record->level;
  header[2] = record->date;
  header[3] = record->time;
136

137
  int gridID = record->gridID;
138
139
  size_t xsize = gridInqXsize(gridID),
         ysize = gridInqYsize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
140
141
142
143
144
  if ( xsize == 0 || ysize == 0 )
    {
      xsize = gridInqSize(gridID);
      ysize = 1;
    }
145
  if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
146
  if ( gridInqSize(gridID) != xsize*ysize )
147
    Error("Internal problem with gridsize!");
148

149
  cdi_check_gridsize_int_limit("SERVICE", gridInqSize(gridID));
150
151
152

  header[4] = (int)xsize;
  header[5] = (int)ysize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
153
154
155
  header[6] = 0;
  header[7] = 0;

156
157
  srvrec_t *srvp = (srvrec_t*) record->exsep;
  srvp->dprec = srvDefDatatype(record->prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
158
159
160
161
162

  srvDefHeader(srvp, header);
}


163
void srvWriteRecord(stream_t *streamptr, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
164
{
165
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
166
  srvDefDataDP(srvp, data);
167
  srvWrite(streamptr->fileID, srvp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
168
169
}

170
static
171
void srv_add_record(stream_t *streamptr, int param, int level, size_t xsize, size_t ysize,
172
                    size_t recsize, off_t position, int prec)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
{
Thomas Jahns's avatar
Thomas Jahns committed
174
175
176
177
  int vlistID = streamptr->vlistID;
  int tsID    = streamptr->curTsID;
  int recID   = recordNewEntry(streamptr, tsID);
  record_t *record = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
178

Thomas Jahns's avatar
Thomas Jahns committed
179
180
181
182
  record->size     = recsize;
  record->position = position;
  record->param    = param;
  record->ilevel   = level;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
183

184
  grid_t *grid = (grid_t*) Malloc(sizeof(*grid));
185
  grid_init(grid);
186
  cdiGridTypeInit(grid, GRID_GENERIC, xsize*ysize);
187
188
  grid->x.size = xsize;
  grid->y.size = ysize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
189
  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
190
191
  int gridID = gridAdded.Id;
  if (!gridAdded.isNew) Free(grid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
192

193
  int leveltype = ZAXIS_GENERIC;
Thomas Jahns's avatar
Thomas Jahns committed
194
  int datatype = srvInqDatatype(prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
195

196
  int varID, levelID = 0;
197
  varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
198
	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
199
               NULL, NULL, NULL, NULL, NULL, NULL, 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
200

201
  xassert(varID <= SHRT_MAX && levelID <= SHRT_MAX);
Thomas Jahns's avatar
Thomas Jahns committed
202
203
  record->varID   = (short)varID;
  record->levelID = (short)levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
204

Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
206
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
207
208

  if ( CDI_Debug )
209
    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
211
}

212
static
213
214
void srvScanTimestep1(stream_t *streamptr)
{
215
  DateTime datetime0 = { LONG_MIN, LONG_MIN };
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216
  off_t recpos;
217
  srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
218

Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220

221
222
223
224
  int tsID  = tstepsNewEntry(streamptr);
  if ( tsID != 0 )
    Error("Internal problem! tstepsNewEntry returns %d", tsID);
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
225

226
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
227

228
  int nrecs = 0;
229
  while ( true )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
    {
231
      int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
232
      recpos = fileGetPos(fileID);
233
      int status = srvRead(fileID, srvp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
234
235
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
	  streamptr->ntsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
237
238
	  break;
	}
239
      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
240
241
242

      srvInqHeader(srvp, header);

243
244
245
246
247
248
249
      int prec   = srvp->dprec;
      int rcode  = header[0];
      int rlevel = header[1];
      int vdate  = header[2];
      int vtime  = header[3];
      int rxsize = header[4];
      int rysize = header[5];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
250

251
      int param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
252

Uwe Schulzweida's avatar
Uwe Schulzweida committed
253
254
255
256
257
258
259
      if ( nrecs == 0 )
	{
	  datetime0.date = vdate;
	  datetime0.time = vtime;
	}
      else
	{
260
	  for ( int recID = 0; recID < nrecs; recID++ )
Thomas Jahns's avatar
Thomas Jahns committed
261
262
            if (    streamptr->tsteps[0].records[recID].param  == param
                 && streamptr->tsteps[0].records[recID].ilevel == rlevel )
263
              goto tstepScanLoopFinished;
264
265
	  DateTime datetime = { .date = vdate, .time = vtime };
	  if ( datetimeCmp(datetime, datetime0) )
266
	    Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
267
268
269
270
271
	}

      nrecs++;

      if ( CDI_Debug )
272
	Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
273

274
      srv_add_record(streamptr, param, rlevel, rxsize, rysize, recsize, recpos, prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275
276
    }

277
  tstepScanLoopFinished:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
278
  streamptr->rtsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
279

280
  cdi_generate_vars(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
281

282
  int taxisID = taxisCreate(TAXIS_ABSOLUTE);
283
  taxis->type = TAXIS_ABSOLUTE;
284
285
  taxis->vdate = (int)datetime0.date;
  taxis->vtime = (int)datetime0.time;
286
287
  taxis->rdate = taxis->vdate;
  taxis->rtime = taxis->vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
288

289
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
290
291
  vlistDefTaxis(vlistID, taxisID);

292
  vlist_check_contents(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
293

294
  int nrecords = streamptr->tsteps[0].nallrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
  if ( nrecords < streamptr->tsteps[0].recordSize )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
296
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
297
298
      streamptr->tsteps[0].recordSize = nrecords;
      streamptr->tsteps[0].records =
299
	(record_t *) Realloc(streamptr->tsteps[0].records,
300
                             (size_t)nrecords * sizeof(record_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
301
302
    }

303
  streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304
  streamptr->tsteps[0].nrecs = nrecords;
305
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
306
    streamptr->tsteps[0].recIDs[recID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
307

Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
309
    {
310
      int tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
311
      if ( tsID != streamptr->rtsteps )
312
	Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313

314
      streamptr->tsteps[tsID-1].next   = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
317
    }

318
  streamScanTimeConstAdjust(streamptr, taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
320
}

321
static
322
323
int srvScanTimestep2(stream_t *streamptr)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324
325
  int header[8];
  off_t recpos = 0;
326
  srvcompvar_t compVar, compVar0;
327
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
329

  streamptr->curTsID = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
330

331
332
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
333

334
  int tsID = streamptr->rtsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
335
  if ( tsID != 1 )
336
    Error("Internal problem! unexpected timestep %d", tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
337

338
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
339

Uwe Schulzweida's avatar
Uwe Schulzweida committed
340
  fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
341

342
  cdi_create_records(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
343

344
  int nrecords = streamptr->tsteps[0].nallrecs;
345
  streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
  streamptr->tsteps[1].nrecs = 0;
347
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
348
    streamptr->tsteps[1].recIDs[recID] = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
349

350
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
351
    {
352
      streamptr->tsteps[tsID].records[recID].position =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
353
	streamptr->tsteps[0].records[recID].position;
354
      streamptr->tsteps[tsID].records[recID].size     =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
	streamptr->tsteps[0].records[recID].size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
356
357
    }

358
  for ( int rindex = 0; rindex <= nrecords; rindex++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
360
    {
      recpos = fileGetPos(fileID);
361
      int status = srvRead(fileID, srvp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
362
363
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364
	  streamptr->ntsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
365
366
	  break;
	}
367
      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368
369
370

      srvInqHeader(srvp, header);

371
372
373
374
      int rcode  = header[0];
      int rlevel = header[1];
      int vdate  = header[2];
      int vtime  = header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375

376
      int param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
377

Uwe Schulzweida's avatar
Uwe Schulzweida committed
378
379
380
381
382
383
384
      if ( rindex == 0 )
	{
	  taxis->type  = TAXIS_ABSOLUTE;
	  taxis->vdate = vdate;
	  taxis->vtime = vtime;
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
      compVar.param = param;
386
      compVar.level = rlevel;
387
388
      bool nextstep = false;
      int recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
390
      for ( recID = 0; recID < nrecords; recID++ )
	{
391
	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
392
393
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;

394
	  if ( memcmp(&compVar0, &compVar, sizeof(srvcompvar_t)) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
396
	      if ( streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397
		{
398
		  nextstep = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
399
400
401
		}
	      else
		{
402
		  streamptr->tsteps[tsID].records[recID].used = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403
		  streamptr->tsteps[tsID].recIDs[rindex] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
404
405
406
407
408
409
		}
	      break;
	    }
	}
      if ( recID == nrecords )
	{
410
	  Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
411
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
412
413
414
415
416
	}

      if ( nextstep ) break;

      if ( CDI_Debug )
417
	Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, rcode, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
418

Uwe Schulzweida's avatar
Uwe Schulzweida committed
419
      streamptr->tsteps[tsID].records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
420

421
      compVar0.param = streamptr->tsteps[tsID].records[recID].param;
422
      compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
423

424
      if ( memcmp(&compVar0, &compVar, sizeof(srvcompvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
425
	{
426
	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
427
		  tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
428
		  streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
		  streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
430
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
431
432
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
433
      streamptr->tsteps[1].records[recID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
434
435
    }

436
437
  int nrecs = 0;
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
439
      if ( ! streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440
	{
441
	  int varID = streamptr->tsteps[tsID].records[recID].varID;
442
          vlistDefVarTimetype(vlistID, varID, TIME_CONSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
444
445
446
447
448
	}
      else
	{
	  nrecs++;
	}
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
449
  streamptr->tsteps[tsID].nrecs = nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
450

Uwe Schulzweida's avatar
Uwe Schulzweida committed
451
  streamptr->rtsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
452

Uwe Schulzweida's avatar
Uwe Schulzweida committed
453
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
454
    {
455
      int tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
456
      if ( tsID != streamptr->rtsteps )
457
	Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
458

459
      streamptr->tsteps[tsID-1].next   = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
460
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
461
462
    }

463
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
464
465
466
}


467
int srvInqContents(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
468
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
469
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
470

471
472
  srvScanTimestep1(streamptr);

473
  int status = (streamptr->ntsteps == -1) ? srvScanTimestep2(streamptr) : 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474

475
  fileSetPos(streamptr->fileID, 0, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
476

477
  return status;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
478
479
}

480
static
481
long srvScanTimestep(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
482
483
484
485
{
  int header[8];
  off_t recpos = 0;
  int recID;
486
  int nrecs = 0;
487
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488

Uwe Schulzweida's avatar
Uwe Schulzweida committed
489
490
  int tsID  = streamptr->rtsteps;
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
491

Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
  if ( streamptr->tsteps[tsID].recordSize == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
493
    {
494
      cdi_create_records(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
495

Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
      nrecs = streamptr->tsteps[1].nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
497

Uwe Schulzweida's avatar
Uwe Schulzweida committed
498
      streamptr->tsteps[tsID].nrecs = nrecs;
499
      streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
      for ( recID = 0; recID < nrecs; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
501
	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
502

503
      int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
504

Uwe Schulzweida's avatar
Uwe Schulzweida committed
505
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
506

507
      for ( int rindex = 0; rindex <= nrecs; rindex++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
	{
	  recpos = fileGetPos(fileID);
510
	  int status = srvRead(fileID, srvp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
512
	  if ( status != 0 )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513
	      streamptr->ntsteps = streamptr->rtsteps + 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
515
	      break;
	    }
516
	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
518
519

	  srvInqHeader(srvp, header);

520
521
522
523
	  int rcode  = header[0];
	  int rlevel = header[1];
	  int vdate  = header[2];
	  int vtime  = header[3];
524
525
          /* rxsize = header[4]; */
          /* rysize = header[5]; */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
526

527
	  int param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528

529
530
	  // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
	  if ( rindex == nrecs ) continue;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
531
	  recID = streamptr->tsteps[tsID].recIDs[rindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
533
534
535
536
537
538

	  if ( rindex == 0 )
	    {
	      taxis->type  = TAXIS_ABSOLUTE;
	      taxis->vdate = vdate;
	      taxis->vtime = vtime;
	    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
539

Thomas Jahns's avatar
Thomas Jahns committed
540
541
          if (    param  != streamptr->tsteps[tsID].records[recID].param
               || rlevel != streamptr->tsteps[tsID].records[recID].ilevel )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
	    {
543
	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
		      tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
545
		      streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546
		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
547
	      Error("Invalid, unsupported or inconsistent record structure!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
548
549
	    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
550
551
	  streamptr->tsteps[tsID].records[recID].position = recpos;
	  streamptr->tsteps[tsID].records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
553

	  if ( CDI_Debug )
554
	    Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, rcode, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
555
556
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
      streamptr->rtsteps++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558

Uwe Schulzweida's avatar
Uwe Schulzweida committed
559
      if ( streamptr->ntsteps != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
	{
561
	  tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
	  if ( tsID != streamptr->rtsteps )
563
	    Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
564

565
	  streamptr->tsteps[tsID-1].next   = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
566
	  streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
568
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
569
570
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
571
572
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
  if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
    {
575
      Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
576
      streamptr->ntsteps = tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
577
578
    }

579
  return streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
580
581
582
}


583
int srvInqTimestep(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
584
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
  if ( tsID == 0 && streamptr->rtsteps == 0 )
586
    Error("Call to cdiInqContents missing!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
587
588

  if ( CDI_Debug )
589
    Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
590

591
592
  long ntsteps = CDI_UNDEFID;
  while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == CDI_UNDEFID )
593
    ntsteps = srvScanTimestep(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
594

595
  int nrecs = 0;
596
  if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
597
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
598
599
      streamptr->curTsID = tsID;
      nrecs = streamptr->tsteps[tsID].nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
600
601
    }

602
  return nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
604
605
}


606
void srvReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
607
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
608
609
  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);

610
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
611

612
613
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
614
  /* NOTE: tiles are not supported here! */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
615
  double missval = vlistInqVarMissval(vlistID, varID);
616
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
617
  int tsid     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
618

619
  off_t currentfilepos = fileGetPos(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620

621
  /* NOTE: tiles are not supported here! */
622
623
  int recID = streamptr->vars[varID].recordTable[0].recordID[levID];
  off_t recpos = streamptr->tsteps[tsid].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
624
  fileSetPos(fileID, recpos, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
625
626
  if ( srvRead(fileID, srvp) < 0 ) abort();
  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
628
629
630
631
632
  srvInqHeader(srvp, header);
  srvInqDataDP(srvp, data);

  fileSetPos(fileID, currentfilepos, SEEK_SET);

  *nmiss = 0;
633
  for ( size_t i = 0; i < gridsize; i++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
635
636
637
638
639
640
641
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }
}


642
void srvReadVarDP(stream_t *streamptr, int varID, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
643
644
645
646
{
  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);

  int vlistID = streamptr->vlistID;
647
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
648
649
650
651
652
653
654
  size_t nlevs    = (size_t) streamptr->vars[varID].recordTable[0].nlevs;

  for ( size_t levID = 0; levID < nlevs; levID++)
    srvReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
655
void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
656
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
657
  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
658

659
660
661
662
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
  int tsID     = streamptr->curTsID;
  int gridID   = vlistInqVarGrid(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
663

664
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
665
  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
666

Uwe Schulzweida's avatar
Uwe Schulzweida committed
667
  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
668
  header[0] = pnum;
669
  header[1] = (int)(zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
670
671
  header[2] = streamptr->tsteps[tsID].taxis.vdate;
  header[3] = streamptr->tsteps[tsID].taxis.vtime;
672

673
674
  size_t xsize = gridInqXsize(gridID);
  size_t ysize = gridInqYsize(gridID);
675
  if ( xsize == 0 || ysize == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
676
    {
677
678
      xsize = gridInqSize(gridID);
      ysize = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
679
    }
680
  if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
681
  if ( gridInqSize(gridID) != xsize*ysize )
682
    Error("Internal problem with gridsize!");
683

684
  cdi_check_gridsize_int_limit("SERVICE", gridInqSize(gridID));
685

686
687
  header[4] = xsize;
  header[5] = ysize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
688
689
690
  header[6] = 0;
  header[7] = 0;

691
  int datatype = vlistInqVarDatatype(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
692

Uwe Schulzweida's avatar
Uwe Schulzweida committed
693
  srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
694
695
  srvp->dprec = srvDefDatatype(datatype);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
696
697
698
  srvDefHeader(srvp, header);
  srvDefDataDP(srvp, data);
  srvWrite(fileID, srvp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
700
701
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
702
void srvWriteVarDP(stream_t *streamptr, int varID, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
703
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
704
  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
705

Uwe Schulzweida's avatar
Uwe Schulzweida committed
706
  int vlistID = streamptr->vlistID;
707
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
708
  size_t nlevs    = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
709

Uwe Schulzweida's avatar
Uwe Schulzweida committed
710
711
  for ( size_t levID = 0; levID < nlevs; levID++ )
    srvWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
712
713
714
}

#endif /* HAVE_LIBSERVICE */
715

716
717
718
719
720
721
722
723
724
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */