DD_comm.h 17.9 KB
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 142 143 144 145 146 147 148 149 150 151 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 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 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 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 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 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
/*=================================================================================
 *               DD SYSTEM base package
 *              DD_Server DD_Client library
 *                  DD_comm.h
 *                   V. 6.0
 * Changes listing:
 *      Feb 27 1995 - V 1.0
 *      13 Apr. 2002 - changed for NetCDF 3.3
 *      03 Oct. 2002 - v.4.0  Fedorov, communication ideology is changed
 *      Oct 31, 2002 - V.4.1  Fedorov, UserName, UserHost and UserID transferred into DD_Access.h
 *      May 7, 2003  - V.4.2  Fedorov, The Cash structure is changed (flag of open file )
 *      June 17, 2003 - V.4.3  Fedorov, The Maximal Packet Size is changed
 *      Nov 18, 2004 - V.4.4  Fedorov,  Some changes
 *      Aug 17, 2005 - V.4.5  Fedorov,  Cach Time constant is changed
 *      Jun 17, 2007 - V.4.6  Fedorov, New requestes and external executables
 *      Aug 01, 2007 - V.4.7  Fedorov, Cache length = 20, New DD_Var_t structure
 *      Sep 20, 2007 - V.5.0  Fedorov, Update Time Info library now in the separate file
 *      Sep 23, 2007 - V.5.1  Fedorov, New interface of SetTime
 *      Sep 25, 2007 - V.5.2  Fedorov, Individual minimal gap
 *      Oct 08, 2007 - V.5.3  Budnik,  php createVI.php <baseID> <remSetID> <ddSetID>
 *      Jan 25, 2008 - V.5.3.1 Budnik, min data gap = 1 day!!!!
 *      May 22, 2008 - V.5.4 Fedorov, DD_Var_t has a LockStartTime value
 *      May 27, 2008 - V.5.5 Fedorov, Maximal tracnsmition buffer
 *      Sep 19, 2008 - V.5.6 MAXVARLENGTH=64 REQUESTLENGTH 184
 *      Dec 15, 2012 - V.6.0 New multiparam Get_MultiData() function
 *===================================================================================*/

#include <stdio.h>
#include <sys/errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include "DD_Access.h"

#ifdef SOLARIS
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>      /* internet stile addres */
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/rpc.h>
#endif /* SOLARIS */

#ifdef HPUX
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/un.h>
#include <rpc/xdr.h>
#include <rpc/rpc.h>
#endif

#ifdef OSF1
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <rpc/xdr.h>
#endif /* OSF1 */

#ifdef LINUX
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#endif /* LINUX */

#ifdef SUNOS
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <netinet/in.h>
#include <netdb.h>
#include <rpc/xdr.h>
#endif /* SUNOS */

/*----------------- Defenitions of request and server replies --------------------*/
/* 1. Data manipulation requests  */
#define OPENINSREQ  0     /* Open virtual instrument    */
#define DATAINFOREQ 1     /* Request of constant info */
#define TIMESETREQ  2     /* Position of pointer by StartTime*/
#define DATAGETREQ  3     /* Data request by time interval */
#define CLOSEINSREQ 4     /* Request to close virtual instrument */
#define MOVPOINTREQ 5     /* Move the pointer od data request*/
#define ADDVIREQ    6     /*  Add New virtual instrument */

/*  2. Security requests */
#define GETTICKETREQ 10
#define SHOWTICKETREQ 11

/*-------- Some constants ------------------*/
#define EMPTY       0     /* Filler of the trailer */
#define FILEACCMARG 1     /* The minimum time from the last access to remove this file */

/*------------ Important lengths and pathes ----------------*/
#define PROTOCOL        0     /* protocol TCP  */
#define REPLYLENGTH    12     /* Length of header of reply packet */
#define REQUESTLENGTH 196     /* Length of request packets MAXSETLENGTH + 2*MAXVARLENGTH + 16 */
#define MAXVARLENGTH   64     /* Length (with \0) of Variable Name */
#define MAXSETLENGTH   52     /* Max Length of VI name */
#define PATHLENGTH    128     /* Length of complete path */
#define MAXFILENAME    32     /* The maximal length of the data file (info, cach, times as well)*/
#define REFNAME "/refer.nc"   /* path name for databse  refer file */
#define CASHLEN 20            /* Length of cash array */
#define TRY 100               /* How many tymes to ask the socket */
#define MAXPACKSIZE  5000000  /* Maximal size of one packet of transmission in bytes */
#define MAXCOMMANDL   300     /* Command in system() maximal length
/*-------------------------------------------------
 * XDR length to calcolate the total len
 *-------------------------------------------------*/
#define XDRINTLEN 4
#define XDRFLOATLEN 4
#define XDRDOUBLELEN 8
// String length is counted as 4B + N + r (to completed to 4 bytes)

/*------------ List of External Call of DD_Server and ERRORS -------------------*/
#define ADDDATASETCALL "php %s/CALLEXT/createVI.php %s %s %s"        /* Format to call to create new VI */
#define GETNEWDATACALL "php %s/CALLEXT/getData.php  %s %s %s %s %s &"  /* Format to call to get new data  */
#define NOPHP     32512
#define NOSCRIPT  256
#define PHPOK     0

/*------ Constant to understand data availabilities -------------------------------*/
#define GLOBSTARTNAME "GlobalStart"
#define GLOBSTOPNAME "GlobalStop"
#define SAMPLNAME "MinSampling"
#define REMARCHNAME "DataBaseID"
#define REMINSTNAME "DataSetID"
#define MINGAP    86400.0 /*Seconds. The minimal time gap to set up the flag DATAGAP */
#define REQTIMEINT 86400.0 /* One day, +/- of request time interval */
#define ISOTIMEF  "%4u%*1c%2u%*1c%2u%*1c%2u%*1c%2u%*1c%2u%*1c%3u" /* Format to READ time in ISO format */
#define ISOTIMEP  "%04u-%02u-%02uT%02u:%02u:%02u.%03uZ" /* Format to PRINT time in ISO format */
#define NODATASTR "NODATA"
#define DIRLOCK "LOCK"

#define QUANTOFFSET 0.01
/*------------- More internal specifications -----------------------*/
/*
 *   See ../DOC/TECHDOC/DDGenProt.html (lyx)
 */

/* Reply variables:
 * Error - negative value described in DD.h
 * Type - int (see DD.h)
 * Dim_Number - int ( the dimension (vector, matrix, cube, etc) ov the variable)
 * Data_Size - int (the size of the data packet in bytes)
 * RemID     - int (number of virtual instruments still open in this session)
 * Dim       - int (the particular dimension )
 * LastPacketFlag - int ( == OK in this packet is last, or MOREDATA)
 * Data - array of Type of Dim X Dim X....X Dim size
 *                         --------------------
 *                             Dim_Number
 * DataPacket:
 *
 * <LastPacketFlag>             |
 * <Dim>    |                   |
 * <.....>  |  Dim_Number       |  Data_Size bytes
 * <Dim>    |                   |
 * <data>                       |
 * .....  | only for real data  |
 * <data> |                     |
 *
 * Note is the value is scalar - the Dim = 0 (???)
 */

/* REPLY SPECIFICATION
 *
 * Reply consists Header 12 bytes length and Data Block
 *
 * on Open Virtual instrument:
 * <OPENINSREQ><ID/Eroor><EMPTY><EMPTY>
 * on Constant Info request:
 * <DATAINFOREQ><Type/Error><Dim_Number><Data_Size><DataPacket>
 * on Set pointer by StartTime:
 * <SETTIMEREQ><EMPTY/Error><EMPTY><EMPTY>
 * on Get Data by TimeInt :
 * <DATAGETREQ><Type/Error><Dim_Numbers><Data_Size><LastRecordFlag><DataPacket>
 * on Move pointer with records number
 * <MOVPOINTREQ><EMPTY/Error><EMPTY><EMPTY>
 * on Close Virtual Instrument
 * <CLOSEINSREQ><RemID/Error><EMPTY><EMPTY>
 */

/*-------------------- TYPEDEF ---------------------------*/
typedef struct {
                 char CacheFilePath[PATHLENGTH];
                 char names[CASHLEN][MAXSETLENGTH];
                 long times[CASHLEN];
                 int FileOpen[CASHLEN];    /* 1 if file is open */
                 int ID;                   /* ID of open cach file */
                 int nameID;               /* ID of names array */
                 int timeID;               /* ID of times array */
                 int fopenID;              /* ID of fopen flag */
               } DD_cash_t;      /* The structure holding cash informaton
                                  * of particular virtual instrument DataBase
                                  */

/*
 * This structure corresponds to ONE requested variable
 * of some Virtual instrument
 */
typedef struct { char  InstrName[MAXSETLENGTH]; /* Virtual Instrument Name */
                 char path[PATHLENGTH]; /* Path to directory of open virtual instrument */
                 /*---------------------------------------
		  *              Cache part
		  *--------------------------------------*/
                 DD_cash_t Cash;        /* Cash holder */
                 int CurrCushN;         /* Current cash pointer */
                 /*--------------------------------------
		  *  This is the part of open data file and corresponding data set
		  *-------------------------------------*/
                 int ncID;              /* ID of open nc_file */
                 size_t nc_rec;         /* the current record number nc_file */
                 size_t Maxnc_rec;      /* Maximum of records number in in the current nc file */
                 DD_data_t *VarData;    /* Static pointer. Variables Holder */
		 size_t ParamSize;      /* Number or requested variables to save */
                 /*---------------------------------------------
		  *    This is part of times file of given VI
		  *--------------------------------------------*/
                 char TimesFileName[PATHLENGTH];
                 double SDTime;         /* Requested Start Time in double form */
                 double FDTime;         /* Requested Stop Time in double form */
                 double CDTime;         /* Current Time in double form */
                 int tmID;              /* ID of "times" file of this  virtual instrument*/
                 int NameID;            /* ID of FileName variable in times file */
                 int StartID;           /* ID of Start variable in times file */
                 int StopID;            /* ID of Stop variable in times file */
                 size_t TimeRecNumber;  /* Current Record number in the "times" file */
                 size_t MaxTimeRecNum;  /* Maximum records number in the "times" file */
                 int RValidMin;      /* Minimal record with valid data */
                 int RValidMax;      /* Maximal record with valid data */
                 double MinValidTime;
                 double MaxValidTime;   /* Start of RValidMin, and stop of RValidMax */
                 int CurrRmin;       /* Sure that looking time is greater than stop; -1 if NOT */
                 int CurrRmax;       /* Sure that looking time is less than start; -1 if NOT */
                 /*------- Working with external Data Base ------------------------------*/
                 int VILocked;       /* Flag to show that request to remote database has been sent */
                 time_t LockStartTime; /* Value to calculate a time elapsed from lock made by THIS VI */
                 /*---------- This is the part of Info file of given VI -----------------*/
                 int attrID;            /* ID of constant information nc_file */
                 char AttrName[PATHLENGTH]; /* Name of constant information file */
                 DD_data_t AttrData;    /* Dimensions of Attributes */
                 /*---- Part concerning External call ------------------*/
                 double MinGap;         /* The minimal gap between two files */
                 double GlobalStart;    /* The principal begin of data */
                 double GlobalStop;     /* The principal end of data */
                 char BaseName[MAXSETLENGTH]; /* The name of external data archive */
                 char RemSetID[MAXSETLENGTH]; /* The name of VI in exterval archiving */
                 int ExtCallAllowed; /* 1 If Server can call external archiving */
                 /*------------ Flow Control -----------------------------*/
                 int LastPacketFlag;  /* OK - request is completed,
                                       * MOREDATA - one or several blocks expected,
                                       * MOREDELAY - wait, system is blocked */
                 int LastFileStatus;    /* The file status after the last SetNewFile */
                 int NewFile;           /* 1 if File was changed, VI has to be refreshed*/
                 int NewFileWasOpen;    /* 1 if the original position of pointer
                                          * (in data file, times file) was lost after open
                                          * a new data file */
              } DD_Var_t;

/*---------------- Usefull enumerations ---------------------*/
enum SearchRet {REACHLEFT, REACHRIGHT, OKLEFT, OKRIGHT};
  /*
   * enumerate of the status of time inteval searching
   * NOONEDATA - no data at al in this VI
   * INSIDE - CTime is inside valid data interval (tolerance is MINGAP)
   * DATAATRIGHT, DATAATLEFT - Valid interval is on the right/left from CTime
   */
enum SearchIntRet {NOONEDATA, INSIDE, DATAATRIGHT, DATAATLEFT, IDLE};

/* Return function IsTimesLocked */
enum LockStatus {NOLOCK, LOCKED, LOCKREMOVED};


/*------------------ Function for Server ---------------------*/
extern int OpenInstr(char *InstrName);

/*
 * Init shared memory for cache system
 */
extern void Cache_Init();

/*
 * Free shared memory used for cache system
 */
extern void Cache_Free();

/*
 * Free shared memory used for cache system
 */
extern int Cache_RequestDataFileAccess(DD_Var_t *D, char* dataFileName);

/*
 * Free shared memory used for cache system
 */
extern int Cache_ReleaseDataFileAccess(DD_Var_t *D);

/*
 * Close cache file
 */
extern int Cache_CloseFile(DD_Var_t *D);

/*
 * Open Virtual instrument by name and returns the ID
 * Returns negative value in case of error (see DD.h)or OK
 */
extern int GetAttribute(int ID, char *Name);
/*
 * Variable - address of structure with variable description
 * Name - name of attribute
 * Returns OK or an error (see DD.h)
 */
extern int GetMultiData(int ID, int VarSize, char **VarNames, char *TimeInterval, int BackFlag);
/*
 * VarSize - size of the array of Names
 * Names - array of strings with names of requested variables,
 * TimeInterval - Time in DD_time.h style
 * Returns  negative value in case of error (see bellow)
 * Returnes MOREDATA if "there is more data", and OK if data is finished.
 */

extern int SetTime(DD_Var_t *D, double CTime);
/*#################################################################
 *                      SET TIME
 * Set time and try to open appropriate data file. If not try to
 * call external archive
 * D - address of VI holder
 * Time -  Time in DD_time.h style
 * Return:
 * OK
 * NOID - call with uncorrect VI holder
 * OUTOFTIME - Requested time is out of General time limitation
 * WAITEXTCALL - Server sent request to external archive
 * TRYAGAIN - VI is blocked by call to external database
 * NODATAATTIME - request time is inside NODATA time interval
 * some return of SetNewFile(); see ...
 *#################################################################*/

extern int CloseID(int ID);
/* ID - integer identificator of opened Data Set
 * Returns number of remained IDs of this communication seasson
 * in case of 0 the server closes this comminication session
 */

int SetNewFile(DD_Var_t *D, int N);
/*
 * Function tries to get new data for the gap beetween files, or just
 * open a new data file according to offset N referring to current position in the times file.
 * The current position changed if file is succesefully open.
 * Return values:
 * OK
 * OUTOFTIME - next interval exceeeds GlobalStart/Stop
 * TIMEINEMPTY - next interval marked as "NODATA"
 * TRYAGAIN - the VI is blocked while new data is arriving
 * WAITEXTCALL - new data is requested
 * CACHTOOREC - now free space in the CACH
 * CHACHERR - unrecovable error in CACH
 * DATAFILEERR - unrecovable error in data file
 */

size_t MaxRecord(int ncID);
/*
 * Inspect all variables and dimensions of the file (exept Time associated) and
 * returm maximal record number to transmit
 */

/*------------------ Global constants ----------------------------------*/
static u_int xdrlen[] = {4,4,4,8,4};
static size_t unixlen[] = {sizeof(char),sizeof(int),sizeof(float),sizeof(double),sizeof(short)};
static  bool_t ( *ConvFunc[5])() = {xdr_char, xdr_int, xdr_float, xdr_double, xdr_short};

/*------------------ Global data variable for entire  session --------------------*/
extern   DD_Var_t **DD_Var ; /* Actually this variable is implimented
                                                * in DD_GetData.c . The dimension of this array is defined
                                                * by sysconf(_SC_OPEN_MAX)*/
extern size_t MaxIDNumber;        /* Size of DD_Var array. Defined actually in  DD_GetData.c  */

/*
 * Fuctions prototypes in ExtDataRequest.c file
 */
/*======================================================================
 *                IsTimesLocked
 * Return 1 if there is LOCK in the VI directory
 *======================================================================*/
extern int IsTimesLocked(DD_Var_t *DD_Var);

/*======================================================================
 *                ExtDataRequest
 *  Return folowing values:
 *  OK - request is accepted SERVER has to wait when LOCK file is gone
 *  NOEXEC - error in external executable
 *  NODATAATTIME - time corresponds to the NODATA interval
 *  GAPISSMALL - Time is inside too small gap
 *======================================================================*/
extern int ExtDataRequest(DD_Var_t *DD_Var, double CurrTime);

/*=======================================================================
 *                UpdateTimeInfo.c
 *  int SearchLeft(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax)
 *  int SearchRight(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax)
 *  Search the next to the left(right) non-empty time interval
 *  DD_VarL - common data structure corresponding to THIS open VI
 *  Rmin, Rmax - start points
 *
 *  int UpdateTimeInfo(DD_Var_t *DD_VarL)
 *  Function reopen "times" file and update all time constants
 *======================================================================*/
extern int SearchLeft(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax);
extern int SearchRight(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax);
extern int UpdateTimeInfo(DD_Var_t *DD_VarL);