aboutsummaryrefslogtreecommitdiff
path: root/src/SockIOreader.hh
blob: 19f16bfcd9620286aab3edc5276d08b39aa9499d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef __SOCKIOREADER_HH_
#define __SOCKIOREADER_HH_

#include "Arch.h"
#include "IO.hh"
#include "IEEEIO.hh"
#include "RawTCP.H"
#include "PortMux.H"

/*=========================================================================
class: SockIOreader
description: Implements IEEEIO IO interface described in 
	http://bach.ncsa.uiuc.edu/IEEEIO over a socket connection.
	The interface is read-only.  This is the client and the SockIOwriter
	is a server which sends data out to the SockIOreader from the
	application.  All data is cached in an IEEEIO file on the client
	end (this side) for rapid local access by the client application.
	
Problems: The background IO methods are kludgy at best.  Currently it
	depends on SigIO in order to determine when some new data is availible
	on the socket.  However, it is very difficult to demultiplex that 
	signal when you have more than one instance of SockIOreader active.

  Need a garaunteed method to determine if a client has dropped it connection.
  A dropped connection can cause a lockup if it occurs during a blocking read.
  This needs to have a SigALRM in order to recover from such errors.
===========================================================================*/
//void IOsigHandler(int sig); // prototype

class SockIOreader : public IObase {

	// The following data structures come straight out of IEEEIO and
	// are necessary for interpreting the data coming in through the
	// socket connection.  Other than that, you can completely ignore them
	// or refer directly to the docs in IEEEIO.hh if you really feel the
	// need to understand what is happening here.
  enum RecordType {DataRecord=1,AnnotationRecord,AttributeRecord};

#ifdef	__hpux
// silly HPUX compiler doesn't allow FileHdr access to btorder...
public:
#endif

	// Structure for determining the native byte-order of data stored in the file
  union btorder {
    char c[4]; // write as int, read as int
    int  i;
  };

	// File header describes how many data records are in the file and what the
	// version of the IEEEIO wrote this data.
  struct FileHdr {
    // do magic twice so we can figure out which byte-order
    // the current machine is in addition (without hardcoding) in
    // addition to which byte order the file is in
    btorder magic;
    btorder byteorder;
    Long ndatasets;
    short majorversion;
    short minorversion;
  };

	// At the head of each data or attribute record.  Identifies the type of
	// record and how large it is so that it can be skipped if it doesn't contain
	// relevant data.
  struct RecordHdr {
    int recordtype;
    Long recordsize;
    int sequenceID;
  };

	// This immediately follows a RecordHeader if the record contains raw data. 
	// this stores the number of dimensions and the datatype of the record
  struct DataRecordHdr {
    Long datasize;
    int numbertype;
    int rank;
  };
	
	// The immediately follows the RecordHeader if the record contains a
	// NetCDF attribute.  It stores the datatype, name and datasize of the
	// attribute vector.
  struct AttributeRecordHdr {
    Long datasize;
    int numbertype;
    int namesize; // attributes are named
  };

  char scratchfilename[256]; // name of scratchfile in which to store the IEEEIO data
  IEEEIO *scratchfile; // IEEEIO file descriptor for the scratch file
  FastTCPserver ServerPort; // Server port from which connections from SockIOwriters are accept()'ed
  RawTCPport *connected_client; // Only one client can be attached at a time.
  //**** State information for IEEEIO management
  RecordHdr current_rec; 
  DataRecordHdr current_data_rec;
  AttributeRecordHdr current_att_rec;
  //**** master_mux is the serverport (accept calls) and mux is the connected ports (new data)
  PortMux master_mux,mux;
  int n_complete_ds,current_ds,last_ds; // number of completely received datasets + current&last
  int pending; // Flag if a new dataset transfer is currently in progress in the background.

  // Make this functionality inacessible since this class is read-only.
  virtual int write(IObase::DataType typeID,int rank,CONST int *dims,void *data){return 0;}
  virtual int writeAnnotation(CONST char *annotation){return 0;}
  virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data){return 0;}
  virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims){return 0;}
  virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims){return 0;}
  virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data){return 0;}
  virtual int writeStream(void *data,int length){return 0;}
protected:
  int blockingRead(void *buffer,int size); // kludge
  //static void halt(){}
  //static int sendInProgress(){return 0;}
public: 
  void sigHandler(int sig);
  friend void IOsigHandler(int *handler); // give the sighandler internal access to sigHandler();
  //------------------------core stuff.....................
  SockIOreader(CONST char *scratchfilenm,int port); 
  SockIOreader(CONST char *scratchfilenm,int port,int tcpwindowsize);
  virtual ~SockIOreader();
  // should check server status too
  virtual int isValid();
  // could use overloading to differentiate type here... (but I'm going simple)
  virtual int readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims=3);
  virtual int read(void *data);
  virtual int seek(int dataset_index);
  virtual int nDatasets();
  virtual int readAnnotationInfo(int number,int &length);
  virtual int readAnnotation(int number,char *annotation,int maxsize=128);
  virtual int nAnnotations();
  virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128);
  virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem);
  virtual int readAttribute(int number,void *data);
  virtual int nAttributes();
  //-----------------Chunking Utilities..................
  //---Not implemented quite yet on server side, but you can read in chunks on client.
  virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data);
  virtual int readStream(void *data,int length){return 0;}
};

#endif