stream_srv.c 16.6 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
22
static
int srvInqDatatype(int prec)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
23
{
24
  return (prec == EXSE_DOUBLE_PRECISION) ? CDI_DATATYPE_FLT64 : CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25
26
}

27
28
static
int srvDefDatatype(int datatype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
29
{
30
  if ( datatype == CDI_DATATYPE_CPX32 || datatype == CDI_DATATYPE_CPX64 )
31
    Error("CDI/SERVICE library does not support complex numbers!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
32

33
34
  if ( datatype != CDI_DATATYPE_FLT32 && datatype != CDI_DATATYPE_FLT64 )
    datatype = CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35

36
  return (datatype == CDI_DATATYPE_FLT64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
37
38
}

39
/* not used
40
int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
43
{
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
44
  int icode, ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
45
46
47
  int zaxisID = -1;
  int header[8];
  int vlistID;
48
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
49

50
51
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
52
53
54
55
56
57
58
59
60

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

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

  srvInqHeader(srvp, header);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
61
  icode  = header[0];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
62
63
  ilevel = header[1];

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

66
  if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
67
68
69
70

  zaxisID = vlistInqVarZaxis(vlistID, *varID);

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

72
  return 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
73
}
74
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
75

76
void srvReadRecord(stream_t *streamptr, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
77
{
78
79
80
81
82
83
84
  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
85
86
87

  fileSetPos(fileID, recpos, SEEK_SET);

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

92
  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
94
95
  srvInqHeader(srvp, header);
  srvInqDataDP(srvp, data);

96
97
  double missval = vlistInqVarMissval(vlistID, varID);
  int gridID  = vlistInqVarGrid(vlistID, varID);
98
  size_t size = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99

Uwe Schulzweida's avatar
Uwe Schulzweida committed
100
  streamptr->numvals += size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
101
102

  *nmiss = 0;
103
  for ( size_t i = 0; i < size; i++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104
105
106
107
108
109
110
111
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }
}


112
void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
113
{
114
  streamFCopyRecord(streamptr2, streamptr1, "SRV");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
115
116
117
}


118
void srvDefRecord(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
119
{
120
  Record *record = streamptr->record;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121

122
123
  int pdis, pcat, pnum;
  cdiDecodeParam(record->param, &pnum, &pcat, &pdis);
124
125

  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
126
  header[0] = pnum;
127
128
129
  header[1] = record->level;
  header[2] = record->date;
  header[3] = record->time;
130

131
  int gridID = record->gridID;
132
133
  size_t xsize = gridInqXsize(gridID),
         ysize = gridInqYsize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
134
135
136
137
138
  if ( xsize == 0 || ysize == 0 )
    {
      xsize = gridInqSize(gridID);
      ysize = 1;
    }
139
  if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
140
  if ( gridInqSize(gridID) != xsize*ysize )
141
    Error("Internal problem with gridsize!");
142

143
  cdi_check_gridsize_int_limit("SERVICE", gridInqSize(gridID));
144
145
146

  header[4] = (int)xsize;
  header[5] = (int)ysize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
147
148
149
  header[6] = 0;
  header[7] = 0;

150
151
  srvrec_t *srvp = (srvrec_t*) record->exsep;
  srvp->dprec = srvDefDatatype(record->prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
152
153
154
155
156

  srvDefHeader(srvp, header);
}


157
void srvWriteRecord(stream_t *streamptr, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
158
{
159
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
  srvDefDataDP(srvp, data);
161
  srvWrite(streamptr->fileID, srvp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
162
163
}

164
static
165
void srv_add_record(stream_t *streamptr, int param, int level, size_t xsize, size_t ysize,
166
                    size_t recsize, off_t position, int prec)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
167
{
168
169
170
  const int vlistID = streamptr->vlistID;
  const int tsID    = streamptr->curTsID;
  const int recID   = recordNewEntry(streamptr, tsID);
Thomas Jahns's avatar
Thomas Jahns committed
171
  record_t *record = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
172

Thomas Jahns's avatar
Thomas Jahns committed
173
174
175
176
  record->size     = recsize;
  record->position = position;
  record->param    = param;
  record->ilevel   = level;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
177

178
  grid_t *grid = (grid_t*) Malloc(sizeof(*grid));
179
  grid_init(grid);
180
  cdiGridTypeInit(grid, GRID_GENERIC, xsize*ysize);
181
182
  grid->x.size = xsize;
  grid->y.size = ysize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
183
  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
184
  const int gridID = gridAdded.Id;
185
  if (!gridAdded.isNew) Free(grid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
186

187
188
  const int leveltype = ZAXIS_GENERIC;
  const int datatype = srvInqDatatype(prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
189

190
  int varID, levelID = 0;
191
  varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
192
	       datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
193
               NULL, NULL, NULL, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
194

195
  xassert(varID <= SHRT_MAX && levelID <= SHRT_MAX);
Thomas Jahns's avatar
Thomas Jahns committed
196
197
  record->varID   = (short)varID;
  record->levelID = (short)levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198

Uwe Schulzweida's avatar
Uwe Schulzweida committed
199
200
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
201
202

  if ( CDI_Debug )
203
    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
204
205
}

206
static
207
208
void srvScanTimestep1(stream_t *streamptr)
{
209
  DateTime datetime0 = { LONG_MIN, LONG_MIN };
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
  off_t recpos;
211
  srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
212

Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214

215
  int tsID  = tstepsNewEntry(streamptr);
216
  if ( tsID != 0 ) Error("Internal problem! tstepsNewEntry returns %d", tsID);
217
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
218

219
  const int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220

221
  int nrecs = 0;
222
  while ( true )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
224
    {
      recpos = fileGetPos(fileID);
225
      if ( srvRead(fileID, srvp) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
226
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
227
	  streamptr->ntsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
228
229
230
	  break;
	}

231
      const size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
232

233
234
      int header[8];
      srvInqHeader(srvp, header);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
235

236
237
238
239
240
241
242
243
      const int prec   = srvp->dprec;
      const int rcode  = header[0];
      const int rlevel = header[1];
      const int vdate  = header[2];
      const int vtime  = header[3];
      const int rxsize = header[4];
      const int rysize = header[5];
      const int param  = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
      DateTime datetime = { .date = vdate, .time = vtime };
Uwe Schulzweida's avatar
Uwe Schulzweida committed
245

Uwe Schulzweida's avatar
Uwe Schulzweida committed
246
247
      if ( nrecs == 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
248
249
250
	  datetime0 = datetime;
          taxis->vdate = vdate;
          taxis->vtime = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
251
252
253
	}
      else
	{
254
          record_t *records = streamptr->tsteps[tsID].records;
255
	  for ( int recID = 0; recID < nrecs; recID++ )
256
            if ( param == records[recID].param && rlevel == records[recID].ilevel )
257
              goto tstepScanLoopFinished;
258

259
	  if ( datetimeDiffer(datetime, datetime0) )
260
	    Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
261
262
263
264
265
	}

      nrecs++;

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

268
      srv_add_record(streamptr, param, rlevel, rxsize, rysize, recsize, recpos, prec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
269
270
    }

271
  tstepScanLoopFinished:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
272
  streamptr->rtsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
273

274
  cdi_generate_vars(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275

276
  const int taxisID = taxisCreate(TAXIS_ABSOLUTE);
277
278
279
  taxis->type = TAXIS_ABSOLUTE;
  taxis->rdate = taxis->vdate;
  taxis->rtime = taxis->vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
280

281
  const int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
282
283
  vlistDefTaxis(vlistID, taxisID);

284
  vlist_check_contents(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
285

286
  streamScanResizeRecords1(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
287

288
  streamScanTsFixNtsteps(streamptr, recpos);
289
  streamScanTimeConstAdjust(streamptr, taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
290
291
}

292
static
293
294
int srvScanTimestep2(stream_t *streamptr)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
296
  int header[8];
  off_t recpos = 0;
297
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
298
299

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

301
302
  const int vlistID = streamptr->vlistID;
  const int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
303

304
305
  const int tsID = streamptr->rtsteps;
  if ( tsID != 1 ) Error("Internal problem! unexpected timestep %d", tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
306

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

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

311
  cdi_create_records(streamptr, tsID);
312
  record_t *records = streamptr->tsteps[tsID].records;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313

314
  const int nrecords = streamScanInitRecords2(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315

316
  for ( int rindex = 0; rindex <= nrecords; rindex++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
317
318
    {
      recpos = fileGetPos(fileID);
319
      if ( srvRead(fileID, srvp) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
320
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
321
	  streamptr->ntsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
322
323
324
	  break;
	}

325
      const size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
326

327
      srvInqHeader(srvp, header);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328

329
330
331
332
333
      const int rcode  = header[0];
      const int rlevel = header[1];
      const int vdate  = header[2];
      const int vtime  = header[3];
      const int param  = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334

Uwe Schulzweida's avatar
Uwe Schulzweida committed
335
336
337
338
339
340
341
      if ( rindex == 0 )
	{
	  taxis->type  = TAXIS_ABSOLUTE;
	  taxis->vdate = vdate;
	  taxis->vtime = vtime;
	}

342
343
      bool nextstep = false;
      int recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
344
345
      for ( recID = 0; recID < nrecords; recID++ )
	{
346
	  if ( param == records[recID].param && rlevel == records[recID].ilevel )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
347
	    {
348
	      if ( records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
349
		{
350
		  nextstep = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
351
352
353
		}
	      else
		{
354
		  records[recID].used = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
		  streamptr->tsteps[tsID].recIDs[rindex] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
356
357
358
359
360
361
		}
	      break;
	    }
	}
      if ( recID == nrecords )
	{
362
	  Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
363
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364
365
366
367
368
	}

      if ( nextstep ) break;

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

371
      if ( param != records[recID].param || rlevel != records[recID].ilevel )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
372
	{
373
	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
374
		  tsID, recID, records[recID].param, param, records[recID].ilevel, rlevel);
375
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
376
377
	}

378
379
      records[recID].position = recpos;
      records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
380
381
    }

382
383
  int nrecs = 0;
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
384
    {
385
      if ( ! records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
386
	{
387
          vlistDefVarTimetype(vlistID, records[recID].varID, TIME_CONSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
388
389
390
391
392
393
	}
      else
	{
	  nrecs++;
	}
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
394
  streamptr->tsteps[tsID].nrecs = nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395

Uwe Schulzweida's avatar
Uwe Schulzweida committed
396
  streamptr->rtsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397

398
  streamScanTsFixNtsteps(streamptr, recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
399

400
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
402
403
}


404
int srvInqContents(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
405
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
406
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
407

408
409
  srvScanTimestep1(streamptr);

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

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

414
  return status;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
415
416
}

417
static
418
long srvScanTimestep(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
419
420
421
{
  int header[8];
  off_t recpos = 0;
422
  int nrecs = 0;
423
  void *srvp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
424

425
  int tsID = streamptr->rtsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
426
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
427

Uwe Schulzweida's avatar
Uwe Schulzweida committed
428
  if ( streamptr->tsteps[tsID].recordSize == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
    {
430
      cdi_create_records(streamptr, tsID);
431
      record_t *records = streamptr->tsteps[tsID].records;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
432

433
      nrecs = streamScanInitRecords(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
434

435
      const int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
436

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

439
      for ( int rindex = 0; rindex <= nrecs; rindex++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440
441
	{
	  recpos = fileGetPos(fileID);
442
	  if ( srvRead(fileID, srvp) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
444
	      streamptr->ntsteps = streamptr->rtsteps + 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
445
446
447
	      break;
	    }

448
	  const size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
449

450
	  srvInqHeader(srvp, header);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
451

452
453
454
455
456
	  const int rcode  = header[0];
	  const int rlevel = header[1];
	  const int vdate  = header[2];
	  const int vtime  = header[3];
	  const int param  = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
457

458
459
	  // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
	  if ( rindex == nrecs ) continue;
460
	  const int recID = streamptr->tsteps[tsID].recIDs[rindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
461
462
463
464
465
466
467

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

469
          if ( param != records[recID].param || rlevel != records[recID].ilevel )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
470
	    {
471
	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
472
		      tsID, recID, records[recID].param, param, records[recID].ilevel, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
473
	      Error("Invalid, unsupported or inconsistent record structure!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474
475
	    }

476
477
	  records[recID].position = recpos;
	  records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
478
479

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
483
      streamptr->rtsteps++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484

Uwe Schulzweida's avatar
Uwe Schulzweida committed
485
      if ( streamptr->ntsteps != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
486
	{
487
	  tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
	  if ( tsID != streamptr->rtsteps )
489
	    Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
490

491
	  streamptr->tsteps[tsID-1].next   = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
	  streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
493
494
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
495
496
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
498
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
499
  if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
    {
501
      Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
502
      streamptr->ntsteps = tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
503
504
    }

505
  return streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
506
507
508
}


509
int srvInqTimestep(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
510
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
  if ( tsID == 0 && streamptr->rtsteps == 0 )
512
    Error("Call to cdiInqContents missing!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513
514

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

517
518
  long ntsteps = CDI_UNDEFID;
  while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == CDI_UNDEFID )
519
    ntsteps = srvScanTimestep(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
520

521
  int nrecs = 0;
522
  if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
523
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525
      streamptr->curTsID = tsID;
      nrecs = streamptr->tsteps[tsID].nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
526
527
    }

528
  return nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
530
531
}


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

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

538
539
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
540
  /* NOTE: tiles are not supported here! */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
541
  double missval = vlistInqVarMissval(vlistID, varID);
542
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
543
  int tsid     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
544

545
  off_t currentfilepos = fileGetPos(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546

547
  /* NOTE: tiles are not supported here! */
548
549
  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
550
  fileSetPos(fileID, recpos, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
551
552
  if ( srvRead(fileID, srvp) < 0 ) abort();
  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
553
554
555
556
557
558
  srvInqHeader(srvp, header);
  srvInqDataDP(srvp, data);

  fileSetPos(fileID, currentfilepos, SEEK_SET);

  *nmiss = 0;
559
  for ( size_t i = 0; i < gridsize; i++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
561
562
563
564
565
566
567
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }
}


568
void srvReadVarDP(stream_t *streamptr, int varID, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
569
570
571
572
{
  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);

  int vlistID = streamptr->vlistID;
573
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
575
576
577
578
579
580
  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
581
void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
583
  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
584

585
586
587
588
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
  int tsID     = streamptr->curTsID;
  int gridID   = vlistInqVarGrid(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
589

590
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
591
  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
592

Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
  int header[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
594
  header[0] = pnum;
595
  header[1] = (int)(zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
596
597
  header[2] = streamptr->tsteps[tsID].taxis.vdate;
  header[3] = streamptr->tsteps[tsID].taxis.vtime;
598

599
600
  size_t xsize = gridInqXsize(gridID);
  size_t ysize = gridInqYsize(gridID);
601
  if ( xsize == 0 || ysize == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
602
    {
603
604
      xsize = gridInqSize(gridID);
      ysize = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
    }
606
  if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1;
607
  if ( gridInqSize(gridID) != xsize*ysize )
608
    Error("Internal problem with gridsize!");
609

610
  cdi_check_gridsize_int_limit("SERVICE", gridInqSize(gridID));
611

612
613
  header[4] = xsize;
  header[5] = ysize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
614
615
616
  header[6] = 0;
  header[7] = 0;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
619
  srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
621
  srvp->dprec = srvDefDatatype(datatype);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
622
623
624
  srvDefHeader(srvp, header);
  srvDefDataDP(srvp, data);
  srvWrite(fileID, srvp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
625
626
627
}


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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
632
  int vlistID = streamptr->vlistID;
633
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
  size_t nlevs    = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635

Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
637
  for ( size_t levID = 0; levID < nlevs; levID++ )
    srvWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
638
639
640
}

#endif /* HAVE_LIBSERVICE */
641

642
643
644
645
646
647
648
649
650
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */