Commit 4243d674e6ecf6047b63c98da0165ef74442d966

Authored by Benjamin Renard
0 parents

First commit

.gitignore 0 → 100644
  1 +++ a/.gitignore
... ... @@ -0,0 +1,2 @@
  1 +build/
  2 +scripts/StartServer
... ...
CMakeLists.txt 0 → 100644
  1 +++ a/CMakeLists.txt
... ... @@ -0,0 +1,36 @@
  1 +cmake_minimum_required(VERSION 2.6)
  2 +
  3 +PROJECT(DDServer)
  4 +
  5 +configure_file (
  6 + "${CMAKE_SOURCE_DIR}/scripts/StartServer.in"
  7 + "${CMAKE_SOURCE_DIR}/scripts/StartServer"
  8 +)
  9 +
  10 +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/build/${CMAKE_BUILD_TYPE}/bin/)
  11 +set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/build/${CMAKE_BUILD_TYPE}/lib/)
  12 +
  13 +if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
  14 + #64 bits
  15 + set(CMAKE_C_FLAGS_DEBUG "-ggdb -DLINUX -Dlinux -m64 -march=core2 -fPIC -D_REENTRANT -pthread")
  16 + set(CMAKE_C_FLAGS_RELEASE "-DLINUX -Dlinux -m64 -march=core2 -fPIC -D_REENTRANT -pthread")
  17 +else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
  18 + #32 bits
  19 + set(CMAKE_C_FLAGS_DEBUG "-ggdb -DLINUX -march=i686 -fPIC -Dlinux -D_REENTRANT -malign-double -pthread")
  20 + set(CMAKE_C_FLAGS_DEBUG "-DLINUX -march=i686 -fPIC -Dlinux -D_REENTRANT -malign-double -pthread")
  21 +endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
  22 +
  23 +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
  24 +
  25 +find_package( Threads REQUIRED )
  26 +find_package( CRYPT REQUIRED )
  27 +find_package( NetCDF REQUIRED )
  28 +
  29 +MESSAGE( STATUS "Build DDServer Project" )
  30 +add_subdirectory(src/CLIENT)
  31 +add_subdirectory(src/SERVER)
  32 +
  33 +install(FILES "scripts/StartServer" DESTINATION . PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
  34 +install(DIRECTORY "src/INCLUDE/" DESTINATION include)
  35 +
  36 +SET(CMAKE_VERBOSE_MAKEFILE ON)
... ...
README 0 → 100644
  1 +++ a/README
... ... @@ -0,0 +1,20 @@
  1 +1. Set NETCDF_ROOT to use a specific netcdf installation directory :
  2 +> export NETCDF_ROOT="/home/benjamin/AMDA-GIT/AMDA_COTS/netcdf/install"
  3 +
  4 +2. Make the build directory :
  5 +> cmake -E make_directory build
  6 +
  7 +3. Configure the build. Set CMAKE_BUILD_TYPE to Debug or Release to configure the build type. Set CMAKE_INSTALL_PREFIX to configure the install directory :
  8 +> cmake -E chdir build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/home/benjamin/DDServer ..
  9 +
  10 +4. Build DDServer :
  11 +> cmake --build build
  12 +
  13 +5. Install DDServer :
  14 +> make -C build install VERBOSE=1
  15 +
  16 +6. Configure DDServer :
  17 +In the install directory, open "StartServer" and set DDPATH and DDBASE.
  18 +
  19 +7. Run DDServer:
  20 +> ./StartServer
... ...
cmake/modules/FindCRYPT.cmake 0 → 100644
  1 +++ a/cmake/modules/FindCRYPT.cmake
... ... @@ -0,0 +1,32 @@
  1 +FIND_PATH(CRYPT_INCLUDE_DIR crypt.h
  2 + /usr/local/include/crypt
  3 + /usr/local/include
  4 + /usr/include/crypt
  5 + /usr/include
  6 +)
  7 +
  8 +SET(CRYPT_NAMES crypt)
  9 +
  10 +FIND_LIBRARY(CRYPT_LIBRARY
  11 + NAMES ${CRYPT_NAMES}
  12 + PATHS /usr/lib /usr/local/lib
  13 +)
  14 +
  15 +IF(CRYPT_INCLUDE_DIR AND CRYPT_LIBRARY)
  16 + SET(CRYPT_FOUND TRUE)
  17 + SET(CRYPT_LIBRARIES ${CRYPT_LIBRARY} )
  18 +ELSE(CRYPT_INCLUDE_DIR AND CRYPT_LIBRARY)
  19 + SET(CRYPT_FOUND FALSE)
  20 + SET(CRYPT_LIBRARIES)
  21 +ENDIF(CRYPT_INCLUDE_DIR AND CRYPT_LIBRARY)
  22 +
  23 +IF(NOT CRYPT_FOUND)
  24 + IF(CRYPT_FIND_REQUIRED)
  25 + MESSAGE(FATAL_ERROR "crypt library and headers required.")
  26 + ENDIF(CRYPT_FIND_REQUIRED)
  27 +ENDIF(NOT CRYPT_FOUND)
  28 +
  29 +MARK_AS_ADVANCED(
  30 + CRYPT_LIBRARY
  31 + CRYPT_INCLUDE_DIR
  32 +)
... ...
cmake/modules/FindNetCDF.cmake 0 → 100644
  1 +++ a/cmake/modules/FindNetCDF.cmake
... ... @@ -0,0 +1,24 @@
  1 +FIND_PATH(NETCDFINCLUDE_DIR netcdf.h
  2 + HINTS
  3 + $ENV{NETCDF_ROOT}/include
  4 + ${NETCDF_ROOT}/include
  5 +)
  6 +mark_as_advanced(NETCDFINCLUDE_DIR)
  7 +
  8 +find_library(NETCDFLIBRARY
  9 + NAMES netcdf
  10 + HINTS
  11 + $ENV{NETCDF_ROOT}
  12 + ${NETCDF_ROOT}
  13 + PATH_SUFFIXES lib
  14 +)
  15 +mark_as_advanced(NETCDFLIBRARY)
  16 +
  17 +include(FindPackageHandleStandardArgs)
  18 +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NetCdf DEFAULT_MSG NETCDFLIBRARY NETCDFINCLUDE_DIR)
  19 +
  20 +if(NETCDF_FOUND)
  21 + set(NETCDFINCLUDE_DIRS ${NETCDFINCLUDE_DIR})
  22 + set(NETCDFLIBRARIES ${NETCDFLIBRARY})
  23 +endif()
  24 +
... ...
scripts/StartServer.in 0 → 100755
  1 +++ a/scripts/StartServer.in
... ... @@ -0,0 +1,13 @@
  1 +#!/bin/bash
  2 +#-------------------------------------------------------------------
  3 +# StartServer
  4 +#-------------------------------------------------------------------
  5 +DDBASE=@CMAKE_INSTALL_PREFIX@/DDBASE/DATA
  6 +DDPATH=@CMAKE_INSTALL_PREFIX@/DDBASE
  7 +DDLIB=@CMAKE_INSTALL_PREFIX@/lib
  8 +DDBASEBIN=@CMAKE_INSTALL_PREFIX@/bin
  9 +LD_LIBRARY_PATH=$DDLIB/:/usr/local/lib64/
  10 +export DDBASE DDPATH DDBASEBIN DDLIB LD_LIBRARY_PATH
  11 +
  12 +#$DDBASEBIN/DD_Server 1>/dev/null 2>/dev/null&
  13 +$DDBASEBIN/DD_Server -V
... ...
src/CLIENT/CMakeLists.txt 0 → 100644
  1 +++ a/src/CLIENT/CMakeLists.txt
... ... @@ -0,0 +1,22 @@
  1 +
  2 +PROJECT(DDClient)
  3 +
  4 +include_directories(
  5 + ${CMAKE_HOME_DIRECTORY}/src/INCLUDE/
  6 +)
  7 +
  8 +#Library configuration
  9 +file(
  10 + GLOB_RECURSE
  11 + source_files
  12 + ./*
  13 +)
  14 +
  15 +ADD_LIBRARY( DDClient SHARED ${source_files} )
  16 +
  17 +target_link_libraries(
  18 + DDClient
  19 + ${CMAKE_THREAD_LIBS_INIT}
  20 +)
  21 +
  22 +install (TARGETS DDClient DESTINATION lib)
... ...
src/CLIENT/DD_client.c 0 → 100755
  1 +++ a/src/CLIENT/DD_client.c
... ... @@ -0,0 +1,931 @@
  1 +/* $Id: DD_client.c,v 1.4 2012/10/18 09:25:58 budnik Exp $ */
  2 +/*==============================================================
  3 + * DD SYSTEM
  4 + * DD_client.c
  5 + * V.6.0
  6 + * List of changes:
  7 + * November 1995, Version 1.0
  8 + * August 1999 :Access security system was installed by Alexandr Grigoriev (v3.0)
  9 + * October 22, 2002 - Communication ideology is changed (V.4.0)
  10 + * Oct 29, 2002 - Add DD_GetVersion() and some bags are corrected (V.4.1)
  11 + * May 1, 2003 - Network error is developped. (The header receiving is changed): V.4.2
  12 + * Nov 18, 2004 - Cach error is fixed.
  13 + * Jun 17, 2007 - Fedorov, V.4.5 Create new VI and Update data requests
  14 + * Sep 24, 2007 - Fedorov, V.4.6 Processing of return of Get_Data
  15 + * Dec 03, 2007 - Budnik, V.4.7 There may be several sessions with DD Server inside ONE
  16 + * Client session. Keep UserHost & UserName
  17 + * Oct 18, 2012 - Knizhnikova, V.4.8 new DD_SetTimeInfo() function
  18 + * Dec 15, 2012 - Fedorov, V.6.0. DD_GetMultiData(). Request structure is very changed, CurrentData is not a global structure
  19 + *===============================================================*/
  20 +
  21 +#include <unistd.h>
  22 +#include "DD.h"
  23 +#include "DD_comm.h"
  24 +#include "DD_Access.h"
  25 +#include <stdio.h>
  26 +#include <string.h>
  27 +
  28 +#define VERSION "V.6.0"
  29 +
  30 +/*------------------ GLOBAL STATIC VARIABLES --------------------------*/
  31 +int SocketID = -1; /* Global socket id for this communication session */
  32 +char UserName[USRLENGTH]="\0"; /* string for user name */
  33 +char UserHost[MAXHOSTLENGTH] = "\0"; /* IP of user's host in a string form */
  34 +int UserID; /* ID of user at the user's host */
  35 +extern int errno;
  36 +
  37 +/*================== FUNCTIONS =================================*/
  38 +/*----------------------- GET User Host-------------------------------*/
  39 +int GetUserHost()
  40 +{
  41 + char HostName[HOSTNAMELENGTH];
  42 + struct hostent *Host;
  43 + unsigned int HostAddress;
  44 + int userid;
  45 + static unsigned int m1 = 0X000000FF;
  46 + static unsigned int m2 = 0X0000FF00;
  47 + static unsigned int m3 = 0X00FF0000;
  48 + static unsigned int m4 = 0XFF000000;
  49 + unsigned int b1,b2,b3,b4;
  50 +
  51 + userid = getuid(); /* Get a client user ID */
  52 +
  53 +/* UserHost can be set by extern WEB function in case of WEB communicatio,
  54 + * or it should be defined as local host if DD_client is installed at USER
  55 + * computer
  56 + */
  57 + if(UserHost[0] == '\0')
  58 + {
  59 + gethostname(HostName,HOSTNAMELENGTH); /* Get a client host name */
  60 +
  61 + if((Host = gethostbyname(HostName)) == NULL) return NOHOST;
  62 + HostAddress = *((unsigned int *)Host->h_addr_list[0]);
  63 +
  64 + b1 = HostAddress & m1;
  65 + b2 = (HostAddress & m2) >> 8;
  66 + b3 = (HostAddress & m3) >> 16;
  67 + b4 = (HostAddress & m4) >> 24;
  68 +
  69 + sprintf(UserHost,"%03u.%03u.%03u.%03u\0",b1,b2,b3,b4);
  70 + }
  71 + return userid;
  72 +}
  73 +/*-------------------------------------------------------------------*/
  74 +
  75 +/*------------------ MAKE_CONNECTION ---------------------------*/
  76 +/*
  77 + * The function returns opened socket, ready to read and write
  78 + */
  79 +int GetSocket()
  80 +/*
  81 + * Connect with remote server, and returns socket ID
  82 + * In case of error return error number according DD_comm.h
  83 + */
  84 +{
  85 +/*-------- Variables for resource file -----------------*/
  86 + char rname[PATHLENGTH]; /* name of res file */
  87 + char line[PATHLENGTH];
  88 + char *path;
  89 + FILE *resfile; /* resource file */
  90 + char *pline;
  91 +
  92 +/*---------- Variables for network ---------------------*/
  93 + static struct hostent *Host; /* name & internet (32b) address for
  94 + remout hosts (see netdb.h) */
  95 + static char RemSerName[PATHLENGTH]; /* name of remote server */
  96 +
  97 + struct servent *serv; /* pointer to static structure of
  98 + port number of registrated service */
  99 +
  100 + static struct sockaddr_in IntAFAddr; /* structure of internet address of type AF_INET
  101 + see <netinet/in.h>
  102 + to get name of socket we should
  103 + to convert pointer to this structure
  104 + to pointer to "srtruct sockaddr" where
  105 + all fields are "char array". */
  106 +
  107 + int AFAddrLen = sizeof(struct sockaddr_in); /* size of internet address, <netinet/in.h> 18 bytes*/
  108 + int ScAddrLen = sizeof(struct sockaddr); /* size of socket address, <sys/socket.h> 18 bytes*/
  109 +
  110 + int cc,i;
  111 + int arg = 0;
  112 + int normaddr;
  113 +/*
  114 + *---------- Getting socket and its address ---------------------*/
  115 +/*---------------- HOST and PORT ------------------------------*/
  116 + if((path = getenv("DDPATH")) == NULL)
  117 + {
  118 + strcpy(rname,"DD.res");
  119 + }
  120 + else
  121 + {
  122 + strcpy(rname,path);
  123 + strcat(rname, "/DD.res");
  124 + }
  125 +/*
  126 + (void *)strcpy(rname,"./DD.res");
  127 +*/
  128 + if((resfile = fopen(rname,"r")) == NULL)
  129 + {
  130 + fprintf(stderr,"No resource file, sorry\n");
  131 + exit(1);
  132 + }
  133 +
  134 + pline = fgets(RemSerName, PATHLENGTH-1, resfile);
  135 + pline = fgets(line, PATHLENGTH-1, resfile);
  136 + fclose(resfile);
  137 +
  138 + RemSerName[strlen(RemSerName)-1] = '\0';
  139 + sscanf(line,"%d",&(normaddr));
  140 +
  141 + IntAFAddr.sin_port = htons((uint16_t)normaddr); /* Conversion of the port number to
  142 + universal net form */
  143 +/*---------------- END of FILE READING --------------------------*/
  144 +/*
  145 + *------- Trying to open socket with this address and name ---------
  146 + */
  147 + if((Host = gethostbyname(RemSerName)) == NULL) /* Get address and other information by
  148 + host name, see netdb.h */
  149 + {
  150 + fprintf(stderr,"Server %s not found\n",RemSerName);
  151 + return(-1);
  152 + }
  153 +
  154 + if((SocketID = socket(AF_INET,SOCK_STREAM,PROTOCOL)) < 0)
  155 + {
  156 + perror("Socket:"); return(-1);
  157 + }
  158 +
  159 +/* Filling full internet address for socket "name"
  160 + * this address will be used to get communication point */
  161 +
  162 + IntAFAddr.sin_family = Host->h_addrtype;
  163 + memcpy(&IntAFAddr.sin_addr.s_addr,Host->h_addr_list[0],Host->h_length);
  164 +
  165 + /* Connection to server socket on remote computer */
  166 + if(connect(SocketID,(struct sockaddr *)&IntAFAddr,AFAddrLen) < 0)
  167 + { perror("connect"); return(-1); }
  168 +
  169 +/*
  170 + * Get Host name and Host ID for security application
  171 + */
  172 + if((UserID = GetUserHost()) < 0) return(NOHOST);
  173 +
  174 + return SocketID;
  175 +}
  176 +/*------------------- end of GetSocket ---------------------*/
  177 +
  178 +/*==================== Receive From Net ======================*/
  179 +/*
  180 + * Smart buffered receiver
  181 + */
  182 +int ReceiveFromNet(char *buf, int PacketSize)
  183 +{
  184 + int CurLength = 0;
  185 + int i,cc;
  186 + do
  187 + {
  188 + i = 0;
  189 + while(((cc = recv(SocketID,buf+ CurLength,PacketSize - CurLength,0)) < 0) && (i < TRY)) i++;
  190 + if(cc < 0) return -1;
  191 + CurLength = CurLength + cc;
  192 + } while(CurLength < PacketSize);
  193 + return 1;
  194 +}
  195 +
  196 +/*------------------ Open Virtual Instrument -----------------------*/
  197 +/*
  198 + * If no connection, connect to server, then try to order data set and return
  199 + * ID if OK or ErrorNumber if not
  200 + */
  201 +int DD_SetVariable(char *InstrName)
  202 +{
  203 + static caddr_t buff = NULL;
  204 + static XDR xdrs;
  205 + int InstrID; /* Instrumnet ID to return */
  206 + int cc,i;
  207 + int Request = OPENINSREQ;
  208 + int hostlen,userlen;
  209 + char *PUserHost = UserHost, *PUserName = UserName;
  210 + /* We need this because XDR works with adresses of pointers */
  211 +
  212 +/* If there is no connection, try to get it */
  213 + if(SocketID < 0)
  214 + if((SocketID = GetSocket()) < 0) return(NOCONNECTION);
  215 +
  216 +/* Encoding request by XDR to buf */
  217 +/* Buffer and stream allocation */
  218 + buff = (caddr_t)malloc(REQUESTLENGTH);
  219 +
  220 + xdrmem_create(&xdrs, buff, REQUESTLENGTH, XDR_ENCODE);
  221 +
  222 + xdr_int(&xdrs,&Request);
  223 + xdr_string(&xdrs, &InstrName, strlen(InstrName));
  224 +
  225 +/* Send Open Virtual Instrument request */
  226 +
  227 + if((cc = send(SocketID,buff,REQUESTLENGTH,0)) < 0)
  228 + {
  229 + perror("DD_SetVariable:");
  230 + free(buff);
  231 + xdr_destroy(&xdrs);
  232 + return(REQSENDERR);
  233 + }
  234 + xdrmem_create(&xdrs, buff, REQUESTLENGTH, XDR_FREE);
  235 +
  236 +/*-------- preparation an authorization request ----------------*/
  237 + if(UserName[0] == '\0') strcpy(UserName,NONAME);
  238 + hostlen = strlen(UserHost);
  239 + userlen = strlen(UserName);
  240 +
  241 + xdrmem_create(&xdrs, buff,REQUESTLENGTH, XDR_ENCODE);
  242 +
  243 + xdr_int(&xdrs,&UserID);
  244 + xdr_string(&xdrs, &PUserHost, hostlen);
  245 + xdr_string(&xdrs, &PUserName, userlen);
  246 +/* fprintf(stderr,"userid %d host %s DD_name %s\n",UserID,UserHost,UserName); */
  247 +
  248 +/* Send request */
  249 + if((cc = send(SocketID,buff,REQUESTLENGTH,0)) < 0)
  250 + {
  251 + perror("DD_Set_Variable:");
  252 + free(buff);
  253 + xdr_destroy(&xdrs);
  254 + return(REQSENDERR);
  255 + }
  256 +
  257 + free(buff);
  258 + xdr_destroy(&xdrs);
  259 +
  260 +/* Get reply */
  261 + buff = (caddr_t)malloc(REPLYLENGTH);
  262 +/*
  263 + i=0;
  264 + while(((cc = recv(SocketID,buff,REPLYLENGTH,0)) < 0) && (i < TRY)) i++;
  265 +*/
  266 + if((cc = ReceiveFromNet(buff, REPLYLENGTH)) < 0)
  267 + {
  268 + perror("DD_SET_Variable:");
  269 + free(buff);
  270 + return(REPLYRECERR);
  271 + }
  272 +
  273 + xdrmem_create(&xdrs, buff, REPLYLENGTH, XDR_DECODE);
  274 + xdr_int(&xdrs,&InstrID);
  275 +
  276 +/* Free all */
  277 + free(buff);
  278 + xdr_destroy(&xdrs);
  279 +
  280 + return InstrID;
  281 +}
  282 +
  283 +/*----------------------- DD_GetInform -----------------------------*/
  284 +/*
  285 + * Returns "OK" if OK, fill DD_Data structure
  286 + * Return negative value if error
  287 + */
  288 +
  289 +int DD_GetInform(int VarID,char *AttrName,DD_data_t **data)
  290 +{
  291 + static void *v = NULL;
  292 + static DD_data_t idd = {DD_CHAR, 0, NULL,1, &v};
  293 + static caddr_t buf = NULL;
  294 + static XDR xdrs;
  295 + int id;
  296 + int cc;
  297 + int length;
  298 + int op = DATAINFOREQ;
  299 + int type; /* type of information or error */
  300 + int DimNumbers;
  301 + int PacketSize;
  302 + int CurLength;
  303 + int i;
  304 + u_int count;
  305 + u_int MaxNumber;
  306 +
  307 +/*------------------- Empty static data ------------------------*/
  308 + if(idd.Dimensions != NULL)
  309 + {
  310 + free(idd.Dimensions);
  311 + idd.Dimensions = NULL;
  312 + }
  313 + if(idd.Variables[0] != NULL)
  314 + {
  315 + free(idd.Variables[0]);
  316 + idd.Variables[0] = NULL;
  317 + }
  318 +
  319 +/*------------------ Check the Name length -----------------------*/
  320 + if(strlen(AttrName) > MAXVARLENGTH) length = MAXVARLENGTH;
  321 + else length = strlen(AttrName);
  322 +
  323 +/*----------- Allocation of memory and stream --------------------*/
  324 + buf = (caddr_t)malloc(REQUESTLENGTH);
  325 + xdrmem_create(&xdrs, buf, REQUESTLENGTH, XDR_ENCODE);
  326 +
  327 +/*------------------- Encoding the request ----------------------*/
  328 + xdr_int(&xdrs,&op);
  329 + xdr_int(&xdrs,&VarID);
  330 + xdr_string(&xdrs, &AttrName, length);
  331 +
  332 +/*------------------------ Send request ---------------------------*/
  333 + if((cc = send(SocketID,buf,REQUESTLENGTH,0)) < 0)
  334 + {
  335 + perror("DD_GetInform:");
  336 + free(buf);
  337 + xdr_destroy(&xdrs);
  338 + return(REQSENDERR);
  339 + }
  340 + free(buf);
  341 + xdr_destroy(&xdrs);
  342 +
  343 +/*------------------------ Get reply header ------------------------*/
  344 +
  345 + buf = (caddr_t)malloc(REPLYLENGTH);
  346 +/*
  347 + i=0;
  348 + while(((cc = recv(SocketID,buf,REPLYLENGTH,0)) < 0) && (i < TRY)) i++;
  349 + if(cc < 0)
  350 +*/
  351 + if((cc = ReceiveFromNet(buf, REPLYLENGTH)) < 0)
  352 + {
  353 + perror("DD_GetInform:");
  354 + free(buf);
  355 + return(REPLYRECERR);
  356 + }
  357 +
  358 + xdrmem_create(&xdrs, buf, REPLYLENGTH, XDR_DECODE);
  359 + xdr_int(&xdrs,&type);
  360 + if(type < 0)
  361 + {
  362 + free(buf);
  363 + xdr_destroy(&xdrs);
  364 + return(type);
  365 + }
  366 + xdr_int(&xdrs,&DimNumbers);
  367 + xdr_int(&xdrs,&PacketSize);
  368 + free(buf);
  369 + xdr_destroy(&xdrs);
  370 +
  371 + idd.DimNumber = DimNumbers;
  372 + idd.type = type;
  373 +
  374 +/*---------------------------- Get Data Packet ----------------------*/
  375 + if(PacketSize > 0) buf = (caddr_t)malloc(PacketSize);
  376 + else return(REPLYRECERR);
  377 +
  378 + if((cc = ReceiveFromNet(buf, PacketSize)) < 0)
  379 + {
  380 + perror("DD_GetInform:");
  381 + free(buf);
  382 + return(REPLYRECERR);
  383 + }
  384 +
  385 +/*--------------------- Decoding data packet ------------------------*/
  386 + if(DimNumbers > 0)
  387 + {
  388 +/*----------- Memory allocation and xdr creating -----------------*/
  389 + xdrmem_create(&xdrs, buf, (u_int)PacketSize, XDR_DECODE);
  390 +
  391 +/*----------------- Dimensions decoding -------------------------*/
  392 + if(idd.Dimensions !=NULL) free(idd.Dimensions);
  393 + idd.Dimensions = (int *)malloc(DimNumbers*sizeof(int));
  394 +
  395 + xdr_array(&xdrs, (caddr_t *)&(idd.Dimensions),
  396 + &count,
  397 + (u_int )DimNumbers,
  398 + unixlen[DD_INT],
  399 + (xdrproc_t)xdr_int);
  400 +
  401 + count = 1;
  402 + for(i=0; i < DimNumbers;i++)
  403 + count = count*idd.Dimensions[i];
  404 + MaxNumber = count;
  405 + }
  406 + else
  407 + {
  408 + free(buf);
  409 + return(REPLYRECERR);
  410 + }
  411 +
  412 +/*---------------- Allocate memory for Variables and decoding ------------------*/
  413 + if(idd.Variables[0] != NULL) free(idd.Variables[0]);
  414 + idd.Variables[0] = (int *)malloc(unixlen[type] * MaxNumber);
  415 +
  416 + xdr_array(&xdrs,((caddr_t*)(&idd.Variables[0])),&count,
  417 + MaxNumber, unixlen[type], (xdrproc_t)ConvFunc[type]);
  418 +
  419 +/*-------------------------- Free all ------------------------------*/
  420 + free(buf);
  421 + xdr_destroy(&xdrs);
  422 +
  423 + *data = &idd;
  424 + return OK;
  425 +}
  426 +
  427 +/*====================================================
  428 + * DD_SetTime()
  429 + *====================================================*/
  430 +/*-----------------------------------------------------
  431 + * VarID - ID of Data Set
  432 + * Time - string in DD type
  433 + * Returns 1 if OK and negative in case of err
  434 + *---------------------------------------------------*/
  435 +
  436 +int DD_SetTime(int VarID,char *Time)
  437 +{
  438 + static caddr_t buf = NULL;
  439 + static XDR xdrs;
  440 + static int op = TIMESETREQ;
  441 + int type;
  442 + int cc,i;
  443 + int DoneFlag = 0;
  444 +
  445 + while(DoneFlag == 0)
  446 + {
  447 +/* Allocatein memory and stream */
  448 + buf = (caddr_t)malloc(REQUESTLENGTH);
  449 + xdrmem_create(&xdrs, buf, REQUESTLENGTH, XDR_ENCODE);
  450 +
  451 +/* Encoding the request */
  452 + xdr_int(&xdrs,&op);
  453 + xdr_int(&xdrs,&VarID);
  454 + xdr_string(&xdrs, &Time, TIMELENGTH);
  455 +
  456 +/* Send request */
  457 + if((cc = send(SocketID,buf,REQUESTLENGTH,0)) < 0)
  458 + {
  459 + perror("DD_SetTime:");
  460 + free(buf);
  461 + xdr_destroy(&xdrs);
  462 + return(REQSENDERR);
  463 + }
  464 + free(buf);
  465 + xdr_destroy(&xdrs);
  466 +
  467 +/* Get reply header */
  468 +
  469 + buf = (caddr_t)malloc(REPLYLENGTH);
  470 + if((cc = ReceiveFromNet(buf, REPLYLENGTH)) < 0)
  471 + {
  472 + perror("DD_SetTime:");
  473 + free(buf);
  474 + return(REPLYRECERR);
  475 + }
  476 +
  477 + xdrmem_create(&xdrs, buf, REPLYLENGTH, XDR_DECODE);
  478 + xdr_int(&xdrs,&type);
  479 +
  480 + free(buf);
  481 + xdr_destroy(&xdrs);
  482 +
  483 + if(type < 0)
  484 + {
  485 + if(type == CACHTOOREC) sleep((unsigned )(FILEACCMARG));
  486 + else return type;
  487 + }
  488 + else DoneFlag = 1;
  489 + }
  490 + return 1 ;
  491 +}
  492 +
  493 +/*==================================================================
  494 + * DD_SetTimeInfo()
  495 + *=================================================================*/
  496 +/*----------------------------------------------------------
  497 + * VarID - ID of Data Set
  498 + * Time - string in DD type
  499 + * RealTime - double : time value pointer points to
  500 + * Returns 1 if OK and negative in case of err
  501 + *----------------------------------------------------------*/
  502 +
  503 +int DD_SetTimeInfo(int VarID, char *Time, double *RealTime)
  504 +{
  505 + int err;
  506 + static char TimeInt[17] = "0000000000001000\0";
  507 + DD_data_t *data;
  508 +
  509 + err = DD_SetTime(VarID, Time);
  510 + if (err < 1) return err;
  511 +
  512 + err = DD_GetData(VarID, "Time", TimeInt, &data);
  513 + if (err < 0) return err;
  514 + if (data->VarNumber < 1) return OUTOFTIME;
  515 +
  516 + *RealTime = DD_Time2Double((char *)data->Variables[0]);
  517 +
  518 + return 1 ;
  519 +}
  520 +
  521 +/*=========================================================
  522 + * DD_GetData()
  523 + * Just an interface to the DD_GetMultiData()
  524 + *========================================================*/
  525 +int DD_GetData(int VarID, char *VarName, char *TimeInt, DD_data_t **data)
  526 +{
  527 + char *xxx=VarName;
  528 + int err;
  529 + err = DD_GetMultiData(VarID, 1, &xxx, TimeInt, data, 1);
  530 + return err;
  531 +}
  532 +/*=========================================================
  533 + * DD_GetMultiData()
  534 + *========================================================*/
  535 +/*---------------------------------------------------------
  536 + * VarID - ID of open virtual instrument
  537 + * VarSize - the size of the array names
  538 + * VarNames - araay of the variables names
  539 + * TimeInt - Time interval in DD_time style
  540 + * data - returned data
  541 + * Return values:
  542 + * positives:
  543 + * MOREDELAY - call this function again after delay
  544 + * MOREDATA - call this function again to complete request
  545 + * OK - all data received
  546 + * negative value - error (see DD.h)
  547 + *---------------------------------------------------------*/
  548 +
  549 +int DD_GetMultiData(int VarID,size_t VarSize, char **VarNames,char *TimeInt,DD_data_t **data, int BackFlag)
  550 +{
  551 + static DD_data_t *CurrentData = NULL; /* Data records array to keep until the next call */
  552 + static size_t OldVarSize = 0;
  553 + static caddr_t buf = NULL;
  554 + static XDR xdrs;
  555 + static int LastPacketFlag = OK;
  556 + int id;
  557 + int cc;
  558 + int *NameLength = NULL; /* Array of lengths */
  559 + int XDRStrLen; /* xdr length of a string */
  560 + int XDRReqlength; // Length in bytes the XDR stream
  561 + int op = DATAGETREQ;
  562 + int type; /* type of information or error */
  563 + int DimNumbers;
  564 + int PacketSize;
  565 + int CurLength;
  566 + u_int count, MaxSize;
  567 + int i;
  568 +
  569 + /* Empty static data */
  570 + for(id = 0; id < OldVarSize; id++)
  571 + {
  572 + if(CurrentData[id].Dimensions != NULL)
  573 + {
  574 + free(CurrentData[id].Dimensions);
  575 + CurrentData[id].Dimensions = NULL;
  576 + }
  577 + if(CurrentData[id].Variables != NULL)
  578 + {
  579 + for(i = 0; i< CurrentData[id].VarNumber; i++)
  580 + free(CurrentData[id].Variables[i]);
  581 + free(CurrentData[id].Variables);
  582 + CurrentData[id].Variables = NULL;
  583 + }
  584 + }
  585 + free(CurrentData);
  586 +
  587 + /*--------------------------------------
  588 + * Create a new Current Data empty array
  589 + *-------------------------------------*/
  590 + OldVarSize = VarSize;
  591 + CurrentData = (DD_data_t *)malloc(sizeof(DD_data_t)*VarSize);
  592 + for(id = 0; id < VarSize; id++)
  593 + {
  594 + CurrentData[id].Dimensions = NULL;
  595 + CurrentData[id].Variables = NULL;
  596 + CurrentData[id].DimNumber = 0;
  597 + CurrentData[id].VarNumber = 0;
  598 + CurrentData[id].type = 0;
  599 + }
  600 + /*--------------------------------------------------------------
  601 + * The follows request preparation and send is performed only
  602 + * if the priveous data packed is completely received
  603 + *--------------------------------------------------------------*/
  604 + if((LastPacketFlag == OK) || (LastPacketFlag == MOREDELAY))
  605 + {
  606 + /*---------------------------------------
  607 + * Preparation of the array the name lengths
  608 + * Note that the names are cut down to the MAXVARLENGTH
  609 + * Calculation the packet size
  610 + *---------------------------------------*/
  611 + NameLength = (int *)malloc(sizeof(int)*VarSize);
  612 + XDRReqlength = 8; /* the length of the first+last arguments */
  613 + for(id = 0; id < VarSize; id++)
  614 + {
  615 + if(strlen(VarNames[id]) > MAXVARLENGTH) NameLength[id] = MAXVARLENGTH;
  616 + else NameLength[id] = strlen(VarNames[id]);
  617 + XDRStrLen = (NameLength[id] / 4) * 4;
  618 + if((NameLength[id] % 4) > 0) XDRStrLen += 4;
  619 + XDRReqlength += XDRStrLen + 4; // String length + 4 bytes length coding
  620 + //fprintf(stderr,"Variable %s, length %d, total %d\n",VarNames[id],XDRStrLen,XDRReqlength);
  621 + }
  622 + /*--------------------------------
  623 + * The first packet of the request of the standard size
  624 + * Allocation corresponding memory and stream
  625 + *------------------------------*/
  626 + buf = (caddr_t)malloc(REQUESTLENGTH);
  627 + xdrmem_create(&xdrs, buf, REQUESTLENGTH, XDR_ENCODE);
  628 +
  629 + /* Encoding the request */
  630 + xdr_int(&xdrs,&op);
  631 + xdr_int(&xdrs,&VarID);
  632 + xdr_string(&xdrs,&TimeInt,TIMELENGTH);
  633 + xdr_int(&xdrs,&XDRReqlength);
  634 +
  635 + /* Send the first request */
  636 + if((cc = send(SocketID,buf,REQUESTLENGTH,0)) < 0)
  637 + {
  638 + perror("DD_GetData: First Request");
  639 + free(buf);
  640 + xdr_destroy(&xdrs);
  641 + return(REQSENDERR);
  642 + }
  643 + free(buf);
  644 + xdr_destroy(&xdrs);
  645 +
  646 + /*--------------------------------
  647 + * The Second packet of XDRReqlength size
  648 + * Allocation corresponding memory and stream
  649 + *------------------------------*/
  650 + buf = (caddr_t)malloc(XDRReqlength);
  651 + xdrmem_create(&xdrs, buf, XDRReqlength, XDR_ENCODE);
  652 + xdr_int(&xdrs,(int *)(&VarSize));
  653 + for(id = 0; id < VarSize; id++) xdr_string(&xdrs, &VarNames[id], NameLength[id]);
  654 + xdr_int(&xdrs,&BackFlag);
  655 +
  656 + /* Send the second request */
  657 + if((cc = send(SocketID,buf,XDRReqlength,0)) < 0)
  658 + {
  659 + perror("DD_GetData:Second Packet");
  660 + free(buf);
  661 + xdr_destroy(&xdrs);
  662 + return(REQSENDERR);
  663 + }
  664 + free(buf);
  665 + xdr_destroy(&xdrs);
  666 + }
  667 +
  668 + /*-----------------------------------------------------------
  669 + * Get the VarSize reply headers and VarSize data
  670 + *----------------------------------------------------------*/
  671 + for(id = 0; id < VarSize; id++)
  672 + {
  673 + /*-------------------
  674 + * The header
  675 + *-----------------*/
  676 + buf = (caddr_t)malloc(REPLYLENGTH);
  677 + if((cc = ReceiveFromNet(buf, REPLYLENGTH)) < 0)
  678 + {
  679 + perror("DD_GetData:Error while header receive");
  680 + free(buf);
  681 + return(REPLYRECERR);
  682 + }
  683 +
  684 + xdrmem_create(&xdrs, buf, REPLYLENGTH, XDR_DECODE);
  685 + xdr_int(&xdrs,&type);
  686 + xdr_int(&xdrs,&DimNumbers);
  687 + xdr_int(&xdrs,&PacketSize);
  688 + free(buf);
  689 + xdr_destroy(&xdrs);
  690 +
  691 + if((type < 0) && (type != NOVAR)) /* Server returns unrecoverable error */
  692 + {
  693 + fprintf(stderr,"DD_GetData: Server returns %d, unrecovable error\n",type);
  694 + return type;
  695 + }
  696 +
  697 + /*----------- Header is received ----------------------*/
  698 + CurrentData[id].DimNumber = DimNumbers - 1;
  699 + CurrentData[id].type = type;
  700 +
  701 + /*--------------- Receive Data Packet ------------------------------*/
  702 + if(PacketSize > 0) buf = (caddr_t)malloc(PacketSize);
  703 + else return(REPLYRECERR);
  704 + if((cc = ReceiveFromNet(buf, PacketSize)) < 0)
  705 + {
  706 + perror("DD_GetData: Error while data packet receive");
  707 + free(buf);
  708 + return(REPLYRECERR);
  709 + }
  710 + /*----------------- Decoding data packet --------------------*/
  711 + if(DimNumbers > 1)
  712 + {
  713 + xdrmem_create(&xdrs, buf, (u_int)PacketSize, XDR_DECODE);
  714 + count = DimNumbers-1;
  715 + /* allocation memory for dimensions */
  716 + CurrentData[id].Dimensions = (int *)malloc((DimNumbers-1)*sizeof(int));
  717 +
  718 + xdr_int(&xdrs,&LastPacketFlag); /* Last Paket Indicatort*/
  719 + xdr_int(&xdrs,&CurrentData[id].VarNumber); /* Variables number */
  720 +
  721 + if(LastPacketFlag > 2)
  722 + {
  723 + LastPacketFlag = OK;
  724 + CurrentData[id].VarNumber = 0;
  725 + free(buf);
  726 + return(REPLYRECERR);
  727 + }
  728 +
  729 + /*----- Decoding dimensions array -------------------*/
  730 + xdr_array(&xdrs, (caddr_t *)&(CurrentData[id].Dimensions),
  731 + &count,
  732 + (u_int )DimNumbers-1,
  733 + unixlen[DD_INT],
  734 + (xdrproc_t)xdr_int);
  735 +
  736 + count = 1;
  737 + for(i=0; i < DimNumbers-1;i++)
  738 + {
  739 + count = count*CurrentData[id].Dimensions[i];
  740 + }
  741 + MaxSize = count;
  742 + }
  743 + else
  744 + {
  745 + if(type != NOVAR)
  746 + {
  747 + free(buf);
  748 + return(REPLYRECERR);
  749 + }
  750 + else
  751 + {
  752 + CurrentData[id].VarNumber = 0;
  753 + }
  754 + }
  755 +
  756 + /*---------- Decoding variables -------------------------*/
  757 + if(CurrentData[id].VarNumber != 0) CurrentData[id].Variables = (void *)malloc(CurrentData[id].VarNumber*sizeof(void *));
  758 + else CurrentData[id].Variables = NULL;
  759 +
  760 + for(i = 0; i < CurrentData[id].VarNumber; i++)
  761 + {
  762 + CurrentData[id].Variables[i] = (void *)malloc(unixlen[type]*MaxSize);
  763 + count = MaxSize;
  764 + xdr_array(&xdrs,(caddr_t *)(&(CurrentData[id].Variables[i])),&count,MaxSize,unixlen[type], (xdrproc_t)ConvFunc[type]);
  765 + }
  766 +
  767 + /* Free all */
  768 + free(buf);
  769 + xdr_destroy(&xdrs);
  770 + }
  771 + *data = CurrentData;
  772 + return(LastPacketFlag);
  773 +}
  774 +/*===================================================================*/
  775 +
  776 +/*-------------------------- DD_CLOSE --------------------------------*/
  777 +/*
  778 + *
  779 + * VarID - entry point of ID table
  780 + * Returns 1 if OK or negative err
  781 + * Close Socket if no VarID more ( this information supplyed by server )
  782 + */
  783 +
  784 +int DD_Close(int VarID)
  785 +{
  786 + static caddr_t buf = NULL;
  787 + static XDR xdrs;
  788 + static int op = CLOSEINSREQ;
  789 + int RemainedID; /* Server returns number of remained ID */
  790 + int cc,i;
  791 +/* Allocatein memory and stream */
  792 + buf = (caddr_t)malloc(REQUESTLENGTH);
  793 + xdrmem_create(&xdrs, buf, REQUESTLENGTH, XDR_ENCODE);
  794 +
  795 +/* Encoding the request */
  796 + xdr_int(&xdrs,&op);
  797 + xdr_int(&xdrs,&VarID);
  798 +
  799 +/* Send request */
  800 + if((cc = send(SocketID,buf,REQUESTLENGTH,0)) < 0)
  801 + {
  802 + perror("DD_Close:");
  803 + free(buf);
  804 + xdr_destroy(&xdrs);
  805 + return(REQSENDERR);
  806 + }
  807 + free(buf);
  808 + xdr_destroy(&xdrs);
  809 +
  810 +/* Get reply header */
  811 +
  812 + buf = (caddr_t)malloc(REPLYLENGTH);
  813 +/*
  814 + i = 0;
  815 + while(((cc = recv(SocketID,buf,REPLYLENGTH,0)) < 0) && (i < TRY)) i++;
  816 + if(cc < 0)
  817 +*/
  818 + if((cc = ReceiveFromNet(buf, REPLYLENGTH)) < 0)
  819 + {
  820 + perror("DD_Close:");
  821 + free(buf);
  822 + return(REPLYRECERR);
  823 + }
  824 +
  825 + xdrmem_create(&xdrs, buf, REPLYLENGTH, XDR_DECODE);
  826 + xdr_int(&xdrs,&RemainedID);
  827 + if(RemainedID< 0)
  828 + {
  829 + free(buf);
  830 + xdr_destroy(&xdrs);
  831 + return(RemainedID);
  832 + }
  833 + free(buf);
  834 + xdr_destroy(&xdrs);
  835 +
  836 + if(RemainedID == 0)
  837 + {
  838 + shutdown(SocketID,2);
  839 + close(SocketID);
  840 + SocketID = -1;
  841 +/*
  842 + UserHost[0] = '\0';
  843 + UserName[0] = '\0';
  844 +*/
  845 + }
  846 +
  847 + return(1);
  848 +}
  849 +/*------------------------------------------------------------------------------*/
  850 +
  851 +/*=============== DATABASE UPDATE FUNCTIONS ====================================*/
  852 +/*------------------ DD_AddDataSet() -------------------------------------------*/
  853 +int DD_AddDataSet(char *DataSetName, char *RemSetID, char *BaseName)
  854 +{
  855 + static caddr_t buf = NULL;
  856 + static XDR xdrs;
  857 + static int op = ADDVIREQ;
  858 + int Err; /* Server returns OK or NOEXEC */
  859 + int cc,i,length;
  860 + int CloseFlag = 0;
  861 +
  862 +/* If there is no connection, try to get it */
  863 + if(SocketID < 0)
  864 + {
  865 + if((SocketID = GetSocket()) < 0) return(NOCONNECTION);
  866 + CloseFlag = 1; // To close Connection at the end
  867 + }
  868 +
  869 +/* Allocatein memory and stream */
  870 + buf = (caddr_t)malloc(REQUESTLENGTH);
  871 + xdrmem_create(&xdrs, buf, REQUESTLENGTH, XDR_ENCODE);
  872 +
  873 +/* Encoding the request */
  874 + xdr_int(&xdrs,&op);
  875 +
  876 +/* Coding DataSetName */
  877 + if((length = strlen(DataSetName)) > MAXSETLENGTH) length = MAXSETLENGTH;
  878 + xdr_string(&xdrs, &DataSetName, length);
  879 +/* Coding RemSetID */
  880 + if((length = strlen(RemSetID)) > MAXVARLENGTH) length = MAXVARLENGTH;
  881 + xdr_string(&xdrs, &RemSetID, length);
  882 +/* Coding BaseName */
  883 + if((length = strlen(BaseName)) > MAXVARLENGTH) length = MAXVARLENGTH;
  884 + xdr_string(&xdrs, &BaseName, length);
  885 +
  886 +/* Send request */
  887 + if((cc = send(SocketID,buf,REQUESTLENGTH,0)) < 0)
  888 + {
  889 + perror("DD_AddDataSet:");
  890 + free(buf);
  891 + xdr_destroy(&xdrs);
  892 + return(REQSENDERR);
  893 + }
  894 + free(buf);
  895 + xdr_destroy(&xdrs);
  896 +
  897 +/* Get reply header */
  898 + buf = (caddr_t)malloc(REPLYLENGTH);
  899 + if((cc = ReceiveFromNet(buf, REPLYLENGTH)) < 0)
  900 + {
  901 + perror("DD_AddDataSet:");
  902 + free(buf);
  903 + return(REPLYRECERR);
  904 + }
  905 +
  906 + xdrmem_create(&xdrs, buf, REPLYLENGTH, XDR_DECODE);
  907 + xdr_int(&xdrs,&Err);
  908 +
  909 + if(CloseFlag) // Close everything if function established connection
  910 + {
  911 + shutdown(SocketID,2);
  912 + close(SocketID);
  913 + SocketID = -1;
  914 +/* Session with DD Server was closed, but User Session continues !!!!! */
  915 + /* UserHost[0] = '\0';
  916 + UserName[0] = '\0'; */
  917 + }
  918 + return Err;
  919 +}
  920 +/*-----------------------------------------------------------------------------*/
  921 +
  922 +/*---------------------- DD GET VERSION ---------------------------------------*/
  923 +char *DD_GetVersion()
  924 +/*
  925 + * return static pointer to internal string with the DDLIB-SERVER package version
  926 + */
  927 +{
  928 + static char Version[] = VERSION;
  929 + return (char *)Version;
  930 +}
  931 +/*------------------------- End Library -------------------------------*/
... ...
src/CLIENT/DD_time.c 0 → 100755
  1 +++ a/src/CLIENT/DD_time.c
... ... @@ -0,0 +1,321 @@
  1 +/* ===================================================================
  2 + * Name : DD_time.c
  3 + * Version: : 4.1
  4 + * Author : Andrey Fedorov
  5 + * Institution : IRAP/UPS/CNRS Toulouse
  6 + * Modifications list:
  7 + * Oct 5, 2002: V.3.0, New functions DD_Time2Double and Double2DD_Time were added.
  8 + * March 26, 2010: V.3.1 YEARS up to 2025
  9 + * May 17, 2011: V.4.0 Fedorov, completely revised version.
  10 + * There is no more confuse between Time and Time Interval
  11 + * Sept 05, 2011: V.4.1 SetIntNew => arg TimeKind => to work with 1970-1973 : BR
  12 + *==================================================================*/
  13 +
  14 +#include "DD_time.h"
  15 +#include <stdio.h>
  16 +#include <string.h>
  17 +#include <stdarg.h>
  18 +
  19 +#define YEARS 56
  20 +#define STARTYEAR 1970
  21 +
  22 +/*---- Static array of days shift from Jan-1-1970 -------*/
  23 +/* 1970 1971 1972 1973 1974 1975 1976
  24 + * 1977 1978 1979 1980 1981 1982 1983
  25 + * 1984 1985 1986 1987 1988 1989 1990
  26 + * 1991 1992 1993 1994 1995 1996 1997
  27 + * 1998 1999 2000 2001 2002 2003 2004
  28 + * 2005 2006 2007 2008 2009 2010 2011
  29 + * 2012 2013 2014 2015 2016 2017 2018
  30 + * 2019 2020 2021 2022 2023 2024 2025
  31 + */
  32 +static double
  33 + YearDays[YEARS] = { 0.0, 365.0, 730.0, 1096.0, 1461.0, 1826.0, 2191.0,
  34 + 2557.0, 2922.0, 3287.0, 3652.0, 4018.0, 4383.0, 4748.0,
  35 + 5113.0, 5479.0, 5844.0, 6209.0, 6574.0, 6940.0, 7305.0,
  36 + 7670.0, 8035.0, 8401.0, 8766.0, 9131.0, 9496.0, 9862.0,
  37 + 10227.0, 10592.0, 10957.0, 11323.0, 11688.0, 12053.0, 12418.0,
  38 + 12784.0, 13149.0, 13514.0, 13879.0, 14245.0, 14610.0, 14975.0,
  39 + 15340.0, 15706.0, 16071.0, 16436.0, 16801.0, 17167.0, 17532.0,
  40 + 17897.0, 18262.0, 18628.0, 18993.0, 19358.0, 19723.0, 20089.0};
  41 +
  42 +/*-------------------------------------------------------------
  43 + * DAY_OF_YEAR = monthday[*][month-1]+day_of_month -1
  44 + *------------------------------------------------------------*/
  45 +static int monthday[2][12] =
  46 +{
  47 +{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
  48 +{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
  49 +};
  50 +
  51 +/*------------------------------------------------------------
  52 + * Global static Flag to show the current state of the time
  53 + * processor. Is it Time interval (0), or DD Time (1)
  54 + *----------------------------------------------------------*/
  55 +static int TimeFlag = 1;
  56 +/*================== INTERNAL FUNCTION ====================*/
  57 +/*-------------------- SetInt ----------------------------*/
  58 +void SetInt(dd_tmstr_t *UT)
  59 +{
  60 + SetIntNew(UT,DD_TM_UNKNOWN);
  61 +}
  62 +
  63 +void SetIntNew(dd_tmstr_t *UT,t_DDTimeKind timeKind) /* Fill int values of dd_tmstr_t */
  64 +/* If the double times field of UT structure is defined,
  65 + * this function fills remains fields of Year, day .... separately
  66 + */
  67 +{
  68 + static double msofday = 24.0*60.0*60.0;
  69 + static double msofhour = 60.0*60.0;
  70 + static double msofmin = 60.0;
  71 + long daynumber;
  72 + double msrest;
  73 + int i;
  74 +
  75 + daynumber = (long)(UT->times / msofday);
  76 + for(i=0;i<YEARS;i++) if(daynumber < (long)YearDays[i]) break;
  77 + i--;
  78 +
  79 + switch(timeKind)
  80 + {
  81 + case DD_TM_DATE :
  82 + {
  83 + //it's a date
  84 + UT->year = i+1970;
  85 + UT->day = (int)(daynumber - (long)YearDays[i]);
  86 + break;
  87 + }
  88 + case DD_TM_TIME_INTERVAL :
  89 + {
  90 + //it's a time interval
  91 + UT->year = 0;
  92 + UT->day = (int)(daynumber);
  93 + break;
  94 + }
  95 + default :
  96 + //compatibility mode
  97 + if(i > 3)
  98 + {
  99 + UT->year = i+1970;
  100 + UT->day = (int)(daynumber - (long)YearDays[i]);
  101 + }
  102 + else
  103 + {
  104 + UT->year = 0;
  105 + UT->day = (int)(daynumber);
  106 + }
  107 + break;
  108 + }
  109 +
  110 + msrest = UT->times - (double)daynumber * msofday;
  111 + UT->hour = (int)(msrest / msofhour);
  112 + msrest -= (double)(UT->hour)*msofhour;
  113 + UT->min = (int)(msrest / msofmin);
  114 + msrest -= (double)(UT->min)*msofmin;
  115 + UT->sec = (int)(msrest);
  116 + UT->msec = (int)((msrest - (double)(UT->sec))*1000.0);
  117 + return;
  118 +}
  119 +
  120 +/*---------------- end of SetInt -----------------------*/
  121 +
  122 +/*-------------------------------------------------------
  123 + * SetDouble()
  124 + * Returns the double value of seconds since 1 Jan 1970
  125 + * The calculations are made from already filled dd_tmstr_t.
  126 + * If UT->year
  127 + *------------------------------------------------------*/
  128 +void SetDouble(dd_tmstr_t *UT)
  129 +{
  130 + static double SecInMls = 1.0/1000.0;
  131 + static double SecImMin = 60.0;
  132 + static double SecInHour = 60.0*60.0;
  133 + static double SecInDay = 60.0*60.0*24.0;
  134 + if(UT->year >= STARTYEAR) // This is DD Time !
  135 + UT->times = (double)UT->msec*SecInMls +
  136 + (double)UT->sec +
  137 + (double)UT->min*SecImMin +
  138 + (double)UT->hour*SecInHour +
  139 + (double)UT->day*SecInDay +
  140 + YearDays[(UT->year - 1970)]*SecInDay;
  141 + else if(UT->year < STARTYEAR) // This is Time Interval
  142 + UT->times = (double)UT->msec*SecInMls +
  143 + (double)UT->sec +
  144 + (double)UT->min*SecImMin +
  145 + (double)UT->hour*SecInHour +
  146 + (double)UT->day*SecInDay +
  147 + YearDays[UT->year]*SecInDay;
  148 + else
  149 + UT->times = 0.0;
  150 + return;
  151 +}
  152 +/*----------------- end of SetDouble ---------------------*/
  153 +
  154 +/*=================== PUBLIC FUNCTIONS ==================*/
  155 +/*------------------- DD_Time2Double --------------------*/
  156 +double DD_Time2Double(dd_time_t UTstring)
  157 +{
  158 + static dd_tmstr_t UT;
  159 + static char year[5] = "0000\0";
  160 + static char day[4] = "000\0";
  161 + static char hour[3]= "00\0";
  162 + static char min[3] = "00\0";
  163 + static char sec[3]= "00\0";
  164 + static char msec[4] = "000\0";
  165 +
  166 + strncpy(year,UTstring,4);
  167 + strncpy(day,UTstring+4,3);
  168 + strncpy(hour,UTstring+7,2);
  169 + strncpy(min,UTstring+9,2);
  170 + strncpy(sec,UTstring+11,2);
  171 + strncpy(msec,UTstring+13,3);
  172 +
  173 + sscanf(year,"%d",&(UT.year));
  174 + sscanf(day,"%d",&(UT.day));
  175 + sscanf(min,"%d",&(UT.min));
  176 + sscanf(hour,"%d",&(UT.hour));
  177 + sscanf(sec,"%d",&(UT.sec));
  178 + sscanf(msec,"%d",&(UT.msec));
  179 + if(UT.year < STARTYEAR) TimeFlag = 0; // Time Inetrval
  180 +
  181 + SetDouble(&UT);
  182 + return UT.times;
  183 +}
  184 +/*------------------------------------------------------*/
  185 +
  186 +/*------------------- Double2DD_Time ---------------------*/
  187 + char *Double2DD_Time(double Time)
  188 + {
  189 + static dd_time_t UTstring;
  190 + dd_tmstr_t UT;
  191 +
  192 + UT.times = Time;
  193 + SetInt(&UT);
  194 + sprintf(UTstring,"%04d%03d%02d%02d%02d%03d",(UT.year),(UT.day),(UT.hour), (UT.min), (UT.sec),(UT.msec));
  195 + return &(UTstring[0]);
  196 + }
  197 +/*------------------------------------------------------------*/
  198 +
  199 +/*================== BACKUP COMPABILITY FUNCTIONS =================*/
  200 +/*-----------------------------------------------------------------
  201 + * ReadTime()
  202 + * Reads a standard DD time string as an argument
  203 + * and converts it into dd_tmstr_t structure.
  204 + * Function returns the pointer to the internal startic structure dd_tmstr_t.
  205 + * Function redefines TimeFlag.
  206 + *----------------------------------------------------------------*/
  207 +dd_tmstr_t *ReadTime(char *UTstring)
  208 +{
  209 + static dd_tmstr_t UT;
  210 + static char year[5] = "0000\0";
  211 + static char day[4] = "000\0";
  212 + static char hour[3]= "00\0";
  213 + static char min[3] = "00\0";
  214 + static char sec[3]= "00\0";
  215 + static char msec[4] = "000\0";
  216 +
  217 + strncpy(year,UTstring,4);
  218 + strncpy(day,UTstring+4,3);
  219 + strncpy(hour,UTstring+7,2);
  220 + strncpy(min,UTstring+9,2);
  221 + strncpy(sec,UTstring+11,2);
  222 + strncpy(msec,UTstring+13,3);
  223 +
  224 + sscanf(year,"%d",&(UT.year));
  225 + sscanf(day,"%d",&(UT.day));
  226 + sscanf(min,"%d",&(UT.min));
  227 + sscanf(hour,"%d",&(UT.hour));
  228 + sscanf(sec,"%d",&(UT.sec));
  229 + sscanf(msec,"%d",&(UT.msec));
  230 +
  231 + if(UT.year < STARTYEAR) TimeFlag = 0; // Time Inetrval
  232 +
  233 + SetDouble(&UT);
  234 + return(&UT);
  235 +}
  236 +/*-------------------- end of ReadTime ------------------------*/
  237 +
  238 +/*---------------------- Write Time ---------------------------*/
  239 +/* Function Write time convert use only double times field
  240 + * of dd_tmstr_t structure to print time in DD style
  241 + * in internal static string. The integer fields redefined.
  242 + * Function return string pointer.
  243 + */
  244 +
  245 +char *WriteTime(dd_tmstr_t *UT)
  246 +{
  247 + static dd_time_t UTstring;
  248 +
  249 + SetInt(UT);
  250 + sprintf(UTstring,"%04d%03d%02d%02d%02d%03d",(UT->year),(UT->day),(UT->hour),
  251 + (UT->min), (UT->sec),(UT->msec));
  252 + return(UTstring);
  253 +}
  254 +/*------------------- end of WriteTime -------------------*/
  255 +
  256 +void WriteFmtTime(dd_tmstr_t *UT,char *UTstring)
  257 +{
  258 + SetInt(UT);
  259 + sprintf(UTstring,"%04d:%03d:%02d:%02d:%02d",(UT->year),(UT->day),(UT->hour),
  260 + (UT->min), (UT->sec));
  261 +}
  262 +/*------------------- end of WriteFmtTime -------------------*/
  263 +
  264 +/*=========================================================
  265 + * Functions for DECODERs
  266 + * These functions make conversion from/to DD double/DD_time_structure and
  267 + * a integer array as follows:
  268 + * {Year, Month, Day_Of_Month, Hour, Min, Sec, Mls}
  269 + *========================================================*/
  270 +/*--------------------------------------------------------
  271 + * UT2double()
  272 + * Fille the DD_time_structure with double fild from the
  273 + * integer array (see the section header)
  274 + *-------------------------------------------------------*/
  275 +dd_tmstr_t *UT2double(unsigned *ut)
  276 +/* Fill the standard structure with double too using as
  277 + * argument 7 int length array in Gavrilova Passport Standard
  278 + */
  279 +{
  280 +static dd_tmstr_t UT;
  281 +int visocos;
  282 +
  283 +if(ut[0]%4 == 0) visocos = 1; else visocos = 0;
  284 +UT.year = ut[0];
  285 +UT.day = monthday[visocos][ut[1] - 1]+ut[2] - 1;
  286 +UT.hour = ut[3];
  287 +UT.min = ut[4];
  288 +UT.sec = ut[5];
  289 +UT.msec = ut[6];
  290 +
  291 +SetDouble(&UT);
  292 +return(&UT);
  293 +}
  294 +/*-------------------------------------------------------*/
  295 +/*-------------------------------------------------------
  296 + * Double2UT()
  297 + * Converts Standard DD double time to interger array (see
  298 + * the section header)
  299 + *--------------------------------------------------------*/
  300 +unsigned *Double2UT(double t)
  301 +{
  302 + static unsigned UT[7];
  303 + dd_tmstr_t tm;
  304 + int i,visocos;
  305 +
  306 + tm.times = t;
  307 + SetInt(&tm);
  308 + if(tm.year % 4 == 0) visocos = 1; else visocos = 0;
  309 + i = 0;
  310 + while((i < 12) && (tm.day >= monthday[visocos][i])) i++;
  311 + UT[0] = tm.year;
  312 + UT[1] = i;
  313 + UT[2] = tm.day +1 - monthday[visocos][i-1];
  314 + UT[3] = tm.hour;
  315 + UT[4] = tm.min;
  316 + UT[5] = tm.sec;
  317 + UT[6] = tm.msec;
  318 +
  319 + return( (unsigned *)UT);
  320 +}
  321 +/*=======================================================================*/
... ...
src/INCLUDE/DD.h 0 → 100755
  1 +++ a/src/INCLUDE/DD.h
... ... @@ -0,0 +1,135 @@
  1 +/*=================================================================================================
  2 + * DD SYSTEM
  3 + * DD.h
  4 + * Version: 6.0
  5 + * Description: The public header to use DD library libDD.a
  6 + * List of changes:
  7 + * Apr. 17, 2002 Fedorov, - New error constant to interrupt the
  8 + * transmission if data dimensions are changed from file
  9 + * to file
  10 + * Nov 18, 2004 - V.4.2 - Fedorov, New errors for CACH manipulating
  11 + * Jun 17, 2007 - V.4.6 Fedorov New requestes and external executables
  12 + * Aug 02, 2007 - V.4.7 Fedorov Modification of call external executables
  13 + * Sep 24, 2007 - V.5.0 Fedorov New status of Get Data: MOREDELAY
  14 + * May 21, 2008 - V.5.1 Fedorov New Status of SetTime: CTIMEISSHIFTED
  15 + * Oct 18, 2012 - V.5.2 Knizhnikova New DD_SetTimeInfo() function
  16 + *=================================================================================================*/
  17 +
  18 +#include "DD_time.h"
  19 +
  20 +typedef struct { int type; /* Type of variable in netcdf style */
  21 + int DimNumber; /* number of dimensions */
  22 + int *Dimensions; /* Dimensions array
  23 + * fastest change is last */
  24 + int VarNumber; /* Dimension of variable array */
  25 + void **Variables;/* Variables array pointer
  26 + * It is static array refreshed
  27 + * each call
  28 + */
  29 + } DD_data_t;
  30 +
  31 +/*------------------- FUNCTIONS ---------------------------*/
  32 +
  33 +extern int DD_SetVariable(char *VarName);
  34 +/*
  35 + * VarName - full name of variable <project>:<instrument>:<Variable>
  36 + * Returns VarID or negative in case of error (see bellow)
  37 + */
  38 +
  39 +extern int DD_GetInform(int VarID,char *AttrName, DD_data_t **data);
  40 +/*
  41 + * VarID - Variable ID from DD_SetVariable
  42 + * AttrName - name of attribute ( defined by konvention )
  43 + * data - address of data structure
  44 + * Returns 1 if OK and negative value in case of error (see bellow)
  45 + */
  46 +
  47 +extern int DD_SetTime(int VarID, char *Time);
  48 +/*
  49 + * VarID - Variable ID from DD_SetVariable
  50 + * Time - string defined in DD_time.h
  51 + * Returns 1 if OK and negative value in case of error (see bellow)
  52 + */
  53 +
  54 +extern int DD_SetTimeInfo(int VarID, char *Time, double *RealTime);
  55 +/*
  56 + * VarID - Variable ID from DD_SetVariable
  57 + * Time - string defined in DD_time.h
  58 + * RealTime - time pointer was set to
  59 + * Returns 1 if OK and negative value in case of error (see bellow)
  60 + */
  61 +
  62 +extern int DD_GetMultiData(int VarID, size_t VarSize, char **VarNames, char *TimeInt, DD_data_t **data, int BackFlag);
  63 +/*
  64 + * VarID - Variable ID from DD_SetVariable
  65 + * VarSize - number of variables to return
  66 + * VarNames - the array of Names of the requested Variable
  67 + * TimeInt - String of Time interval in DD_time style
  68 + * data - Data structures array
  69 + * BackFlag - 0 - pointer is at the lasy position, 1 - pointer returns to the start point
  70 + * Returns 1 if OK and negative value in case of error (see bellow)
  71 + */
  72 +
  73 +/* ----------------------------------------
  74 + * This function below just call DD_GetMultiData
  75 + * for backup
  76 + *---------------------------------------*/
  77 +extern int DD_GetData(int VarID, char *VarName, char *TimeInt, DD_data_t **data);
  78 +
  79 +extern int DD_MovePoint(int VarID, int RecordNumber);
  80 +/*
  81 + * VarID - Open virtual instrument ID
  82 + * int RecordNumber - +/- records to move
  83 + * Move pointer in the open instrument and return 1 or negative if error
  84 + */
  85 +
  86 +extern int DD_Close(int VarID);
  87 +/*
  88 + * VarID - Variable ID from DD_SetVariable
  89 + * Returns 1 if OK and negative value in case of error (see bellow)
  90 + */
  91 +
  92 +extern char *DD_GetVersion();
  93 +/*
  94 + * return static pointer to internal string with the DDLIB-SERVER package version
  95 + */
  96 +
  97 +/*----------- Data Update functions -----------------------------------*/
  98 +extern int DD_AddDataSet(char *DataSetName, char *RemSetID, char *BaseName);
  99 +/*
  100 + * Request for new VI. See ../DOC/TECHDOC/DDServFunct.html
  101 + */
  102 +
  103 +/*--------------------- CONSTANTS -----------------------------------------*/
  104 +#define MOREDATA 1 /* There is data, but we have to call GetData again right now*/
  105 +#define MOREDELAY 2 /* There is data, but we have to call GetData again after delay */
  106 +#define OK 0 /* It is last data packet */
  107 +#define NOCONNECTION -1
  108 +#define TOOMANYREQ -2
  109 +#define REQSENDERR -3
  110 +#define REPLYRECERR -4
  111 +#define NOID -5
  112 +#define NOREFFILE -6
  113 +#define NOTIMESFILE -7
  114 +#define NOINFOFILE -8
  115 +#define NOVAR -9
  116 +#define OUTOFTIME -10
  117 +#define CACHERR -11 /* The error occured when program manipulated the cach */
  118 +#define CACHTOOREC -33 /* Off files in the CASH are created less then 5 sec ago */
  119 +#define WAITEXTCALL -34 /* Server Waits external call finish */
  120 +#define TRYAGAIN -35 /* Times file is locked. This request should be repeated again */
  121 +#define NODATAATTIME -36 /* Requested time is inside NODATA time interval */
  122 +#define GAPISSMALL -37 /* Gap is too small to call external archive */
  123 +#define CTIMEISSHIFTED -38 /* The request was in NoData interval, try again with time at the end */
  124 +#define DATAFILEERR -12 /* The error while manipulate with data file */
  125 +#define ENVIRERROR -13 /* Error in Environments */
  126 +#define NOPOINTER -14 /* The pointer points nowhere, SetTime were failed */
  127 +#define INTSERERR -15 /* Server internal error */
  128 +#define TIMEINEMPTY -16 /* No data for specified time interval */
  129 +#define NOEXEC -17 /* No executable */
  130 +
  131 +#define DD_SHORT 4
  132 +#define DD_INT 1
  133 +#define DD_FLOAT 2
  134 +#define DD_DOUBLE 3
  135 +#define DD_CHAR 0
... ...
src/INCLUDE/DD_Access.h 0 → 100755
  1 +++ a/src/INCLUDE/DD_Access.h
... ... @@ -0,0 +1,93 @@
  1 +/* ======================================================
  2 + *
  3 + * DD_Access.h
  4 + * V.2.0
  5 + * Last revision: Oct 7, 2002
  6 + * List of revisions: 1997 - version 1.0
  7 + * Oct 7, 2002 - version 2.0 (update a little )
  8 + */
  9 +
  10 +#define MAXHOSTLENGTH 16 /* IP-address: "255.255.255.255\0" */
  11 +#define USRLENGTH 21 /* Length of UserName: + \0 */
  12 +#define TICKETLENGTH 9 /* Length of passwd: 8 + \0 */
  13 +#define HOSTNAMELENGTH 120 /* Length of the user host name */
  14 +#define USERCASHLEN 100 /* Size of user_ticket.nc file must be 300 */
  15 +#define NONAME "no_name\0" /* Name of user in case of non-WEB connection */
  16 +#define ACCINSTR "iball:acc:all" /* Instrument which watch the access */
  17 +#define TICKET_PATH "/ACC/user_ticket.nc"
  18 +#define USERREFNAME "/ACC/user_info.nc"
  19 +#define LOGFILE "/ACC/login.log"
  20 +
  21 +/*------------ Errors of ACCESS ---------------------*/
  22 +#define NOPERMISSION -100
  23 +#define NOHOST -101
  24 +#define NOUSERSFILE -102
  25 +
  26 +/*--------------- Extern global variables -------------------*/
  27 +extern char UserName[USRLENGTH]; /* defined in DD_client.c */
  28 +extern char UserHost[MAXHOSTLENGTH]; /* defined in DD_client.c */
  29 +extern int UserID; /* defined in DD_client.c */
  30 +
  31 +/*--------------- Extern Functions ---------------------------*/
  32 +extern int FillStruct (int argc, void **argv);
  33 +/* This function used to set up the host address from IDL (when WWW access used)
  34 + * Arguments allocation is as follows:
  35 + * UserName - 0
  36 + * UserHost - 1
  37 + * Location: DD_idl.c -> DD_idl.so
  38 +*/
  39 +
  40 +extern int GetTicket(int UID, char *HostName, int DD_user_id);
  41 +/* Description: This function find the user data in user_cash.nc
  42 + * If O'k rewrite the line with new time.
  43 + * In case of a new user, remove the first line with
  44 + * older time data then a current time + 4.5 hours.
  45 + *
  46 + Takes 3 arguments: UserId (id in the romote host)
  47 + Remote host address(string,like "193.232.6.60\0")
  48 + DD_user_id(can see in user_info.nc)
  49 +
  50 + Returns 0 if O'k or NOPERMISSIONS, or ERROR
  51 +
  52 + If DD_log_name equal NULL searching for UserId, IP-address
  53 + If DD_log_name nonequal NULL searching for IP-address,DD_log_name*
  54 + *
  55 + */
  56 +extern int CheckTicket(char *NameUsr, char *Ticket);
  57 +/* Description: This function check if user exosts
  58 + * in user_info.nc file. Returns DD_id if O'k.
  59 + * It returns NOPERMISSION or other errors
  60 + */
  61 +
  62 +extern int ShowTicket(int userid, char *hostname, char *DD_name);
  63 +/*
  64 + * Show if user has authorisation to work
  65 + */
  66 +
  67 +extern int LoginRequest(char *UserPasswd, char *UserLogin, char *HostName);
  68 +/* Description: Library function for client-server using.
  69 + * Send ID, Password,UserLogin, and host to server.
  70 + * Compares the information with your {id,hostname and other}.
  71 + * Returns 0 if O'k, or a negative value in case
  72 + * of "NOPERMISSION" or error.
  73 + *
  74 + */
  75 +extern int SetUser(int UserID, char *HostName, char *LogName);
  76 +/* Description: Library function for client-server using.
  77 + * Send UserID, HostName to server.
  78 + * Compares the information with your {id,hostname}.
  79 + * Returns 1 if O'k, or a NOPERMISSION, or error number
  80 + */
  81 +
  82 +extern int CheckID(char *NameUsr);
  83 +/* Description: This function check the user name in user_info.nc file.
  84 + * Returns DD_id if exists.
  85 + * It returns NOPERMISSION or other errors
  86 + */
  87 +
  88 +extern void Put2Log(int UID, char *Host, char *LogName, int error);
  89 +/* Description: This function logs a user's ID, IP-address of a local host,
  90 + * login name and permission information into log file.
  91 + *
  92 + */
  93 +
... ...
src/INCLUDE/DD_comm.h 0 → 100755
  1 +++ a/src/INCLUDE/DD_comm.h
... ... @@ -0,0 +1,383 @@
  1 +/*=================================================================================
  2 + * DD SYSTEM base package
  3 + * DD_Server DD_Client library
  4 + * DD_comm.h
  5 + * V. 6.0
  6 + * Changes listing:
  7 + * Feb 27 1995 - V 1.0
  8 + * 13 Apr. 2002 - changed for NetCDF 3.3
  9 + * 03 Oct. 2002 - v.4.0 Fedorov, communication ideology is changed
  10 + * Oct 31, 2002 - V.4.1 Fedorov, UserName, UserHost and UserID transferred into DD_Access.h
  11 + * May 7, 2003 - V.4.2 Fedorov, The Cash structure is changed (flag of open file )
  12 + * June 17, 2003 - V.4.3 Fedorov, The Maximal Packet Size is changed
  13 + * Nov 18, 2004 - V.4.4 Fedorov, Some changes
  14 + * Aug 17, 2005 - V.4.5 Fedorov, Cach Time constant is changed
  15 + * Jun 17, 2007 - V.4.6 Fedorov, New requestes and external executables
  16 + * Aug 01, 2007 - V.4.7 Fedorov, Cache length = 20, New DD_Var_t structure
  17 + * Sep 20, 2007 - V.5.0 Fedorov, Update Time Info library now in the separate file
  18 + * Sep 23, 2007 - V.5.1 Fedorov, New interface of SetTime
  19 + * Sep 25, 2007 - V.5.2 Fedorov, Individual minimal gap
  20 + * Oct 08, 2007 - V.5.3 Budnik, php createVI.php <baseID> <remSetID> <ddSetID>
  21 + * Jan 25, 2008 - V.5.3.1 Budnik, min data gap = 1 day!!!!
  22 + * May 22, 2008 - V.5.4 Fedorov, DD_Var_t has a LockStartTime value
  23 + * May 27, 2008 - V.5.5 Fedorov, Maximal tracnsmition buffer
  24 + * Sep 19, 2008 - V.5.6 MAXVARLENGTH=64 REQUESTLENGTH 184
  25 + * Dec 15, 2012 - V.6.0 New multiparam Get_MultiData() function
  26 + *===================================================================================*/
  27 +
  28 +#include <stdio.h>
  29 +#include <sys/errno.h>
  30 +#include <stdlib.h>
  31 +#include <string.h>
  32 +#include <sys/types.h>
  33 +#include <sys/time.h>
  34 +#include <time.h>
  35 +#include "DD_Access.h"
  36 +
  37 +#ifdef SOLARIS
  38 +#include <sys/socket.h>
  39 +#include <netdb.h>
  40 +#include <netinet/in.h> /* internet stile addres */
  41 +#include <rpc/types.h>
  42 +#include <rpc/xdr.h>
  43 +#include <rpc/rpc.h>
  44 +#endif /* SOLARIS */
  45 +
  46 +#ifdef HPUX
  47 +#include <sys/socket.h>
  48 +#include <netinet/in.h>
  49 +#include <netdb.h>
  50 +#include <sys/un.h>
  51 +#include <rpc/xdr.h>
  52 +#include <rpc/rpc.h>
  53 +#endif
  54 +
  55 +#ifdef OSF1
  56 +#include <sys/socket.h>
  57 +#include <netdb.h>
  58 +#include <arpa/inet.h>
  59 +#include <rpc/xdr.h>
  60 +#endif /* OSF1 */
  61 +
  62 +#ifdef LINUX
  63 +#include <sys/socket.h>
  64 +#include <netinet/in.h>
  65 +#include <netdb.h>
  66 +#include <rpc/rpc.h>
  67 +#include <rpc/xdr.h>
  68 +#endif /* LINUX */
  69 +
  70 +#ifdef SUNOS
  71 +#include <sys/socket.h>
  72 +#include <sys/socketvar.h>
  73 +#include <netinet/in.h>
  74 +#include <netdb.h>
  75 +#include <rpc/xdr.h>
  76 +#endif /* SUNOS */
  77 +
  78 +/*----------------- Defenitions of request and server replies --------------------*/
  79 +/* 1. Data manipulation requests */
  80 +#define OPENINSREQ 0 /* Open virtual instrument */
  81 +#define DATAINFOREQ 1 /* Request of constant info */
  82 +#define TIMESETREQ 2 /* Position of pointer by StartTime*/
  83 +#define DATAGETREQ 3 /* Data request by time interval */
  84 +#define CLOSEINSREQ 4 /* Request to close virtual instrument */
  85 +#define MOVPOINTREQ 5 /* Move the pointer od data request*/
  86 +#define ADDVIREQ 6 /* Add New virtual instrument */
  87 +
  88 +/* 2. Security requests */
  89 +#define GETTICKETREQ 10
  90 +#define SHOWTICKETREQ 11
  91 +
  92 +/*-------- Some constants ------------------*/
  93 +#define EMPTY 0 /* Filler of the trailer */
  94 +#define FILEACCMARG 1 /* The minimum time from the last access to remove this file */
  95 +
  96 +/*------------ Important lengths and pathes ----------------*/
  97 +#define PROTOCOL 0 /* protocol TCP */
  98 +#define REPLYLENGTH 12 /* Length of header of reply packet */
  99 +#define REQUESTLENGTH 196 /* Length of request packets MAXSETLENGTH + 2*MAXVARLENGTH + 16 */
  100 +#define MAXVARLENGTH 64 /* Length (with \0) of Variable Name */
  101 +#define MAXSETLENGTH 52 /* Max Length of VI name */
  102 +#define PATHLENGTH 128 /* Length of complete path */
  103 +#define MAXFILENAME 32 /* The maximal length of the data file (info, cach, times as well)*/
  104 +#define REFNAME "/refer.nc" /* path name for databse refer file */
  105 +#define CASHLEN 20 /* Length of cash array */
  106 +#define TRY 100 /* How many tymes to ask the socket */
  107 +#define MAXPACKSIZE 5000000 /* Maximal size of one packet of transmission in bytes */
  108 +#define MAXCOMMANDL 300 /* Command in system() maximal length
  109 +/*-------------------------------------------------
  110 + * XDR length to calcolate the total len
  111 + *-------------------------------------------------*/
  112 +#define XDRINTLEN 4
  113 +#define XDRFLOATLEN 4
  114 +#define XDRDOUBLELEN 8
  115 +// String length is counted as 4B + N + r (to completed to 4 bytes)
  116 +
  117 +/*------------ List of External Call of DD_Server and ERRORS -------------------*/
  118 +#define ADDDATASETCALL "php %s/createVI.php %s %s %s" /* Format to call to create new VI */
  119 +#define GETNEWDATACALL "php %s/getData%s.php %s %s %s %s &" /* Format to call to get new data */
  120 +#define NOPHP 32512
  121 +#define NOSCRIPT 256
  122 +#define PHPOK 0
  123 +
  124 +/*------ Constant to understand data availabilities -------------------------------*/
  125 +#define GLOBSTARTNAME "GlobalStart"
  126 +#define GLOBSTOPNAME "GlobalStop"
  127 +#define SAMPLNAME "MinSampling"
  128 +#define REMARCHNAME "DataBaseID"
  129 +#define REMINSTNAME "DataSetID"
  130 +#define MINGAP 86400.0 /*Seconds. The minimal time gap to set up the flag DATAGAP */
  131 +#define REQTIMEINT 86400.0 /* One day, +/- of request time interval */
  132 +#define ISOTIMEF "%4u%*1c%2u%*1c%2u%*1c%2u%*1c%2u%*1c%2u%*1c%3u" /* Format to READ time in ISO format */
  133 +#define ISOTIMEP "%04u-%02u-%02uT%02u:%02u:%02u.%03uZ" /* Format to PRINT time in ISO format */
  134 +#define NODATASTR "NODATA"
  135 +#define DIRLOCK "LOCK"
  136 +
  137 +#define QUANTOFFSET 0.01
  138 +/*------------- More internal specifications -----------------------*/
  139 +/*
  140 + * See ../DOC/TECHDOC/DDGenProt.html (lyx)
  141 + */
  142 +
  143 +/* Reply variables:
  144 + * Error - negative value described in DD.h
  145 + * Type - int (see DD.h)
  146 + * Dim_Number - int ( the dimension (vector, matrix, cube, etc) ov the variable)
  147 + * Data_Size - int (the size of the data packet in bytes)
  148 + * RemID - int (number of virtual instruments still open in this session)
  149 + * Dim - int (the particular dimension )
  150 + * LastPacketFlag - int ( == OK in this packet is last, or MOREDATA)
  151 + * Data - array of Type of Dim X Dim X....X Dim size
  152 + * --------------------
  153 + * Dim_Number
  154 + * DataPacket:
  155 + *
  156 + * <LastPacketFlag> |
  157 + * <Dim> | |
  158 + * <.....> | Dim_Number | Data_Size bytes
  159 + * <Dim> | |
  160 + * <data> |
  161 + * ..... | only for real data |
  162 + * <data> | |
  163 + *
  164 + * Note is the value is scalar - the Dim = 0 (???)
  165 + */
  166 +
  167 +/* REPLY SPECIFICATION
  168 + *
  169 + * Reply consists Header 12 bytes length and Data Block
  170 + *
  171 + * on Open Virtual instrument:
  172 + * <OPENINSREQ><ID/Eroor><EMPTY><EMPTY>
  173 + * on Constant Info request:
  174 + * <DATAINFOREQ><Type/Error><Dim_Number><Data_Size><DataPacket>
  175 + * on Set pointer by StartTime:
  176 + * <SETTIMEREQ><EMPTY/Error><EMPTY><EMPTY>
  177 + * on Get Data by TimeInt :
  178 + * <DATAGETREQ><Type/Error><Dim_Numbers><Data_Size><LastRecordFlag><DataPacket>
  179 + * on Move pointer with records number
  180 + * <MOVPOINTREQ><EMPTY/Error><EMPTY><EMPTY>
  181 + * on Close Virtual Instrument
  182 + * <CLOSEINSREQ><RemID/Error><EMPTY><EMPTY>
  183 + */
  184 +
  185 +/*-------------------- TYPEDEF ---------------------------*/
  186 +typedef struct { char names[CASHLEN][MAXSETLENGTH];
  187 + long times[CASHLEN];
  188 + int FileOpen[CASHLEN]; /* 1 if file is open */
  189 + int ID; /* ID of open cach file */
  190 + int nameID; /* ID of names array */
  191 + int timeID; /* ID of times array */
  192 + int fopenID; /* ID of fopen flag */
  193 + } DD_cash_t; /* The structure holding cash informaton
  194 + * of particular virtual instrument DataBase
  195 + */
  196 +
  197 +/*
  198 + * This structure corresponds to ONE requested variable
  199 + * of some Virtual instrument
  200 + */
  201 +typedef struct { char InstrName[MAXSETLENGTH]; /* Virtual Instrument Name */
  202 + char path[PATHLENGTH]; /* Path to directory of open virtual instrument */
  203 + /*---------------------------------------
  204 + * Cache part
  205 + *--------------------------------------*/
  206 + DD_cash_t Cash; /* Cash holder */
  207 + int CurrCushN; /* Current cash pointer */
  208 + /*--------------------------------------
  209 + * This is the part of open data file and corresponding data set
  210 + *-------------------------------------*/
  211 + int ncID; /* ID of open nc_file */
  212 + size_t nc_rec; /* the current record number nc_file */
  213 + size_t Maxnc_rec; /* Maximum of records number in in the current nc file */
  214 + DD_data_t *VarData; /* Static pointer. Variables Holder */
  215 + size_t ParamSize; /* Number or requested variables to save */
  216 + /*---------------------------------------------
  217 + * This is part of times file of given VI
  218 + *--------------------------------------------*/
  219 + char TimesFileName[PATHLENGTH];
  220 + double SDTime; /* Requested Start Time in double form */
  221 + double FDTime; /* Requested Stop Time in double form */
  222 + double CDTime; /* Current Time in double form */
  223 + int tmID; /* ID of "times" file of this virtual instrument*/
  224 + int NameID; /* ID of FileName variable in times file */
  225 + int StartID; /* ID of Start variable in times file */
  226 + int StopID; /* ID of Stop variable in times file */
  227 + size_t TimeRecNumber; /* Current Record number in the "times" file */
  228 + size_t MaxTimeRecNum; /* Maximum records number in the "times" file */
  229 + int RValidMin; /* Minimal record with valid data */
  230 + int RValidMax; /* Maximal record with valid data */
  231 + double MinValidTime;
  232 + double MaxValidTime; /* Start of RValidMin, and stop of RValidMax */
  233 + int CurrRmin; /* Sure that looking time is greater than stop; -1 if NOT */
  234 + int CurrRmax; /* Sure that looking time is less than start; -1 if NOT */
  235 + /*------- Working with external Data Base ------------------------------*/
  236 + int VILocked; /* Flag to show that request to remote database has been sent */
  237 + time_t LockStartTime; /* Value to calculate a time elapsed from lock made by THIS VI */
  238 + /*---------- This is the part of Info file of given VI -----------------*/
  239 + int attrID; /* ID of constant information nc_file */
  240 + char AttrName[PATHLENGTH]; /* Name of constant information file */
  241 + DD_data_t AttrData; /* Dimensions of Attributes */
  242 + /*---- Part concerning External call ------------------*/
  243 + double MinGap; /* The minimal gap between two files */
  244 + double GlobalStart; /* The principal begin of data */
  245 + double GlobalStop; /* The principal end of data */
  246 + char BaseName[MAXSETLENGTH]; /* The name of external data archive */
  247 + char RemSetID[MAXSETLENGTH]; /* The name of VI in exterval archiving */
  248 + int ExtCallAllowed; /* 1 If Server can call external archiving */
  249 + /*------------ Flow Control -----------------------------*/
  250 + int LastPacketFlag; /* OK - request is completed,
  251 + * MOREDATA - one or several blocks expected,
  252 + * MOREDELAY - wait, system is blocked */
  253 + int LastFileStatus; /* The file status after the last SetNewFile */
  254 + int NewFile; /* 1 if File was changed, VI has to be refreshed*/
  255 + int NewFileWasOpen; /* 1 if the original position of pointer
  256 + * (in data file, times file) was lost after open
  257 + * a new data file */
  258 + } DD_Var_t;
  259 +
  260 +/*---------------- Usefull enumerations ---------------------*/
  261 +enum SearchRet {REACHLEFT, REACHRIGHT, OKLEFT, OKRIGHT};
  262 + /*
  263 + * enumerate of the status of time inteval searching
  264 + * NOONEDATA - no data at al in this VI
  265 + * INSIDE - CTime is inside valid data interval (tolerance is MINGAP)
  266 + * DATAATRIGHT, DATAATLEFT - Valid interval is on the right/left from CTime
  267 + */
  268 +enum SearchIntRet {NOONEDATA, INSIDE, DATAATRIGHT, DATAATLEFT, IDLE};
  269 +
  270 +/* Return function IsTimesLocked */
  271 +enum LockStatus {NOLOCK, LOCKED, LOCKREMOVED};
  272 +
  273 +
  274 +/*------------------ Function for Server ---------------------*/
  275 +extern int OpenInstr(char *InstrName);
  276 +/*
  277 + * Open Virtual instrument by name and returns the ID
  278 + * Returns negative value in case of error (see DD.h)or OK
  279 + */
  280 +extern int GetAttribute(int ID, char *Name);
  281 +/*
  282 + * Variable - address of structure with variable description
  283 + * Name - name of attribute
  284 + * Returns OK or an error (see DD.h)
  285 + */
  286 +extern int GetMultiData(int ID, int VarSize, char **VarNames, char *TimeInterval, int BackFlag);
  287 +/*
  288 + * VarSize - size of the array of Names
  289 + * Names - array of strings with names of requested variables,
  290 + * TimeInterval - Time in DD_time.h style
  291 + * Returns negative value in case of error (see bellow)
  292 + * Returnes MOREDATA if "there is more data", and OK if data is finished.
  293 + */
  294 +
  295 +extern int SetTime(DD_Var_t *D, double CTime);
  296 +/*#################################################################
  297 + * SET TIME
  298 + * Set time and try to open appropriate data file. If not try to
  299 + * call external archive
  300 + * D - address of VI holder
  301 + * Time - Time in DD_time.h style
  302 + * Return:
  303 + * OK
  304 + * NOID - call with uncorrect VI holder
  305 + * OUTOFTIME - Requested time is out of General time limitation
  306 + * WAITEXTCALL - Server sent request to external archive
  307 + * TRYAGAIN - VI is blocked by call to external database
  308 + * NODATAATTIME - request time is inside NODATA time interval
  309 + * some return of SetNewFile(); see ...
  310 + *#################################################################*/
  311 +
  312 +extern int CloseID(int ID);
  313 +/* ID - integer identificator of opened Data Set
  314 + * Returns number of remained IDs of this communication seasson
  315 + * in case of 0 the server closes this comminication session
  316 + */
  317 +
  318 +int SetNewFile(DD_Var_t *D, int N);
  319 +/*
  320 + * Function tries to get new data for the gap beetween files, or just
  321 + * open a new data file according to offset N referring to current position in the times file.
  322 + * The current position changed if file is succesefully open.
  323 + * Return values:
  324 + * OK
  325 + * OUTOFTIME - next interval exceeeds GlobalStart/Stop
  326 + * TIMEINEMPTY - next interval marked as "NODATA"
  327 + * TRYAGAIN - the VI is blocked while new data is arriving
  328 + * WAITEXTCALL - new data is requested
  329 + * CACHTOOREC - now free space in the CACH
  330 + * CHACHERR - unrecovable error in CACH
  331 + * DATAFILEERR - unrecovable error in data file
  332 + */
  333 +
  334 +size_t MaxRecord(int ncID);
  335 +/*
  336 + * Inspect all variables and dimensions of the file (exept Time associated) and
  337 + * returm maximal record number to transmit
  338 + */
  339 +/*------------------ Global constants ----------------------------------*/
  340 +static u_int xdrlen[] = {4,4,4,8,4};
  341 +static size_t unixlen[] = {sizeof(char),sizeof(int),sizeof(float),sizeof(double),sizeof(short)};
  342 +static bool_t ( *ConvFunc[5])() = {xdr_char, xdr_int, xdr_float, xdr_double, xdr_short};
  343 +
  344 +/*------------------ Global data variable for entire session --------------------*/
  345 +extern DD_Var_t **DD_Var ; /* Actually this variable is implimented
  346 + * in DD_GetData.c . The dimension of this array is defined
  347 + * by sysconf(_SC_OPEN_MAX)*/
  348 +extern size_t MaxIDNumber; /* Size of DD_Var array. Defined actually in DD_GetData.c */
  349 +
  350 +/*
  351 + * Fuctions prototypes in ExtDataRequest.c file
  352 + */
  353 +/*======================================================================
  354 + * IsTimesLocked
  355 + * Return 1 if there is LOCK in the VI directory
  356 + *======================================================================*/
  357 +extern int IsTimesLocked(DD_Var_t *DD_Var);
  358 +
  359 +/*======================================================================
  360 + * ExtDataRequest
  361 + * Return folowing values:
  362 + * OK - request is accepted SERVER has to wait when LOCK file is gone
  363 + * NOEXEC - error in external executable
  364 + * NODATAATTIME - time corresponds to the NODATA interval
  365 + * GAPISSMALL - Time is inside too small gap
  366 + *======================================================================*/
  367 +extern int ExtDataRequest(DD_Var_t *DD_Var, double CurrTime);
  368 +
  369 +/*=======================================================================
  370 + * UpdateTimeInfo.c
  371 + * int SearchLeft(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax)
  372 + * int SearchRight(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax)
  373 + * Search the next to the left(right) non-empty time interval
  374 + * DD_VarL - common data structure corresponding to THIS open VI
  375 + * Rmin, Rmax - start points
  376 + *
  377 + * int UpdateTimeInfo(DD_Var_t *DD_VarL)
  378 + * Function reopen "times" file and update all time constants
  379 + *======================================================================*/
  380 +extern int SearchLeft(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax);
  381 +extern int SearchRight(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax);
  382 +extern int UpdateTimeInfo(DD_Var_t *DD_VarL);
  383 +
... ...
src/INCLUDE/DD_time.h 0 → 100755
  1 +++ a/src/INCLUDE/DD_time.h
... ... @@ -0,0 +1,59 @@
  1 +/* This is header file for working with DD time */
  2 +/* V.4.1 */
  3 +/* name: DD_time.h
  4 + * Author: Andrey Fredorov
  5 + * Institution: IKI RAN
  6 + * Date: 21-Feb-1995
  7 + * Last update Sept 05, 2011
  8 + * Sept 05, 2011: V.3.2 SetIntNew => arg TimeKind => to work with 1970-1973 : BR
  9 + */
  10 +
  11 +#define TIMELENGTH 17
  12 +
  13 +typedef char dd_time_t[TIMELENGTH]; /* YYYYDDDHHMMSSMLS */
  14 +
  15 +/* ---------------- Functions prototypes ----------------------*/
  16 +extern double DD_Time2Double(dd_time_t DD_Time);
  17 +/* Convert string to double and return.
  18 + * Return negative value in case of error string format
  19 + */
  20 +extern char *Double2DD_Time(double Time);
  21 +/* Convert double Time value into string form and return pointer to static string
  22 + * allocated INSIDE the library. Thus the value is renoveted each function call.
  23 + */
  24 +
  25 +/*---------------- Backup compability with V.3.0 and earlier ----------*/
  26 +typedef struct { double times; /* time sec from 1970 */
  27 + int year;
  28 + int day;
  29 + int hour;
  30 + int min;
  31 + int sec;
  32 + int msec;
  33 + } dd_tmstr_t ;
  34 +
  35 +
  36 +extern dd_tmstr_t *ReadTime(char *UT); /* Read time from sring and fill static
  37 + * structure defined IN function.
  38 + * Returns pointer of strusture */
  39 +extern char *WriteTime(dd_tmstr_t *UT); /* Get pointer of time structure
  40 + * and convert it into string
  41 + * Function returns pointer of
  42 + * internal string */
  43 +
  44 +extern void WriteFmtTime(dd_tmstr_t *UT,char *UTstring);
  45 +
  46 +extern void SetDouble(dd_tmstr_t *UT); /* Fill double value of dd_tmstr_t */
  47 +
  48 +typedef enum {DD_TM_UNKNOWN, DD_TM_TIME_INTERVAL, DD_TM_DATE} t_DDTimeKind;
  49 +
  50 +extern void SetInt(dd_tmstr_t *UT); /* Fill int values of dd_tmstr_t */
  51 +extern void SetIntNew(dd_tmstr_t *UT,t_DDTimeKind timeKind);
  52 +
  53 +/*------- Functions for DECODERS ------------------------
  54 + *These functions works with with Gavrilova's UT representation */
  55 +extern dd_tmstr_t *UT2double(unsigned *UT); /* Set standard time
  56 + * structure and return
  57 + * its pointer
  58 + */
  59 +extern unsigned *Double2UT(double Time); /*Converts Double to Gavrilova array */
... ...
src/SERVER/CMakeLists.txt 0 → 100644
  1 +++ a/src/SERVER/CMakeLists.txt
... ... @@ -0,0 +1,26 @@
  1 +
  2 +PROJECT(DDServer)
  3 +
  4 +include_directories(
  5 + ${CMAKE_HOME_DIRECTORY}/src/INCLUDE/
  6 + ${NETCDFINCLUDE_DIR}
  7 +)
  8 +
  9 +#Configuration de l'exécutable
  10 +file(
  11 + GLOB_RECURSE
  12 + source_files
  13 + ./*
  14 +)
  15 +
  16 +ADD_EXECUTABLE (DDServer ${source_files} )
  17 +
  18 +target_link_libraries(
  19 + DDServer
  20 + ${CMAKE_THREAD_LIBS_INIT}
  21 + DDClient
  22 + ${NETCDFLIBRARY}
  23 + ${CRYPT_LIBRARY}
  24 +)
  25 +
  26 +install (TARGETS DDServer DESTINATION bin)
... ...
src/SERVER/DD_Access_sr.c 0 → 100644
  1 +++ a/src/SERVER/DD_Access_sr.c
... ... @@ -0,0 +1,655 @@
  1 +/*
  2 + *-------------------- DD_ACCESS -------------------------------
  3 + *
  4 + * name: DD_Access.c V4.0
  5 + * author: Alexander Grigoriev , Andrei Fedorov
  6 + * Insitution: IKI RAN lab.546 aug@afed.iki.rssi.ru
  7 + * Description: Set of function for access to DD system
  8 + * Last revision: Oct 10, 2002
  9 + * List of revisions:
  10 + * March 1999 V1.0
  11 + * 20 Oct 1999 ; ShowTicket was corrected. V2.0
  12 + * 28 Oct 1999 ; Added LOGINS,ddcheck V3.0
  13 + * Oct 10, 2002 - revised by A. Fedorov V 4.0
  14 + */
  15 +/*#define _XOPEN_SOURCE*/ /* for crypt function */
  16 +
  17 +#define _XOPEN_SOURCE
  18 +#include <unistd.h>
  19 +#include <time.h>
  20 +#include <DD.h>
  21 +#include <netcdf.h>
  22 +#include <DD_comm.h>
  23 +#include <DD_Access.h>
  24 +
  25 +/*=========== Global Variables ===============================*/
  26 + size_t CashStart[2]={0L,0L};
  27 + size_t CashCount[2]={1, MAXHOSTLENGTH};
  28 + size_t CashCountInt[2]={1, 1};
  29 + extern int Verbose;
  30 +
  31 +/*############################################################################*/
  32 +
  33 +/*----------------GETTICKET------------------------------------*/
  34 +
  35 +/* Description: This function find the user data in user_cash.nc
  36 + * If O'k rewrite the line with new time.
  37 + * In case of a new user, remove the first line with
  38 + * older time data then a current time + 4.5 hours.
  39 + *
  40 + Take 3 arguments: UserId,
  41 + IP-address(string,like "193.232.6.60\0")
  42 + DD_user_id(can see in user_info.nc)
  43 +
  44 + Returns 0 if O'k or NOPERMISSION if error
  45 +
  46 + If DD_log_name equal NULL searching for UserId, IP-address
  47 + If DD_log_name nonequal NULL searching for IP-address,DD_log_name*
  48 + *
  49 + */
  50 +
  51 +int GetTicket(int UID, char *HostName, int DD_user_id)
  52 + {
  53 + char *ddbase;
  54 + char refname[PATHLENGTH];
  55 + int TicketID, Comp=1, Flag,OldFlag=0, Find=0, dltt;
  56 + int CurIDID,HostID,TimeID, DD_id_ID; /* Variable IDs in the NC ticket file */
  57 + int TimeFinish;
  58 + int Clock;
  59 + char CurHostName[MAXHOSTLENGTH];
  60 + int CurID, CurTime,DD_id, MemTime,OldestStart; /* Values to read and write to ticket file */
  61 + size_t CurCashStart[2]={0,0};
  62 + size_t HostCount[2] = {1,MAXHOSTLENGTH};
  63 + int ACCESS = NOPERMISSION;
  64 + int status; /* Return value of any NC routine */
  65 +
  66 + if(Verbose) fprintf(stderr,"GetTicket: UID = %d, HostName <%s>, DD_user_id = <%d> is going to work\n",UID, HostName,DD_user_id);
  67 +
  68 +/*------------- OpenUserNC ---------------------------------*/
  69 +
  70 + if((ddbase = getenv("DDBASE")) == NULL)
  71 + {
  72 + if(Verbose) fprintf(stderr,"GETTICKET: No DDBASE environment.\n");
  73 + return(ENVIRERROR);
  74 + }
  75 + strcpy(refname,ddbase);
  76 + strcat(refname,TICKET_PATH);
  77 + if(Verbose) fprintf(stderr,"GETTICKET: TICKET_PATH is %s \n",refname);
  78 +
  79 + if((status = nc_open(refname, NC_WRITE,&TicketID)) != NC_NOERR)
  80 + {
  81 + if(Verbose) fprintf(stderr,"GETTICKET: %s\n", nc_strerror(status));
  82 + return(NOUSERSFILE);
  83 + }
  84 +
  85 +/*------------------ Working with -------------------------------*/
  86 +
  87 + status = nc_inq_varid(TicketID,"id",&CurIDID);
  88 + status = nc_inq_varid(TicketID,"host",&HostID);
  89 + status = nc_inq_varid(TicketID,"time",&TimeID);
  90 + status = nc_inq_varid(TicketID,"DD_id",&DD_id_ID);
  91 + status = nc_sync(TicketID);
  92 +
  93 + Clock = (int)time(NULL);
  94 +
  95 + // TimeFinish = Clock+16200; // 4.5 hours
  96 + TimeFinish = Clock+172800; // 48 hours
  97 + HostName[strlen(HostName)] = '\0';
  98 + CashStart[0]=0;
  99 + OldestStart = 0;
  100 +
  101 + do
  102 + {
  103 + status = nc_get_var1_int(TicketID, CurIDID, CashStart,&CurID);
  104 + nc_get_var1_int(TicketID, DD_id_ID, CashStart,&DD_id);
  105 + nc_get_vara_text(TicketID, HostID,CashStart,HostCount,CurHostName);
  106 + nc_get_var1_int(TicketID, TimeID,CashStart,&CurTime);
  107 +
  108 + if(CashStart[0] == 0) MemTime=CurTime;
  109 +
  110 + Comp=strcmp(CurHostName,HostName);
  111 +
  112 + if((CurID == UID)&&(Comp == 0)&&(DD_id == DD_user_id))
  113 + {
  114 + CurCashStart[0]=CashStart[0];
  115 + Find = 1;
  116 + }
  117 + dltt = (CurTime - MemTime);
  118 +
  119 + if((dltt < 0) && (CurHostName[0] != '\0'))
  120 + {
  121 + OldestStart=CashStart[0];
  122 + MemTime = CurTime;
  123 + }
  124 +
  125 + CashStart[0]++;
  126 + }
  127 + while((Find != 1) && (CurHostName[0] != '\0') && (CashStart[0] < USERCASHLEN));
  128 +
  129 + if(Verbose) fprintf(stderr,"FINISH TIME : %ld\n",TimeFinish);
  130 +
  131 + CashStart[0]--;
  132 +
  133 + if(MemTime < Clock) {
  134 + OldFlag = 1;
  135 + }
  136 + if(Find == 1)
  137 + {
  138 + nc_put_var1_int(TicketID,TimeID,CurCashStart,&TimeFinish);
  139 + if(Verbose) fprintf(stderr,"User: ID = %d, DD_id = %d, HostName <%s> continue work.\n ",UID,DD_user_id,HostName);
  140 + ACCESS = 0;
  141 + }
  142 + else
  143 + if(OldFlag == 1)
  144 + {
  145 + CashStart[0]=OldestStart;
  146 +
  147 + nc_put_var1_int(TicketID,CurIDID, CashStart,&UID);
  148 + nc_put_var1_int(TicketID,DD_id_ID, CashStart,&DD_user_id);
  149 + nc_put_vara_text(TicketID,HostID,CashStart,HostCount,HostName);
  150 + nc_put_var1_int(TicketID,TimeID,CashStart,&TimeFinish);
  151 + if(Verbose) fprintf(stderr,"User: ID = %d, DD_id = %d, \n HostName <%s> started work.\n ",UID,DD_user_id,HostName);
  152 + ACCESS = 0;
  153 + }
  154 + else
  155 + if((CashStart[0]<USERCASHLEN) && (CurHostName[0] == '\0'))
  156 + {
  157 + nc_put_var1_int(TicketID,CurIDID, CashStart,&UID);
  158 + nc_put_var1_int(TicketID,DD_id_ID, CashStart,&DD_user_id);
  159 + nc_put_vara_text(TicketID,HostID,CashStart,HostCount,HostName);
  160 + nc_put_var1_int(TicketID,TimeID,CashStart,&TimeFinish);
  161 + if(Verbose) fprintf(stderr,"User: ID = %d, DD_id = %d, \n HostName <%s> started work.\n ",UID,DD_user_id,HostName);
  162 + ACCESS = 0;
  163 + }
  164 + else {fprintf(stderr,"Too many members!\n");ACCESS = NOPERMISSION;}
  165 +
  166 +
  167 + /*if((CurID == UID)&&(Comp == 0)) fprintf(stderr,"Exists...\n");*/
  168 +
  169 + nc_sync(TicketID);
  170 + nc_close(TicketID);
  171 +
  172 +return((int)ACCESS);
  173 +}
  174 +
  175 +/*############################################################################*/
  176 +
  177 +/*-------------------CHECK TICKET-----------------------*/
  178 +
  179 +/* Description: This function check the user for accessability
  180 + * in user_info.nc file. Returns DD_id if O'k.
  181 + * Returns NOPERMISSION in case of unaccessability, neagative value (DD_access.h)
  182 + * in case of error.
  183 + */
  184 +
  185 +int CheckTicket(char *NameUsr, char *Ticket)
  186 +{
  187 + int i=0;
  188 + int DD_id;
  189 + int Right = NOPERMISSION;
  190 + char salt[2],newkey[USRLENGTH];
  191 +
  192 + int UsrRefID; /* ID of reference file which consists description of all users */
  193 + char *ddbase;
  194 + char refname[PATHLENGTH];
  195 +
  196 + int UserDimID,UserLenDimID,PasLenDimID; /* ID of dimensions in NC file */
  197 + int MemID, PasID; /* ID of variables in NC file */
  198 + size_t MaxRecords, UserLength, PasswdLength; /* Dimensions */
  199 + size_t start[2] = {0,0}, UserCount[2] = {1,0}, PasswdCount[2] = {1,0};
  200 + static char UserDimName[] = "user", UserLenDimName[] = "UserLength"; /* Dimensions names */
  201 + static char PasLenDimName[] = "PasswdLength"; /* Dimensions names */
  202 + static char MemName[] = "member", PasName[] = "passwd"; /* Variable Names */
  203 + char PasChar[USRLENGTH],MemChar[USRLENGTH];
  204 + int status; /* Return of any NC call */
  205 +
  206 +/*------------- Open User reference NC ---------------------------------*/
  207 + if((ddbase = getenv("DDBASE")) == NULL)
  208 + {
  209 + if(Verbose) fprintf(stderr,"CHECKTICKET: No DDBASE environment.\n");
  210 + return(ENVIRERROR);
  211 + }
  212 + strcpy(refname,ddbase);
  213 + strcat(refname,USERREFNAME);
  214 + if(Verbose) fprintf(stderr," CHECHTICKET: PATH is %s \n",refname);
  215 +// sleep(40);
  216 + if((status = nc_open(refname, NC_WRITE,&UsrRefID)) != NC_NOERR)
  217 + {
  218 + if(Verbose) fprintf(stderr,"CHECHTICKET: %s\n", nc_strerror(status));
  219 + return(NOUSERSFILE);
  220 + }
  221 +
  222 +/*------------------ Define all dimensions -------------------------------*/
  223 +
  224 + status = nc_inq_dimid(UsrRefID,UserDimName,&UserDimID);
  225 + status = nc_inq_dimlen(UsrRefID, UserDimID, &MaxRecords);
  226 + status = nc_inq_dimid(UsrRefID,UserLenDimName,&UserLenDimID);
  227 + status = nc_inq_dimlen(UsrRefID, UserLenDimID, &UserLength);
  228 + UserCount[1] = UserLength;
  229 + status = nc_inq_dimid(UsrRefID,PasLenDimName,&PasLenDimID);
  230 + status = nc_inq_dimlen(UsrRefID, PasLenDimID, &PasswdLength);
  231 + PasswdCount[1] = PasswdLength;
  232 +
  233 +/*fprintf(stderr,"CheckTicket:Rec: %d %d %d\n",MaxRecords,UserLength,PasswdLength);*/
  234 +
  235 +/*------------------ Define all variables ID -------------------------------*/
  236 + status = nc_inq_varid(UsrRefID, MemName,&MemID);
  237 + status = nc_inq_varid(UsrRefID, PasName,&PasID);
  238 +
  239 +
  240 + for(i=0;i<MaxRecords;i++)
  241 + {
  242 + start[0]=(size_t)i;
  243 + nc_get_vara_text(UsrRefID, MemID, start,UserCount, MemChar);
  244 +
  245 + if(strcmp(MemChar,NameUsr)==0)
  246 + {
  247 + nc_get_vara_text(UsrRefID, PasID, start, PasswdCount, PasChar);
  248 +
  249 + /*fprintf(stderr,"Your dd_id is %u\n",i);*/
  250 + DD_id = i;
  251 + Ticket[strlen(Ticket)]='\0';
  252 + NameUsr[strlen(NameUsr)]='\0';
  253 + newkey[PasswdLength-1]='\0';
  254 +
  255 + strncpy(salt,PasChar,2);
  256 +
  257 + strcpy(newkey,(char *)crypt(Ticket,salt));
  258 +
  259 + if(strcmp(PasChar,newkey) == 0)
  260 + {
  261 + if(Verbose) fprintf(stderr,"User %s is logged in\n",NameUsr);
  262 + Right = DD_id;
  263 + }
  264 + else
  265 + {
  266 + if(Verbose) fprintf(stderr,"for user %s permission denied.\n",NameUsr);
  267 + Right = NOPERMISSION;
  268 + }
  269 + }
  270 + }
  271 + nc_close(UsrRefID);
  272 +return((int)Right);
  273 +}
  274 +
  275 +/*
  276 + *-------------------- SHOW TICKET -------------------------------*/
  277 +/*
  278 + * Description: Library function. Used by DD_Server. It reads the
  279 + * content of user_ticket.nc file. Compares the information
  280 + * with your {id,hostname,DD_id,time}.
  281 + * If id and hostname(IP_address) and DD_id exists in table of registarated
  282 + * users, check the working time. If one has any time for work, returns 0,
  283 + * or a negative value "NOPERMISSION".
  284 + * It IS DD_Check !
  285 + */
  286 +
  287 +int ShowTicket(int userID, char *hostname, char *DD_name)
  288 + {
  289 + char *ddbase;
  290 + char refname[PATHLENGTH];
  291 + int TicketID; /* Ticket file ID */
  292 + int Comp=1, Time_is=0, Find=0;
  293 + int CurIDID,HostID,TimeID, DD_id_ID; /* NC variables ID */
  294 + time_t Clock;
  295 + char CurHostName[MAXHOSTLENGTH];
  296 + int CurID, CurTime, RefTime, DD_id; /* Variables */
  297 + size_t CurCashStart[2]={0,0};
  298 + size_t HostCount[2] = {1,MAXHOSTLENGTH};
  299 + int ServerReply = NOPERMISSION;
  300 + int DD_user_id = -1;
  301 + int status; /* Return of any NC call */
  302 +
  303 + hostname[strlen(hostname)]='\0';
  304 + DD_name[strlen(DD_name)]='\0';
  305 + if((strcmp(DD_name,NONAME))!=0) DD_user_id = CheckID(DD_name);
  306 +
  307 +/*------------- OpenUserNC ---------------------------------*/
  308 +
  309 + if((ddbase = getenv("DDBASE")) == NULL)
  310 + {
  311 + if(Verbose) fprintf(stderr,"SHOWTICKET: No DDBASE environment.\n");
  312 + return(ENVIRERROR);
  313 + }
  314 + strcpy(refname,ddbase);
  315 + strcat(refname,TICKET_PATH);
  316 + if(Verbose) fprintf(stderr,"SHOWTICKET: TICKET_PATH is %s \n",refname);
  317 +
  318 + if((status = nc_open(refname, NC_WRITE,&TicketID)) != NC_NOERR)
  319 + {
  320 + if(Verbose) fprintf(stderr,"SHOWTICKET: %s\n", nc_strerror(status));
  321 + return(NOUSERSFILE);
  322 + }
  323 +
  324 +/*------------------Info about source.file-------------------------------*/
  325 + status = nc_inq_varid(TicketID,"id",&CurIDID);
  326 + status = nc_inq_varid(TicketID,"host",&HostID);
  327 + status = nc_inq_varid(TicketID,"time",&TimeID);
  328 + status = nc_inq_varid(TicketID,"DD_id",&DD_id_ID);
  329 +
  330 + nc_sync(TicketID);
  331 + CashStart[0]=0;
  332 +
  333 + do
  334 + {
  335 + status = nc_get_var1_int(TicketID, CurIDID, CashStart,&CurID);
  336 + status = nc_get_var1_int(TicketID, DD_id_ID, CashStart,&DD_id);
  337 + status = nc_get_vara_text(TicketID, HostID,CashStart,HostCount,CurHostName);
  338 + status = nc_get_var1_int(TicketID, TimeID,CashStart,&CurTime);
  339 +
  340 + Comp=strcmp(CurHostName,hostname);
  341 + if((strcmp(DD_name,NONAME)) == 0) DD_user_id = DD_id;
  342 +
  343 + if((CurID == userID) && (Comp == 0) && (DD_id == DD_user_id))
  344 + {
  345 + RefTime = CurTime;
  346 + CurCashStart[0]=CashStart[0];
  347 + Find = 1;
  348 + }
  349 +
  350 + CashStart[0]++;
  351 + }
  352 + while((CurHostName[0] != '\0') && (CashStart[0] < USERCASHLEN));
  353 +
  354 + if(Find == 1)
  355 + {
  356 + CashStart[0]=CurCashStart[0];
  357 + status = nc_get_var1_int(TicketID, CurIDID, CashStart,&CurID);
  358 + status = nc_get_var1_int(TicketID, DD_id_ID, CashStart,&DD_id);
  359 + status = nc_get_vara_text(TicketID, HostID,CashStart,HostCount,CurHostName);
  360 + status = nc_get_var1_int(TicketID, TimeID,CashStart,&CurTime);
  361 + if((strcmp(DD_name,NONAME))==0) DD_user_id = (int)DD_id;
  362 + }
  363 + CashStart[0]--;
  364 +
  365 + Clock=(int)time(NULL);
  366 +
  367 + if(CurTime > Clock) Time_is = 1;
  368 +
  369 + if((Find == 1) && (Time_is == 1))
  370 + {
  371 + fprintf(stderr,"User: ID = %d, DD_id = %d, host %s, timework=%d, is connected. \n",CurID,DD_user_id,hostname,Time_is);
  372 + ServerReply = 0;
  373 + }
  374 + else {
  375 +
  376 + fprintf(stderr,"User: ID = %d, DD_id = %d, host %s, timework=%d, Permission denied!. \n",CurID,DD_user_id,hostname,Time_is);
  377 + ServerReply=NOPERMISSION;
  378 + }
  379 +
  380 + nc_sync(TicketID);
  381 + nc_close(TicketID);
  382 + return ServerReply;
  383 +}
  384 +
  385 +/*
  386 + *------------------------ SETUSER -------------------------------*/
  387 +/*
  388 + * Description: Library function for client-server using.
  389 + * Send ID, HostName to server.
  390 + * Compares the information with your {id,hostname}.
  391 + * Returns 1 if O'k, or a negative value in case
  392 + * of "NOPERMISSION".
  393 + *
  394 + */
  395 +int SetUser(int UserID, char *HostName, char *LogName)
  396 +{
  397 +
  398 + int SocketID = -1; /* Global socket id for this communication session */
  399 + static DD_data_t dd = {DD_CHAR,0,NULL,0,NULL};
  400 + static caddr_t buf = NULL;
  401 + static XDR xdrs;
  402 + int cc,i, hostlen, ticketlen, userlen;
  403 + int op = SHOWTICKETREQ;
  404 + int SHOW_ACCESS;
  405 +
  406 + SHOW_ACCESS = NOPERMISSION;
  407 + /* fprintf(stderr,"after CLIENT int SetUser: SocketID = %d\n",SocketID);
  408 + fprintf(stderr,"after CLIENT int SetUser: User = %d Host %s\n",UserID,HostName);
  409 + */
  410 +
  411 +/*------------------CONNECTION to SERVER---------------------------*/
  412 +/*
  413 + * If no connection, connect to server, try to order data set and return
  414 + * ID if OK or ErrorNumber if not
  415 + */
  416 +
  417 +
  418 + /* fprintf(stderr,"Try to connect Server\n");*/
  419 +/* If there is no connection, try to get it */
  420 + if(SocketID < 0)
  421 + if((SocketID = GetSocket()) < 0) return(NOCONNECTION);
  422 + /* fprintf(stderr,"Server3 connected\n");*/
  423 +
  424 +
  425 +/*---------------------REQUEST TO SERVER-----------------------------*/
  426 +
  427 +/* Check the HostName length */
  428 + if(strlen(HostName) > MAXHOSTLENGTH) hostlen = MAXHOSTLENGTH;
  429 + else hostlen = strlen(HostName);
  430 + if(strlen(LogName) > USRLENGTH) userlen = USRLENGTH;
  431 + else userlen = strlen(LogName);
  432 +
  433 +/* Allocation memory and stream */
  434 + buf = (caddr_t)malloc(REQUESTLENGTH);
  435 + xdrmem_create(&xdrs, buf, REQUESTLENGTH, XDR_ENCODE);
  436 +
  437 +/* Encoding the request */
  438 + xdr_int(&xdrs,&op);
  439 + xdr_int(&xdrs,&UserID);
  440 + xdr_string(&xdrs, &HostName, hostlen);
  441 + xdr_string(&xdrs, &LogName, userlen);
  442 +/* fprintf(stderr,"UserID, HostName just more : %d %s\n",UserID,HostName);*/
  443 +/* Send request */
  444 + if((cc = send(SocketID,buf,REQUESTLENGTH,0)) < 0)
  445 + {
  446 + perror("DD_GetTicket:");
  447 + free(buf);
  448 + xdr_destroy(&xdrs);
  449 + return(REQSENDERR);
  450 + }
  451 + free(buf);
  452 + xdr_destroy(&xdrs);
  453 +
  454 +/* Get reply header */
  455 +
  456 + buf = (caddr_t)malloc(REPLYLENGTH);
  457 + i =0;
  458 + while(((cc = recv(SocketID,buf,REPLYLENGTH,0)) < 0) && (i < TRY)) i++;
  459 + if(cc < 0)
  460 + {
  461 + perror("DD_SetUser:");
  462 + free(buf);
  463 + return(REPLYRECERR);
  464 + }
  465 +
  466 + xdrmem_create(&xdrs, buf, REPLYLENGTH, XDR_DECODE);
  467 + xdr_int(&xdrs,&SHOW_ACCESS);
  468 +
  469 + free(buf);
  470 + xdr_destroy(&xdrs);
  471 + shutdown(SocketID,2);
  472 + close(SocketID);
  473 + /*SocketID = -1;*/
  474 +/* fprintf(stderr,"SetUser,End; UserID, HostName just more : %d %s\n",UserID,HostName);
  475 + fprintf(stderr,"SHOW_ACCES %d \n",SHOW_ACCESS);
  476 +*/
  477 + if(Verbose) fprintf(stderr,"SetUser: ACCES = %d \n",SHOW_ACCESS);
  478 +
  479 +return((int)SHOW_ACCESS);
  480 +}
  481 +
  482 +/*############################################################################*/
  483 +
  484 +/*-------------------CHECK ID-----------------------*/
  485 +
  486 +/* Description: This function check the user name in user_info.nc file.
  487 + * Returns DD_id if exists.
  488 + * Returns OK, or NOPERMISSION, or an ERROR
  489 + */
  490 +
  491 +int CheckID(char *NameUsr)
  492 +{
  493 + int i=0,Find=0;
  494 + int DD_id = NOPERMISSION;
  495 +
  496 + int UsrRefID; /* ID of NC file */
  497 + char *ddbase;
  498 + char refname[PATHLENGTH];
  499 + int UserDimID,UserLenDimID; /* Dimennsions ID */
  500 + int MemID; /* Variable ID */
  501 + size_t MaxRecords, UserLength; /* Dimensions */
  502 + size_t start[2]= {0,0};
  503 + size_t UserCount[2] = {1,0};
  504 + char UserDimName[] = "user", UserLenDimName[] = "UserLength"; /* Dimensions names */
  505 + char MemName[] = "member"; /* Variable name */
  506 + char MemChar[USRLENGTH];
  507 + int status;
  508 +
  509 +/*------------- Open User Reference file ---------------------------------*/
  510 + if((ddbase = getenv("DDBASE")) == NULL)
  511 + {
  512 + if(Verbose) fprintf(stderr,"CHECKID: No DDBASE environment.\n");
  513 + return(ENVIRERROR);
  514 + }
  515 + strcpy(refname,ddbase);
  516 + strcat(refname,USERREFNAME);
  517 + if(Verbose) fprintf(stderr," CHECKID: PATH is %s \n",refname);
  518 +
  519 + if((status = nc_open(refname, NC_WRITE,&UsrRefID)) != NC_NOERR)
  520 + {
  521 + if(Verbose) fprintf(stderr,"CHECKID: %s\n", nc_strerror(status));
  522 + return(NOUSERSFILE);
  523 + }
  524 +
  525 +/*------------------ Define all dimensions -------------------------------*/
  526 +
  527 + status = nc_inq_dimid(UsrRefID,UserDimName,&UserDimID);
  528 + status = nc_inq_dimlen(UsrRefID, UserDimID, &MaxRecords);
  529 + status = nc_inq_dimid(UsrRefID,UserLenDimName,&UserLenDimID);
  530 + status = nc_inq_dimlen(UsrRefID, UserLenDimID, &UserLength);
  531 + UserCount[1] = UserLength;
  532 +
  533 +/*fprintf(stderr,"CheckTicket:Rec: %d %d %d\n",MaxRecords,UserLength,PasswdLength);*/
  534 +
  535 +/*------------------ Define all variables ID -------------------------------*/
  536 + status = nc_inq_varid(UsrRefID, MemName,&MemID);
  537 +
  538 + while((i<MaxRecords) && (Find != 1))
  539 + {
  540 + start[0]=i;
  541 + status = nc_get_vara_text(UsrRefID, MemID, start,UserCount,MemChar);
  542 + if(strcmp(MemChar,NameUsr)==0) {DD_id = i;Find=1;}
  543 + i++;
  544 + }
  545 + nc_close(UsrRefID);
  546 + return(DD_id);
  547 +}
  548 +
  549 +/*----------------Put into LOG file------------------------------------*/
  550 +
  551 +/* Description: This function requires ID of local host, IP-address of
  552 +* local host and Login Name.
  553 +*
  554 +*/
  555 +
  556 +void Put2Log(int UID, char *Host, char *LogName, int error)
  557 + {
  558 + FILE *log;
  559 + time_t Clock;
  560 + char *ddbase;
  561 + char refname[PATHLENGTH], right[]=" normal \0",noright[]="no permission\0";
  562 +
  563 + if((ddbase = getenv("DDBASE")) == NULL)
  564 + {
  565 + fprintf(stderr,"No DDBASE info. Check your profile... \n");
  566 + return;
  567 + }
  568 + strcpy(refname,ddbase);
  569 + strcat(refname,LOGFILE);
  570 + if(Verbose) fprintf(stderr,"LOG file: %s \n",refname);
  571 + if((log = fopen(refname, "a")) == NULL)
  572 + {
  573 + fprintf(stderr,"Error in opening log file. \n");
  574 + return;
  575 + }
  576 +
  577 + Clock=time(NULL);
  578 +
  579 + if(error>=0)
  580 + fprintf(log,"%s\t%s\t%u %s\t%s",Host,LogName,UID,right,ctime(&Clock));
  581 + else fprintf(log,"%s\t%s\t%u %s\t%s",Host,LogName,UID,noright,ctime(&Clock));
  582 +
  583 + fclose(log);
  584 +
  585 + return;
  586 + }
  587 +
  588 +/*---------------------LOGINS----------------------------------*/
  589 +
  590 +/* Description: This function uses by ddcheck */
  591 +/* Compare two passwords */
  592 +
  593 +int LOGINS(char *password)
  594 +{
  595 + char salt[3],newkey[13];
  596 + char pas[80];
  597 + char PName[]="Administrator password: ";
  598 + int ACCESS_ = 0;
  599 +
  600 +/*--------------Password----------------------------*/
  601 +
  602 + strncpy(salt,password,2);
  603 + salt[2]='\0';
  604 + strcpy(pas,getpass(PName));
  605 + pas[strlen(pas)] = '\0';
  606 + strcpy(newkey,(char *)crypt(pas,salt));
  607 + newkey[strlen(newkey)] = '\0';
  608 + if(strcmp(newkey, password) == 0) ACCESS_=1;
  609 +
  610 + return ACCESS_;
  611 +}
  612 +
  613 +/*---------------------DDCHECK----------------------------------*/
  614 +
  615 +/* Description: This function check user for dd administrator access to DD_System
  616 +* Require only dd password from you.
  617 +* Returns 0 if o'k or -1 in case of unaccessability.
  618 +*
  619 +*/
  620 +
  621 +int ddcheck()
  622 +{
  623 + int FL=1,coun,i;
  624 + char lines[256],ref[40];
  625 + FILE *files;
  626 +
  627 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  628 + files=fopen("/etc/passwd","r");
  629 + while(FL != 0)
  630 + {
  631 + if(fgets(lines, 255, files) != NULL)
  632 + {
  633 + coun=(strlen(lines)-strlen(strchr(lines,':')));
  634 + strncpy(ref,lines,coun);
  635 + ref[(strlen(lines)-strlen(strchr(lines,':')))]='\0';
  636 + if(strcmp(ref,"dd") == 0)
  637 + {
  638 + coun=(strlen(&(lines[0])+3)-strlen(strchr(&(lines[0])+3,':')));
  639 + strncpy(ref,&lines[0]+3,coun);
  640 + ref[coun]='\0';
  641 + i=LOGINS(ref);
  642 + }
  643 +
  644 + }
  645 + else FL=0;
  646 + }
  647 + fclose(files);
  648 + if(i == 0) return(-1);
  649 + return(0);
  650 +}
  651 +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  652 +
  653 +
  654 +
  655 +
... ...
src/SERVER/DD_GetData.c 0 → 100755
  1 +++ a/src/SERVER/DD_GetData.c
... ... @@ -0,0 +1,1415 @@
  1 +/*=====================================================================
  2 + * DD SYSTEM base package
  3 + * DD_Server library
  4 + * DD_GetData.c
  5 + * V. 6.1
  6 + * author: Andrey Fedorov
  7 + *
  8 + * Last revision:
  9 + * May 19 1997: Version 1.0
  10 + * 25 February 1999 by A.Grigoriev
  11 + * DD_GetData was updated. V.2.0
  12 + * Methods of search in SetTime are changed.
  13 + * April 12, 2002: NETCDF lib is changed V.3.0
  14 + * Oct 10, 2002 Communication prorocol is changed. V 4.0
  15 + * Oct 24, 2002 New calculation of thremaximum record size V. 4.1
  16 + * work with NC files is now in file ncfileop.c
  17 + * May 7, 2003 : V 4.2 Cash work improoved (ncfileop.c also)
  18 + * Jan 6, 2004: V 4.3 Error in ID closing is fixed
  19 + * Jan 21, 2004: V.4.4 Error in free memory fixed,
  20 + * Server can path several new files, and then return
  21 + * Aug 12, 2004: V.4.5 New verbatim in the CLOSEID
  22 + * Nov 18, 2004: V.4.6 Accomodation of new ncfileop.c
  23 + * Mar 15, 2007 V.4.7 Fixed cash bag
  24 + * Jul 10, 2007 V.5.0 According to Server protocol 4.5.1
  25 + * If "times" has "NODATA" string as name of the file, return "NOTIME"
  26 + * New format of VI name (see DDGenProt.lyx)
  27 + * Aug 02, 2007 V.5.1 Add WAITEXTCALL flag and LOCK file to GetData routines
  28 + * Also global time limits
  29 + * Sep 20, 2007 V.5.2 Refrech time limits after database update, database update after Get_Data call
  30 + * Sep 23, 2007 V.5.3 Fedorov, New interface for SetTime()
  31 + * Sep 24, 2007 V.5.4 Fedorov, Get_Data return is changed
  32 + * Sep 25, 2007 V.5.5 Fedorov, Variable minimal gap
  33 + * Feb 22, 2008, V.5.6 SetTime bug corrected -> nc_get,,,(...StartID...) not VarL->StartID !!!!
  34 + * Mar 06, 2008, V.5.7 SetTime bug corrected ->
  35 + * May 03, 2008, V.5.8 GlobalTime limits
  36 + * May 06, 2008 V.5.9 Fedorov, Max Records number processing
  37 + * May 15, 2008 V.5.10 Fedorov, NoData interval processing. Just go to the next correct data interval.
  38 + * May 19, 2008 V.5.11 Fedorov, One record data interval. Time is interpreted as scalar
  39 + * May 21, 2008 V.5.12 Fedorov, No data processing
  40 + * Apr 11, 2009 V.5.13 Fedorov, Out of global limits
  41 + * Apr 13, 2009 V.5.20 Fedorov, Reset of the pointer is in a spectal function
  42 + * Apr 13, 2009 V.5.21 Fedorov, Set time between the last record and Stop time
  43 + * Dec 8, 2012 V.6.0 Fedorov, New call to get the data structure, New multiparam call
  44 + * Jan 11, 2013 V.6.1 Knizhnikova, Fedorov, SlobalStart check, If there is NOVAR, set the corresponding data constants to send the corresponding packet.
  45 + *=====================================================================*/
  46 +#include <netcdf.h>
  47 +#include "DD.h"
  48 +#include "DD_comm.h"
  49 +
  50 +/*------------------ GLOBAL VARIABLES --------------------------*/
  51 +
  52 +DD_Var_t **DD_Var ; /* Common for entire server session , all files */
  53 +size_t MaxIDNumber; /* The size of DD_Var array. Defined when new DD_Server session starts*/
  54 +
  55 +extern int Verbose;
  56 +extern LocalOrigSync(DD_Var_t *Local, DD_Var_t *Orig);
  57 +
  58 +/*#################################################################*/
  59 +/*----------------------- OpenInstr -------------------------------*/
  60 +/*#################################################################*/
  61 +/*
  62 + * Open Virtual instrument by VInstrName and return ID.
  63 + * Make entry point of DD_Var table
  64 + * Fill General attributes fron the INFO file
  65 + */
  66 +int OpenInstr(char *VInstrName)
  67 +{
  68 + char refname[PATHLENGTH]; /* full name of the reference file */
  69 + char *ddbase; /* Environment variable DDBASE (path to the DDBASE ROOT)*/
  70 + char RInstrName[MAXSETLENGTH]; /* Requested virtual instrument name */
  71 + int id; /* ID of open Virtual Instrument */
  72 + int refID,nameID; /* ID of reference file and Var in */
  73 + static size_t RefStart[2] = {0,0};
  74 + static size_t RefCount[2] = {4,PATHLENGTH};
  75 + static char RefVar[4][PATHLENGTH];
  76 + int len, status;
  77 + char *VirInstrP; //Pointer to some part of virtual instrument
  78 + unsigned UT[7]; // Buffer array to decode global time
  79 + dd_tmstr_t *GTimeP; // Buffer structure to decode global time
  80 +
  81 + /** sleep(60); **/
  82 +
  83 + if(Verbose)
  84 + {
  85 + fprintf(stderr,"OpenInstr(%s): begin\n",VInstrName);
  86 + }
  87 +/* Converting original name to the name in database */
  88 + strcpy(RInstrName,VInstrName);
  89 + VirInstrP = (char *)RInstrName;
  90 + while((VirInstrP = strchr(VirInstrP,':')) != NULL) *VirInstrP = '_';
  91 +
  92 +/* Is this name in DD_Var structure ? */
  93 + for(id = 0; id < MaxIDNumber; id++)
  94 + {
  95 + if(DD_Var[id] != NULL)
  96 + if(strcmp(RInstrName, DD_Var[id]->InstrName) == 0)
  97 + {
  98 + if(Verbose) fprintf(stderr,"OpenInstr(%s): VI is already open with ID = %d\n",VInstrName,id);
  99 + return(id);
  100 + }
  101 + }
  102 + if(Verbose) fprintf(stderr,"OpenInstr(%s): No such VI in DD_Var array. Create New Entry.\n",VInstrName);
  103 +
  104 +/* Is the empty space in DD_Var table */
  105 + id =0;
  106 + while((DD_Var[id] != NULL) && (id < MaxIDNumber)) id++;
  107 + if(id >= MaxIDNumber)
  108 + {
  109 + if(Verbose) fprintf(stderr,"OpenInstr(%s): No Room in DD_Var table\n",VInstrName);
  110 + return(TOOMANYREQ); /* No room */
  111 + }
  112 +/**
  113 + if(Verbose) fprintf(stderr,"OpenInstr(%s): There is empty plase at %d\n",VInstrName,id);
  114 +**/
  115 +/* Open reference NC file */
  116 + if((ddbase = getenv("DDBASE")) == NULL) return(NOREFFILE);
  117 + strcpy(refname,ddbase);
  118 + strcat(refname,REFNAME);
  119 +
  120 + status = nc_open(refname, NC_NOWRITE|NC_SHARE,&refID);
  121 + if(status != NC_NOERR)
  122 + {
  123 + if(Verbose) fprintf(stderr,"OpentInstr(%s): open file %s, message: %s\n",VInstrName,refname,nc_strerror(status));
  124 + return(NOREFFILE);
  125 + }
  126 +
  127 + status = nc_inq_varid(refID,RInstrName,&nameID);
  128 + if(status != NC_NOERR)
  129 + {
  130 + if(Verbose) fprintf(stderr,"OpentInstr(%s): read %s, message: %s\n",VInstrName,RInstrName, nc_strerror(status));
  131 + return(NOVAR);
  132 + }
  133 +
  134 + status = nc_get_vara_text(refID,nameID,RefStart,RefCount,(char *)RefVar);
  135 + if(status != NC_NOERR)
  136 + {
  137 + if(Verbose) fprintf(stderr,"OpentInstr(%s): %s\n",VInstrName,nc_strerror(status));
  138 + return(NOVAR);
  139 + }
  140 +
  141 + len = strcspn(RefVar[1]," "); RefVar[1][len] = '\0';
  142 + len = strcspn(RefVar[2]," "); RefVar[2][len] = '\0';
  143 + len = strcspn(RefVar[0]," "); RefVar[0][len] = '\0';
  144 + len = strcspn(RefVar[3]," "); RefVar[3][len] = '\0';
  145 + status = nc_close(refID);
  146 +
  147 +/* Create VI holder*/
  148 + DD_Var[id] = (DD_Var_t *)malloc(sizeof(DD_Var_t));
  149 +
  150 +/* Init Values */
  151 + strcpy(DD_Var[id]->InstrName,RInstrName);
  152 + DD_Var[id]->VarData = NULL;
  153 + DD_Var[id]->ParamSize = 0;
  154 + DD_Var[id]->AttrData.Dimensions = NULL;
  155 + DD_Var[id]->AttrData.Variables = NULL;
  156 + DD_Var[id]->ncID = -1;
  157 + DD_Var[id]->Maxnc_rec = 0;
  158 + strcpy(DD_Var[id]->path, RefVar[0]);
  159 +
  160 + /*----- Init control Flags ---------------*/
  161 + DD_Var[id]->LastPacketFlag = OK;
  162 + DD_Var[id]->NewFile = 0;
  163 + DD_Var[id]->NewFileWasOpen = 0;
  164 +/* ----------------------------------------------------------------
  165 + * Open and init "Times" file
  166 + * -----------------------------------------------------------------*/
  167 + DD_Var[id]->VILocked = 0;
  168 + DD_Var[id]->tmID = -1;
  169 + strcpy(DD_Var[id]->TimesFileName,RefVar[1]);
  170 + if((status = UpdateTimeInfo(DD_Var[id])) < 0) return status;
  171 +
  172 +/* ----------------------------------------------------------------
  173 + * Open "Info" file
  174 + * -----------------------------------------------------------------*/
  175 +/* Attention: Constant information file open and close by request in GetAttribute() */
  176 + strcpy(DD_Var[id]->AttrName,RefVar[2]);
  177 + DD_Var[id]->attrID = -1;
  178 + /*
  179 + * Important to make NULL all variables
  180 + */
  181 + DD_Var[id]->AttrData.Dimensions = NULL;
  182 + DD_Var[id]->AttrData.Variables = NULL;
  183 +/**
  184 + if(Verbose) fprintf(stderr,"OpentInstr(%s): ID = %d, Atributes are resetted\n",VInstrName,id);
  185 +**/
  186 +/* ----------------------------------------------------------------
  187 + * Open "CACHE" file
  188 + * -----------------------------------------------------------------*/
  189 + status = nc_open(RefVar[3],NC_WRITE|NC_SHARE,&(DD_Var[id]->Cash.ID)); /* Cach file */
  190 + if(status != NC_NOERR)
  191 + {
  192 + if(Verbose) fprintf(stderr,"OpentInstr(): open cash %s, message:%s\n",RefVar[3], nc_strerror(status));
  193 + return(CACHERR);
  194 + }
  195 + status = nc_inq_varid(DD_Var[id]->Cash.ID,"name",&(DD_Var[id]->Cash.nameID));
  196 + status = nc_inq_varid(DD_Var[id]->Cash.ID,"time",&(DD_Var[id]->Cash.timeID));
  197 + status = nc_inq_varid(DD_Var[id]->Cash.ID,"fopen",&(DD_Var[id]->Cash.fopenID));
  198 + DD_Var[id]->CurrCushN = -1;
  199 +
  200 + if(status != NC_NOERR)
  201 + {
  202 + if(Verbose) fprintf(stderr,"OpentInstr(): %s\n",nc_strerror(status));
  203 + return(CACHERR);
  204 + }
  205 +/**
  206 + if(Verbose) fprintf(stderr,"OpentInstr(%s): ID = %d, Cache is open\n",VInstrName,id);
  207 +**/
  208 +/* ----------------------------------------------------------------
  209 + * Read Global timing and minimal gap from INFO file
  210 + * -----------------------------------------------------------------*/
  211 + if((status = GetAttribute(id, GLOBSTARTNAME)) < 0) DD_Var[id]->GlobalStart = 0.0;
  212 + else
  213 + {
  214 + sscanf((char *)((DD_Var[id]->AttrData).Variables[0]), ISOTIMEF, &UT[0],&UT[1],&UT[2],&UT[3],&UT[4],&UT[5],&UT[6]);
  215 + SetDouble(GTimeP = UT2double(UT));
  216 + DD_Var[id]->GlobalStart = GTimeP->times;
  217 + }
  218 + if((status = GetAttribute(id, GLOBSTOPNAME)) < 0) DD_Var[id]->GlobalStop = 1.0e11;
  219 + else
  220 + {
  221 + sscanf((char *)((DD_Var[id]->AttrData).Variables[0]), ISOTIMEF, &UT[0],&UT[1],&UT[2],&UT[3],&UT[4],&UT[5],&UT[6]);
  222 + SetDouble(GTimeP = UT2double(UT));
  223 + DD_Var[id]->GlobalStop = GTimeP->times;
  224 + }
  225 + if((status = GetAttribute(id, SAMPLNAME)) < 0) DD_Var[id]->MinGap = MINGAP;
  226 + else
  227 + {
  228 + DD_Var[id]->MinGap = *((double *)((DD_Var[id]->AttrData).Variables[0])) * 5.0;
  229 + if(DD_Var[id]->MinGap < MINGAP) DD_Var[id]->MinGap = MINGAP;
  230 + }
  231 +/* ----------------------------------------------------------------
  232 + * Read External archiving info
  233 + * -----------------------------------------------------------------*/
  234 + DD_Var[id]->ExtCallAllowed = 0;
  235 + if((status = GetAttribute(id, REMARCHNAME)) < 0)
  236 + {
  237 + if(Verbose) fprintf(stderr,"OpentInstr(%s):RemBase:GetAttribute(%s): %s\n", VInstrName,REMARCHNAME, nc_strerror(status));
  238 + DD_Var[id]->ExtCallAllowed = 0;
  239 + DD_Var[id]->BaseName[0] = '\0';
  240 + DD_Var[id]->RemSetID[0] = '\0';
  241 + }
  242 + else
  243 + {
  244 + strcpy(DD_Var[id]->BaseName,(DD_Var[id]->AttrData).Variables[0]);
  245 + if((status = GetAttribute(id, REMINSTNAME)) < 0)
  246 + {
  247 + DD_Var[id]->ExtCallAllowed = 0;
  248 + if(Verbose) fprintf(stderr,"OpentInstr(%s):RemInstr: %s\n",VInstrName,nc_strerror(status));
  249 + }
  250 + else
  251 + {
  252 + DD_Var[id]->ExtCallAllowed = 1;
  253 + strcpy(DD_Var[id]->RemSetID,(DD_Var[id]->AttrData).Variables[0]);
  254 + }
  255 + }
  256 +
  257 + if(Verbose) fprintf(stderr,"OpentInstr(%s): GStart: %f GStop: %f\n",VInstrName,DD_Var[id]->GlobalStart,DD_Var[id]->GlobalStop);
  258 + if(Verbose) fprintf(stderr,"OpentInstr(%s): RemBase: %s RemInstr: %s\n",VInstrName,DD_Var[id]->BaseName,DD_Var[id]->RemSetID);
  259 +
  260 +
  261 + if(Verbose) fprintf(stderr,"DD_GetData:OpentInstr: New ID = %d\n",id);
  262 + return(id);
  263 +}
  264 +/*-------------------------------------------------------------------------------*/
  265 +
  266 +/*###########################################################*/
  267 +/*------------------- CLOSEID -------------------------------*/
  268 +/*###########################################################*/
  269 +int CloseID(int ID)
  270 +/*
  271 + * Closes this ID and return number of IDs remained in use
  272 + */
  273 +
  274 +{
  275 + size_t CashStart[2] = {0L,0L};
  276 + size_t CashCount[2] = {1L,MAXFILENAME};
  277 + int status;
  278 + int i,il, count = 0;
  279 +/* Is this ID */
  280 + if(Verbose) fprintf(stderr,"CloseID(%d)\n",ID);
  281 + if(ID >= MaxIDNumber) return(1); /* Everythig is OK */
  282 + if(DD_Var[ID] != NULL)
  283 + {
  284 +/**
  285 + if(Verbose) fprintf(stderr,"CloseID(%d): ID exists, start termination\n",ID);
  286 +**/
  287 +/*------ Close all netCDF files -----*/
  288 + if(DD_Var[ID]->ncID >= 0)
  289 + {
  290 + status = nc_close(DD_Var[ID]->ncID);
  291 + DD_Var[ID]->ncID = -1;
  292 + /**
  293 + if(Verbose) fprintf(stderr,"CloseID(%d): Data File is closed\n",ID);
  294 + **/
  295 + }
  296 + if(DD_Var[ID]->Cash.ID >= 0)
  297 + {
  298 + status = nc_close(DD_Var[ID]->Cash.ID);
  299 + DD_Var[ID]->Cash.ID = -1;
  300 + if(Verbose)
  301 + {
  302 + if(DD_Var[ID]->CurrCushN >= 0)
  303 + fprintf(stderr,"CloseID(%d): File %s, N %d closed\n",ID, &(DD_Var[ID]->Cash.names[DD_Var[ID]->CurrCushN][0]),DD_Var[ID]->CurrCushN);
  304 + else fprintf(stderr,"CloseID(%d): cash closed\n",ID);
  305 + }
  306 + }
  307 + if(DD_Var[ID]->attrID >= 0)
  308 + {
  309 + status = nc_close(DD_Var[ID]->attrID);
  310 + DD_Var[ID]->attrID = -1;
  311 + /**
  312 + if(Verbose) fprintf(stderr,"CloseID(%d): Info File is closed\n",ID);
  313 + **/
  314 + }
  315 + if(DD_Var[ID]->tmID >= 0)
  316 + {
  317 + status = nc_close(DD_Var[ID]->tmID);
  318 + DD_Var[ID]->tmID = -1;
  319 + /**
  320 + if(Verbose) fprintf(stderr,"CloseID(%d): Times File is closed\n",ID);
  321 + **/
  322 + }
  323 +
  324 +/*==========================================================
  325 + * FREE MEMORY Variable Data
  326 + *==========================================================*/
  327 + for(il = 0; il < DD_Var[ID]->ParamSize; il++)
  328 + {
  329 + for(i = 0; i < DD_Var[ID]->VarData[il].VarNumber; i++)
  330 + {
  331 + if (Verbose) fprintf(stderr,"CloseID(%d): %d, ptr %p\n",ID,i,DD_Var[ID]->VarData[il].Variables[i]);
  332 + free(DD_Var[ID]->VarData[il].Variables[i]);
  333 + DD_Var[ID]->VarData[il].VarNumber = 0;
  334 + }
  335 + free(DD_Var[ID]->VarData[il].Dimensions);
  336 + }
  337 + if(DD_Var[ID]->ParamSize > 0) free(DD_Var[ID]->VarData);
  338 +
  339 +/**
  340 + if(Verbose) fprintf(stderr,"CloseID(%d): Free VarData\n",ID);
  341 +**/
  342 +
  343 + if(DD_Var[ID]->AttrData.Variables != NULL)
  344 + {
  345 +/**
  346 + if (Verbose)
  347 + fprintf(stderr,"CloseID(%d): Free AttrData.Variables[0] = %p\n",ID,DD_Var[ID]->AttrData.Variables[0]);
  348 +**/
  349 + if (DD_Var[ID]->AttrData.Variables[0] != NULL)
  350 + {
  351 + free(DD_Var[ID]->AttrData.Variables[0]);
  352 + DD_Var[ID]->AttrData.Variables[0] = NULL;
  353 + }
  354 + }
  355 +
  356 + free(DD_Var[ID]);
  357 + DD_Var[ID] = NULL;
  358 + if(Verbose) fprintf(stderr,"CloseID(%d): Free DD_Var\n",ID);
  359 + }
  360 +
  361 +/* Count determination */
  362 + for(i = 0; i < MaxIDNumber; i++) if(DD_Var[i] != NULL) count++;
  363 +
  364 + return(count);
  365 +}
  366 +
  367 +/*###########################################################*/
  368 +/*------------------ GETATTRIBUTE ---------------------------*/
  369 +/*###########################################################*/
  370 +int GetAttribute(int ID, char *VarName)
  371 +/*
  372 + * Get information variable by ID and variable
  373 + * name. Fill Variable structure
  374 + */
  375 +
  376 +{
  377 + int VarID; /* ID of requested Variable */
  378 + static size_t DimArray[NC_MAX_DIMS];
  379 + static int IntDimArray[NC_MAX_DIMS];
  380 + static int DimIDArray[NC_MAX_DIMS];
  381 + static size_t start[NC_MAX_DIMS];
  382 + static void *CommonAttrPnt = NULL; /* Pointer to the Atributes for ALL ID's */
  383 + static nc_type type;
  384 + size_t count = 1;
  385 + int i, status;
  386 +
  387 +/* Check the ID */
  388 + if(DD_Var[ID] == NULL) return(NOID);
  389 +
  390 + if(Verbose) fprintf(stderr,"GetAttribute(%d): Name = %s\n",ID,VarName);
  391 +
  392 +/* Free memory for data */
  393 + if(DD_Var[ID]->AttrData.Dimensions == NULL)
  394 + DD_Var[ID]->AttrData.Dimensions = (int *)IntDimArray;
  395 +
  396 + if(DD_Var[ID]->AttrData.Variables == NULL)
  397 + DD_Var[ID]->AttrData.Variables = &CommonAttrPnt; /* Static pointer -> Variables[0] */
  398 + if(DD_Var[ID]->AttrData.Variables[0] != NULL) /* Only one variable exists (no time) */
  399 + {
  400 +/**/
  401 + if (Verbose) fprintf(stderr,"GetAttribute(%d):Free AttrData.Variables[0] = %p\n", ID,DD_Var[ID]->AttrData.Variables[0]);
  402 +/**/
  403 + free(DD_Var[ID]->AttrData.Variables[0]);
  404 + DD_Var[ID]->AttrData.Variables[0] = NULL;
  405 + }
  406 +
  407 +/* Try to open constant information data */
  408 + status = nc_open(DD_Var[ID]->AttrName,NC_NOWRITE,&(DD_Var[ID]->attrID)); /* Constant information */
  409 + if(status!= NC_NOERR)
  410 + {
  411 + if(Verbose) fprintf(stderr,"GetAttribute(%d): %s\n",ID,nc_strerror(status));
  412 + return(NOINFOFILE);
  413 + }
  414 +/* Get ID for queired variable. If not return */
  415 + status = nc_inq_varid(DD_Var[ID]->attrID,VarName,&VarID);
  416 + if(status != NC_NOERR)
  417 + {
  418 + if(Verbose) fprintf(stderr,"GetAttribute(%d): %s\n",ID,nc_strerror(status));
  419 + return(NOVAR);
  420 + }
  421 +
  422 +/* Get invormation about queried variable */
  423 + status = nc_inq_vartype(DD_Var[ID]->attrID,VarID,&type); /* Type of variable */
  424 + status = nc_inq_varndims(DD_Var[ID]->attrID,VarID,&(DD_Var[ID]->AttrData.DimNumber)); /* Number of dimansions */
  425 + status = nc_inq_vardimid(DD_Var[ID]->attrID,VarID,DimIDArray); /* Array of dimensions IDs */
  426 + if(status != NC_NOERR)
  427 + {
  428 + if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status));
  429 + return(NOVAR);
  430 + }
  431 +
  432 + if(DD_Var[ID]->AttrData.DimNumber == 0)
  433 + {
  434 + DD_Var[ID]->AttrData.DimNumber = 1;
  435 + DimArray[0] = 1;
  436 + IntDimArray[0] = 1;
  437 + }
  438 + else
  439 + for(i = 0; i < DD_Var[ID]->AttrData.DimNumber; i++)
  440 + {
  441 + status = nc_inq_dimlen( DD_Var[ID]->attrID,DimIDArray[i],&(DimArray[i])); /* Dimensions values */
  442 + if(status != NC_NOERR)
  443 + {
  444 + if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status));
  445 + return(NOVAR);
  446 + }
  447 + IntDimArray[i] = (int)DimArray[i];
  448 + }
  449 +
  450 +
  451 +/* Define type of variable */
  452 + switch(type)
  453 + {
  454 + case NC_DOUBLE: DD_Var[ID]->AttrData.type = DD_DOUBLE; break;
  455 + case NC_CHAR: DD_Var[ID]->AttrData.type = DD_CHAR; break;
  456 + case NC_FLOAT: DD_Var[ID]->AttrData.type = DD_FLOAT; break;
  457 + case NC_SHORT: DD_Var[ID]->AttrData.type = DD_SHORT; break;
  458 + case NC_INT: DD_Var[ID]->AttrData.type = DD_INT;
  459 + }
  460 +
  461 +/* Setting Dimensions attributes to get data */
  462 + for(i = 0; i < DD_Var[ID]->AttrData.DimNumber; i++) count = count * DimArray[i];
  463 +
  464 +/* Alocating memory for data */
  465 + DD_Var[ID]->AttrData.Variables[0] = (void *)malloc(unixlen[DD_Var[ID]->AttrData.type]*count);
  466 +
  467 +/*
  468 + if (Verbose)
  469 + fprintf(stderr,"Malloc DD_Var[%d]->AttrData.Variables[0] = %p\n",ID,DD_Var[ID]->AttrData.Variables[0]);
  470 +*/
  471 +
  472 + switch(type)
  473 + {
  474 + case NC_DOUBLE: status = nc_get_vara_double(DD_Var[ID]->attrID,VarID,start,DimArray,(double *)DD_Var[ID]->AttrData.Variables[0]);
  475 + if (status != NC_NOERR)
  476 + {
  477 + if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status));
  478 + return(NOVAR);
  479 + }
  480 + break;
  481 + case NC_CHAR: status = nc_get_vara_text(DD_Var[ID]->attrID,VarID,start,DimArray,(char *)DD_Var[ID]->AttrData.Variables[0]);
  482 + if (status != NC_NOERR)
  483 + {
  484 + if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status));
  485 + return(NOVAR);
  486 + }
  487 + break;
  488 + case NC_FLOAT: status = nc_get_vara_float(DD_Var[ID]->attrID,VarID,start,DimArray,(float *)DD_Var[ID]->AttrData.Variables[0]);
  489 + if (status != NC_NOERR)
  490 + {
  491 + if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status));
  492 + return(NOVAR);
  493 + }
  494 + break;
  495 + case NC_SHORT: status = nc_get_vara_short(DD_Var[ID]->attrID,VarID,start,DimArray,(short *)DD_Var[ID]->AttrData.Variables[0]);
  496 + if (status != NC_NOERR)
  497 + {
  498 + if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status));
  499 + return(NOVAR);
  500 + }
  501 + break;
  502 + case NC_INT: status = nc_get_vara_long(DD_Var[ID]->attrID,VarID,start,DimArray,(long *)DD_Var[ID]->AttrData.Variables[0]);
  503 + if (status != NC_NOERR)
  504 + {
  505 + if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status));
  506 + return(NOVAR);
  507 + }
  508 + }
  509 + if(DD_Var[ID]->attrID >= 0) nc_close(DD_Var[ID]->attrID);
  510 + DD_Var[ID]->attrID = -1;
  511 + return(1);
  512 +}
  513 +/*--------------------------------------------------------------*/
  514 +
  515 +/*##############################################################
  516 + *# GetMultiData() #
  517 +/*##############################################################*/
  518 + int GetMultiData(int ID, int VarSize, char **VarNames, char *TimeInt, int BackFlag)
  519 +/*
  520 + * Create static DD_data_t variables array and return its pointer.
  521 + * After open a new file the function refreshes variable dimensions
  522 + * Data are returned by portions until end of requested interval.
  523 + * Return MOREDATA or OK, or error value.
  524 + * If requsted variable is "Time", then it converts into "double" form.
  525 + * The rool of this routine: DO NOT CALL SetNewFile if VI is locked,
  526 + * If VI have been locked and then have been releesed, Times has to be updated and
  527 + * SetTime has to be redone.
  528 + */
  529 +{
  530 + static int *VarID = NULL; /* IDs of requested Parameters of this VI */
  531 + static char TimeStr[TIMELENGTH];
  532 + static char TimeName[] = "Time";
  533 + static int TimeID;
  534 + //static size_t DimArray[NC_MAX_DIMS];
  535 + static size_t **DimArrayS = NULL; /* Several Dimensions arrays */
  536 + size_t *DimArray; /* Local Dimension Array (for the specific parameter */
  537 + static int DimIDArray[NC_MAX_DIMS];
  538 + static nc_type type;
  539 + static size_t start[NC_MAX_DIMS];
  540 + static size_t TimeCount[2] = {1,TIMELENGTH};
  541 + static size_t TimeStart[2] = {0,0};
  542 + static int Scalar = 0; /* indicator of scalar value */
  543 + static int String = 0; /* indicator of single (not timed) string March 9 1997 */
  544 + static int TimeTypeValue = 0; /* indicator of time type value */
  545 + static size_t RecordSize; /* Size of one record in terms of variables of specified type */
  546 + static size_t *PacketSize=NULL; /* Packets sizes of one record (of specified variable) */
  547 + static size_t RecordNumber; /* Variable maximal number of records in one packet */
  548 + int i,il;
  549 + int DimNumber;
  550 + int err2,status;
  551 + int CurrncID;
  552 +
  553 + /*-------------------------------------------------------------
  554 + * Following variables subsitute fields in DD_Var to save a time
  555 + *------------------------------------------------------------*/
  556 + static DD_Var_t Local;
  557 +
  558 + /** sleep(60); **/
  559 + /** if(Verbose)
  560 + {
  561 + for(il = 0; il < VarSize; il++)
  562 + fprintf(stderr,"GetMultiData(ID=%d), VarName=%s,Timeint=%s)\n",ID,VarNames[il],TimeInt);
  563 + fprintf(stderr,"GeMultitData(ID=%d) LastPacket: %d FileStatus: %d NewFile: %d NFWasOpen: %d\n",ID,
  564 + DD_Var[ID]->LastPacketFlag,
  565 + DD_Var[ID]->LastFileStatus,
  566 + DD_Var[ID]->NewFile,
  567 + DD_Var[ID]->NewFileWasOpen);
  568 + fprintf(stderr,"GetMultiData(ID=%d), DD_Var[ID]->VarData = %p\n",ID,DD_Var[ID]->VarData);
  569 + }
  570 + **/
  571 + /* Check the ID and reset the variable number*/
  572 + if(DD_Var[ID] == NULL) return(NOID);
  573 + //if(FirstFlag) { DD_Var[ID]->ParamSize = 0; FirstFlag = 0;}
  574 +
  575 + /* sleep(30); */ /* To give possibility to start gdb */
  576 +
  577 + /*===================================================
  578 + * Free data from the previous requests
  579 + * BUT the data dimensions are not removed YET
  580 + * Probably we have just fill new portion of the same data
  581 + *==================================================*/
  582 + for(il = 0; il < DD_Var[ID]->ParamSize; il++)
  583 + {
  584 + for(i = 0; i < DD_Var[ID]->VarData[il].VarNumber; i++)
  585 + {
  586 + //if (Verbose) fprintf(stderr," FREE ID = %d, il = %d, i = %d ptr %p\n",ID,il,i,DD_Var[ID]->VarData[il].Variables[i]);
  587 + free(DD_Var[ID]->VarData[il].Variables[i]);
  588 + DD_Var[ID]->VarData[il].VarNumber = 0;
  589 + }
  590 + }
  591 +
  592 + /*============================================================================
  593 + *###### Check if we need to refresh entire information about parameters #####
  594 + *###### We have to renovate ALL if previous request been finished or #####
  595 + *###### new file was open during previous entry #####
  596 + *============================================================================*/
  597 + if((DD_Var[ID]->LastPacketFlag == OK) || DD_Var[ID]->NewFile) // Request been finished or
  598 + // System was trying to open new file
  599 + {
  600 + if(DD_Var[ID]->ncID < 0) return NOPOINTER; /* Time has been not set */
  601 + if(Verbose) fprintf(stderr,"GetMultiData(%d): Parameters Info should be updated\n", ID);
  602 + /** sleep(60); **/
  603 + /*---------------------------------------------------------------------
  604 + * Look if the LastFileStatus has an error
  605 + *--------------------------------------------------------------------*/
  606 + switch(DD_Var[ID]->LastFileStatus)
  607 + {
  608 + case OK: break; /* Data file was open succesfully */
  609 + case CACHTOOREC: /* There was no free place in the CACH */
  610 + case TRYAGAIN: /* VI was blocked */
  611 + case WAITEXTCALL: /* New data was requested at external database */
  612 + if(Verbose) fprintf(stderr,"GetData(%d): There was WAITEXTCALL, I am trying again\n",ID);
  613 + /* We have to check if VI is unlocked */
  614 + switch(IsTimesLocked(&Local))
  615 + {
  616 + case NOLOCK: break;
  617 + case LOCKED:
  618 + if(Verbose) fprintf(stderr,"GetData(%d): Data base is still locked\n",ID);
  619 + DD_Var[ID]->VILocked = Local.VILocked;
  620 + return MOREDELAY; break;
  621 + case LOCKREMOVED: UpdateTimeInfo(&Local);
  622 + LocalOrigSync(&Local,DD_Var[ID]);
  623 + SetTime(&Local,Local.CDTime); /* Return to the original status */
  624 + if(Verbose) fprintf(stderr,"GetData(%d):Lock Was removed, SetTime again",ID);
  625 + }
  626 + switch(DD_Var[ID]->LastFileStatus = SetNewFile(&Local,1)) /* Only LOCAL work in our case !*/
  627 + {
  628 + case OK: break; /* New file is open, go on */
  629 + case CACHTOOREC: /* There was no free place in the CACH */
  630 + case TRYAGAIN: /* VI was blocked */
  631 + case WAITEXTCALL: /* New data was requested */
  632 + DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */
  633 + DD_Var[ID]->NewFile = 1;
  634 + DD_Var[ID]->NewFileWasOpen = 1;
  635 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  636 + if(Verbose) fprintf(stderr,"GetData(%d): We have to waite again: %d\n",ID,status);
  637 + return MOREDELAY;
  638 + break;
  639 + case OUTOFTIME:
  640 + if(Verbose) fprintf(stderr,"GetData(%d): OUTOFTIME while requested new file %d\n",ID,status);
  641 + DD_Var[ID]->LastFileStatus = OUTOFTIME;
  642 + DD_Var[ID]->LastPacketFlag = OK; /* Just to show that this request is completed */
  643 + return DD_Var[ID]->LastFileStatus;
  644 + break;
  645 + default:
  646 + if(Verbose) fprintf(stderr,"GetData(%d): Unrecoverable error: %d\n",ID,status);
  647 + DD_Var[ID]->LastPacketFlag = OK; /* Just to show that this request is completed */
  648 + return DD_Var[ID]->LastFileStatus;
  649 + }
  650 + break;
  651 + case OUTOFTIME: // Nothing to do with this request. New set time is needed
  652 + if(Verbose) fprintf(stderr,"GetData(%d): Previous call gave OUTOFTIME, return\n",ID);
  653 + return DD_Var[ID]->LastFileStatus;
  654 + break;
  655 + default: /* The error is unrecoverable */
  656 + if(Verbose) fprintf(stderr,"GetData(%d): Unrecoverable error: %d\n",ID,status);
  657 + return DD_Var[ID]->LastFileStatus;
  658 + }
  659 +
  660 + /*-----------------------------------------------------------------------------
  661 + * Data file is open. It is time to refresh information about parameters
  662 + *----------------------------------------------------------------------------*/
  663 + for(il = 0; il < DD_Var[ID]->ParamSize; il++) // Free existing dimensions
  664 + {
  665 + if(DD_Var[ID]->VarData[il].Dimensions != NULL) {free(DD_Var[ID]->VarData[il].Dimensions); DD_Var[ID]->VarData[il].Dimensions = NULL;}
  666 + if(DimArrayS[il] != NULL) {free(DimArrayS[il]); DimArrayS[il] = NULL;}
  667 + }
  668 + if(DD_Var[ID]->ParamSize > 0)
  669 + {
  670 + if(DD_Var[ID]->VarData != NULL) { free(DD_Var[ID]->VarData); DD_Var[ID]->VarData = NULL;}
  671 + free(VarID);
  672 + free(PacketSize);
  673 + free(DimArrayS);
  674 + }
  675 + DD_Var[ID]->ParamSize = (size_t)VarSize;
  676 + /*--------------------------------------------
  677 + * Create a new holder according to the parameters number
  678 + *--------------------------------------------*/
  679 + DD_Var[ID]->VarData = (DD_data_t *)malloc(sizeof(DD_data_t) * VarSize);
  680 + VarID = (int *)malloc(sizeof(int) * VarSize);
  681 + PacketSize = (size_t *)malloc(sizeof(size_t) * VarSize);
  682 + DimArrayS = (size_t **)malloc(sizeof(size_t *) * VarSize);
  683 + for(il = 0; il < DD_Var[ID]->ParamSize; il++) DimArrayS[il] = NULL;
  684 +
  685 + /*----------------------------------------------------
  686 + * Decide which ncID we are using
  687 + *---------------------------------------------------*/
  688 + if(DD_Var[ID]->NewFile == 1) CurrncID = Local.ncID;
  689 + else CurrncID = DD_Var[ID]->ncID;
  690 +
  691 + /*------------------------------------------------
  692 + * Calculation what number of records
  693 + * of the maximaly sized variable we can transmit
  694 + *-----------------------------------------------*/
  695 + RecordNumber = MaxRecord(CurrncID);
  696 + if(RecordNumber <= 0)
  697 + {
  698 + if(Verbose) fprintf(stderr,"GetMultiData(%d): Error in calculation of records number\n",ID);
  699 + return(INTSERERR);
  700 + }
  701 +
  702 + /*---------------------------------------------
  703 + * Define time ID
  704 + *--------------------------------------------*/
  705 + status = nc_inq_varid(CurrncID,TimeName,&TimeID);
  706 + /*------------------------------------------------------------------------------------------
  707 + * Reseting VarNumber and create a new local data structure
  708 + * Also we need to set Time limit constants
  709 + *------------------------------------------------------------------------------------------*/
  710 + if(DD_Var[ID]->LastPacketFlag == OK) /* Very new request, after SetTime() */
  711 + {
  712 + TimeStart[0] = DD_Var[ID]->nc_rec;
  713 + status = nc_get_vara_text(DD_Var[ID]->ncID,TimeID,TimeStart,TimeCount,TimeStr);
  714 + DD_Var[ID]->CDTime = DD_Time2Double(TimeStr); /* Current time of record */
  715 + DD_Var[ID]->SDTime = DD_Var[ID]->CDTime; /* Start time of record */
  716 + DD_Var[ID]->FDTime = DD_Var[ID]->SDTime + DD_Time2Double(TimeInt);
  717 + }
  718 +
  719 + DD_Var[ID]->NewFile = 0; /* Forget that it was new file */
  720 +
  721 + /*--------------------------------------------------
  722 + * Get Dimensions and allocate memory for all
  723 + * requested parameters
  724 + *-------------------------------------------------*/
  725 + for(il = 0; il < VarSize; il++)
  726 + {
  727 + DD_Var[ID]->VarData[il].VarNumber = 0;
  728 + status = nc_inq_varid(CurrncID,VarNames[il],&(VarID[il]));
  729 + if (status != NC_NOERR)
  730 + {
  731 + if(Verbose)
  732 + {
  733 + fprintf(stderr,"MultiData(%d): NCDF message: %s\n",ID,nc_strerror(status));
  734 + fprintf(stderr,"MultiData(%d): Parameter %s not found\n",ID,VarNames[il]);
  735 + }
  736 + VarID[il] = NOVAR; /* NOVAR */
  737 + }
  738 + /*--------------------------------------------------------
  739 + * Get dimensions number and its type
  740 + *------------------------------------------------------*/
  741 + if(VarID[il] != NOVAR)
  742 + {
  743 + DimArrayS[il] = (size_t *)malloc(sizeof(size_t) * NC_MAX_DIMS);
  744 + DimArray = DimArrayS[il]; // Just a local pointer
  745 + status = nc_inq_vartype(CurrncID,VarID[il],&type);
  746 + status = nc_inq_varndims(CurrncID,VarID[il],&DimNumber);
  747 + //if(Verbose) fprintf(stderr,"GetMultiData(%d): Dimensions(%d) number = %d\n",ID,il,DimNumber);
  748 +
  749 + status = nc_inq_vardimid(CurrncID,VarID[il],DimIDArray);
  750 + if(DimNumber == 0)
  751 + {
  752 + DD_Var[ID]->VarData[il].DimNumber = 1;
  753 + DimArray[1] = 1;
  754 + Scalar = 1; // For one parameter call only
  755 + }
  756 + else /* Filling the array of Dimensions */
  757 + {
  758 + for(i = 0; i < DimNumber; i++) status = nc_inq_dimlen(CurrncID,DimIDArray[i],&(DimArray[i]));
  759 + }
  760 +
  761 + /*--------------- Several special trucks for single variables (without time) ---------*/
  762 + if((DimArray[0]<2) && (DimIDArray[0] != 0)) Scalar = 1; /* If the first dimension is not TIME and lenrgth is 1 or 0 */
  763 + if((type == NC_CHAR) && (DimNumber < 2)) String = 1;
  764 + if(String == 0) DimArray[0] = 1; else DimArray[1] = DimArray[0];
  765 + if((String == 0) && (DimNumber == 1)) { DimArray[1] = 1; DimNumber = 2;}
  766 + if(DimNumber > 1) DD_Var[ID]->VarData[il].DimNumber = DimNumber -1;
  767 + else DD_Var[ID]->VarData[il].DimNumber = 1;
  768 +
  769 + /*----------------------------------------------------------
  770 + * Create dimensions, and fill the dimensions array
  771 + *--------------------------------------------------------*/
  772 + DD_Var[ID]->VarData[il].Dimensions = (int *)malloc(sizeof(int)*DimNumber);
  773 + for(i = 0; i < DD_Var[ID]->VarData[il].DimNumber; i++)
  774 + {
  775 + (DD_Var[ID]->VarData[il].Dimensions)[i] = (int)DimArray[i+1];
  776 + //if(Verbose) fprintf(stderr,"GetMultiData(%d): Dimensions(%d): dim[%d] = %d\n",ID,il,i,(int)DimArray[i+1]);
  777 + }
  778 +
  779 + /*---------------------------------------------------------------------
  780 + * Set Variable type
  781 + *-------------------------------------------------------------------*/
  782 + switch(type)
  783 + {
  784 + case NC_DOUBLE: DD_Var[ID]->VarData[il].type = DD_DOUBLE; break;
  785 + case NC_CHAR: DD_Var[ID]->VarData[il].type = DD_CHAR; break;
  786 + case NC_FLOAT: DD_Var[ID]->VarData[il].type = DD_FLOAT; break;
  787 + case NC_SHORT: DD_Var[ID]->VarData[il].type = DD_SHORT; break;
  788 + case NC_INT: DD_Var[ID]->VarData[il].type = DD_INT; break;
  789 + case NC_BYTE: DD_Var[ID]->VarData[il].type = DD_CHAR; break;
  790 + default: DD_Var[ID]->VarData[il].type = DD_CHAR;
  791 + }
  792 +
  793 + /*-------------------------------------------------------------------------
  794 + * Calculate the corresponding record size,
  795 + * an allocate memory to fit the RecordNumber records
  796 + *------------------------------------------------------------------------*/
  797 + RecordSize = 1;
  798 + for(i = 1; i < DimNumber; i++)
  799 + {
  800 + RecordSize = RecordSize * DimArray[i];
  801 + start[i] = 0;
  802 + }
  803 + if(String == 1) RecordSize = DimArray[0]; /* March 9 1997 */
  804 + PacketSize[il] = RecordSize*unixlen[DD_Var[ID]->VarData[il].type];
  805 +
  806 + DD_Var[ID]->VarData[il].Variables = (void **)malloc(sizeof(void *) * RecordNumber);
  807 + /*
  808 + if (Verbose)
  809 + fprintf(stderr," Malloc: DD_Var[%d]->VarData[%d].Variables = %p\n",ID, il, DD_Var[ID]->VarData[il].Variables);
  810 + */
  811 + }
  812 + else
  813 + {
  814 + DD_Var[ID]->VarData[il].type = NOVAR; /* To indicate absence of this variable */
  815 + PacketSize[il] = 0;
  816 + DD_Var[ID]->VarData[il].DimNumber = 0;
  817 + DD_Var[ID]->VarData[il].VarNumber = 0;
  818 + PacketSize[il] = 0;
  819 + }
  820 + } /* FOR il */
  821 +
  822 + /*-------------------------------------------
  823 + * Create a Local structure
  824 + *------------------------------------------- */
  825 + if(DD_Var[ID]->LastPacketFlag == OK) /* Very new request, after SetTime() */
  826 + {
  827 + memcpy((void *)&Local, (void *)DD_Var[ID], sizeof(DD_Var_t)); /*--- Local structure if it is new request */
  828 + //if(Verbose) fprintf(stderr,"GetData(%d): DD_Var[ID] -> Local\n",ID);
  829 + }
  830 + if(Verbose) fprintf(stderr,"GetMultiData(ID=%d), Created Local, DD_Var[ID]->VarData = %p\n",ID,DD_Var[ID]->VarData);
  831 + }
  832 + /*#######################################################################*/
  833 + /* End of refresh information about variable in case of new file
  834 + * or new request */
  835 + /*#######################################################################*/
  836 +
  837 + /*=================================================================
  838 + * GET DATA
  839 + *=================================================================*/
  840 + if ((Scalar == 1) || (String == 1)) DD_Var[ID]->LastPacketFlag = OK;
  841 + else DD_Var[ID]->LastPacketFlag = MOREDATA;
  842 +
  843 + /*===========================================================
  844 + * The loop to get data until time or file finish
  845 + *===========================================================*/
  846 + do
  847 + {
  848 + /*----------------------------------------
  849 + * Get memory for each variable
  850 + *-----------------------------------------*/
  851 + for(il = 0; il < VarSize; il++)
  852 + {
  853 + if( DD_Var[ID]->VarData[il].type >= 0)
  854 + {
  855 + DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber] = (void *)malloc(PacketSize[il]);
  856 + /*
  857 + if (Verbose)
  858 + fprintf(stderr,"Malloc: DD_Var[%d]->VarData[%d].Variables[%d] = %p, Size = %d\n",ID, il,
  859 + DD_Var[ID]->VarData[il].VarNumber,
  860 + DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber],
  861 + PacketSize[il]);
  862 + */
  863 + }
  864 + }
  865 + if((Scalar == 1) || (String == 1))
  866 + {
  867 + start[0] = 0;
  868 + }
  869 + else /* Setup start and looking for a time limit */
  870 + {
  871 +
  872 + /*---------- Define START from LOCAL struct and read current Time ----------*/
  873 + start[0] = Local.nc_rec;
  874 + TimeStart[0] = Local.nc_rec;
  875 + status = nc_get_vara_text(Local.ncID,TimeID,TimeStart,TimeCount,TimeStr);
  876 + Local.CDTime = DD_Time2Double(TimeStr); /* Current time of record */
  877 + //fprintf(stderr,"GetData(%d): Start %f Current %f Stop %f\n",ID,Local.SDTime,Local.CDTime,Local.FDTime);
  878 +
  879 + //-------------- Check if we have to return by time --------------
  880 + if(Local.CDTime > Local.FDTime) /* Return by time. All problem will path to the next GetData */
  881 + {
  882 + /* If new file was open we have to return to original file */
  883 + if(Verbose) fprintf(stderr,"GetData(%d): Stop By Time\n",ID);
  884 + SetOriginPointer(&Local, ID);
  885 + /*------- Free reserved for nothing last array -------------*/
  886 + for(il = 0; il < VarSize; il++)
  887 + {
  888 + if(DD_Var[ID]->VarData[il].type >= 0)
  889 + {
  890 + free(DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]);
  891 + /*
  892 + if (Verbose)
  893 + fprintf(stderr,"Free: DD_Var[%d]->VarData[%d].Variables[%d], Pntr %p\n",ID, il, DD_Var[ID]->VarData[il].VarNumber, DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]);
  894 + */
  895 + }
  896 + }
  897 + return OK;
  898 + } //--------- End return by time ---------------
  899 + }
  900 +
  901 + /*-------------------------------------------------------
  902 + * Get Data according to its type
  903 + *-------------------------------------------------------*/
  904 + for(il = 0; il < VarSize; il++)
  905 + {
  906 + if( DD_Var[ID]->VarData[il].type >= 0)
  907 + {
  908 + DimArray = DimArrayS[il];
  909 + /*
  910 + if(Verbose)
  911 + {
  912 + for (i = 0; i < DD_Var[ID]->VarData[il].DimNumber+1; i++)
  913 + fprintf(stderr,"GetMultiData(%d): Variable[%d], Dimension[%d] DimSize = %d\n", ID, il, i,DimArray[i]);
  914 + fprintf(stderr,"VarID[%d] = %d, type = %d\n",il, VarID[il],DD_Var[ID]->VarData[il].type);
  915 + }
  916 + */
  917 + switch(DD_Var[ID]->VarData[il].type)
  918 + {
  919 + case DD_DOUBLE: status = nc_get_vara_double(Local.ncID, VarID[il], start, DimArray,
  920 + (double *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]);
  921 + break;
  922 + case DD_INT: status = nc_get_vara_int(Local.ncID, VarID[il], start, DimArray,
  923 + (int *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]);
  924 + break;
  925 + case DD_FLOAT: status = nc_get_vara_float(Local.ncID, VarID[il], start, DimArray,
  926 + (float *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]);
  927 + // if(Verbose) fprintf(stderr,"(Variable[%d])[0] = %f\n",il,((float *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber])[0]);
  928 + break;
  929 + case DD_SHORT: status = nc_get_vara_short(Local.ncID, VarID[il], start, DimArray,
  930 + (short *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]);
  931 + break;
  932 + case DD_CHAR: status = nc_get_vara_text(Local.ncID, VarID[il], start, DimArray,
  933 + (char *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]);
  934 + } /* End of switch */
  935 + DD_Var[ID]->VarData[il].VarNumber++;
  936 + } /* if not NOVAR */
  937 + } /* for il */
  938 + /*------ Return immediately if it is just one record ------------*/
  939 + if ((Scalar == 1) || (String == 1)) return OK;
  940 +
  941 + /*---- Now we have to decide if we opVarNamesen a new file to continue ------------*/
  942 + if(DD_Var[ID]->LastPacketFlag == MOREDATA) /* Timed variable (no scalar) */
  943 + {
  944 + Local.nc_rec++;
  945 +
  946 + /*======================================================================
  947 + * The next procedure runs if the current file is finished and we have
  948 + * to open a new file (or look for external data source
  949 + *=====================================================================*/
  950 + if(Local.nc_rec > Local.Maxnc_rec - 1)
  951 + {
  952 + if(Verbose) fprintf(stderr,"GetData(%d): Stop By EOF\n",ID);
  953 + /* Before open new file we have to check the LOCK status */
  954 + switch(IsTimesLocked(&Local))
  955 + {
  956 + case NOLOCK: break;
  957 + case LOCKED: DD_Var[ID]->LastFileStatus = TRYAGAIN;
  958 + DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */
  959 + DD_Var[ID]->NewFile = 1;
  960 + DD_Var[ID]->NewFileWasOpen = 1;
  961 + return MOREDELAY; break;
  962 + case LOCKREMOVED: UpdateTimeInfo(&Local);
  963 + LocalOrigSync(&Local,DD_Var[ID]);
  964 + SetTime(&Local,Local.CDTime); /* Return to the original status */
  965 + }
  966 + switch(DD_Var[ID]->LastFileStatus = SetNewFile(&Local,1))
  967 + {
  968 + case OK: // Everything is OK
  969 + DD_Var[ID]->LastPacketFlag = MOREDATA;
  970 + DD_Var[ID]->NewFile = 1; // We have to reset all variables
  971 + DD_Var[ID]->NewFileWasOpen = 1;
  972 + if(Verbose) fprintf(stderr,"GetMultiData(ID=%d), Retun by EOF, MOREDATA, DD_Var[ID]->VarData = %p\n",ID,DD_Var[ID]->VarData);
  973 + return MOREDATA;
  974 + case TRYAGAIN: // just wait and try again
  975 + if(Verbose) fprintf(stderr,"GetData(%d): Open New File return TRYAGAIN\n",ID);
  976 + DD_Var[ID]->NewFile = 1;
  977 + DD_Var[ID]->NewFileWasOpen = 1;
  978 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  979 + DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */
  980 + return MOREDELAY;
  981 + case WAITEXTCALL: // just wait and try again
  982 + if(Verbose) fprintf(stderr,"GetData(%d): Open New File returned WAITEXTCALL\n",ID);
  983 + DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */
  984 + DD_Var[ID]->NewFile = 1;
  985 + DD_Var[ID]->NewFileWasOpen = 1;
  986 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  987 + return MOREDELAY;
  988 + case CACHTOOREC: // just wait and try again
  989 + if(Verbose) fprintf(stderr,"GetData(%d): Open New File returned CACHTOOREC\n",ID);
  990 + DD_Var[ID]->NewFile = 1;
  991 + DD_Var[ID]->NewFileWasOpen = 1;
  992 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  993 + return MOREDELAY;
  994 + case OUTOFTIME: // Return data as the last packet (as well as it was finished by time
  995 + if(Verbose) fprintf(stderr,"GetData(%d): New file is out of time\n",ID);
  996 + SetOriginPointer(&Local, ID);
  997 + DD_Var[ID]->LastPacketFlag = OK;
  998 + DD_Var[ID]->NewFile = 1;
  999 + return OK;
  1000 + break;
  1001 + default: // Unrecoverable error in the database or out of time
  1002 + if(Verbose) fprintf(stderr,"GetData(%d): Unrecoverable error in the new file\n",ID);
  1003 + Local.nc_rec--;
  1004 + DD_Var[ID]->LastPacketFlag = OK;
  1005 + DD_Var[ID]->NewFile = 0;
  1006 + return DD_Var[ID]->LastFileStatus;
  1007 + }
  1008 + } /* End of file finish processing */
  1009 +
  1010 + if(DD_Var[ID]->VarData[0].VarNumber >= RecordNumber) /* Packet size exceeded */
  1011 + {
  1012 + DD_Var[ID]->LastPacketFlag = MOREDATA;
  1013 + return MOREDATA;
  1014 + }
  1015 + } /* End of check of status */
  1016 + } while(1);
  1017 +
  1018 + return OK;
  1019 +}
  1020 +/*-----------------------------------------------------------------*/
  1021 +
  1022 +/*#################################################################
  1023 + * SET TIME
  1024 + * Set time and try to open appropriate data file. If not try to
  1025 + * call external archive
  1026 + * Return:
  1027 + * NOID - call with uncorrect VI holder
  1028 + * OUTOFTIME - Requested time is out of General time limitation
  1029 + * WAITEXTCALL - Server sent request to external archive
  1030 + * TRYAGAIN - VI is blocked by call to external database
  1031 + * NODATAATTIME - request time is inside NODATA time interval
  1032 + * some return of SetNewFile(); see ...
  1033 + *#################################################################*/
  1034 +
  1035 +int SetTime(DD_Var_t *DD_VarL, double VCTime)
  1036 +{
  1037 + char Name[MAXSETLENGTH]; /* Name of data nc file */
  1038 + char FullName[PATHLENGTH]; /* Full name of nc file */
  1039 + char StartTime[TIMELENGTH];
  1040 + char StopTime[TIMELENGTH];
  1041 + static char StartName[] = "StartTime";
  1042 + static char StopName[] = "StopTime";
  1043 + static char TimeName[] = "Time";
  1044 + int StartID,StopID,TimeID;
  1045 + size_t Rmin,Rmax,RLeft,RRight; /* Limits of record num */
  1046 + double dt, TestTime,MinTime,MaxTime;
  1047 + dd_tmstr_t *tt;
  1048 + int More; /* InsideFlag - we are inside good time interval */
  1049 + /* NoDataFlag - we in the time record marked "NODATA" */
  1050 + char TimeIntName[MAXSETLENGTH]; /* File name associated with the given time interval */
  1051 +
  1052 + static size_t start[2] = {0,0};
  1053 + static size_t TimeCount[2] = {1,TIMELENGTH};
  1054 + static size_t FileCount[2] = {1,MAXFILENAME};
  1055 + static void *p;
  1056 + static double CTime = 0.0; /* Real working requested time */
  1057 + int status;
  1058 + int SearchStatus; /* Status at the end of interval search */
  1059 + int ExternalReqStatus; /* Status at return of extenal call */
  1060 +
  1061 +/* Check the ID */
  1062 +/** sleep(40); **/
  1063 +
  1064 + if(Verbose) fprintf(stderr,"SetTime(%f): Start\n",VCTime);
  1065 + if(DD_VarL == NULL) return(NOID);
  1066 +
  1067 +/*===========================================================
  1068 + * Set CTime if need
  1069 + *===========================================================*/
  1070 + if(VCTime > 0)
  1071 + {
  1072 + CTime = VCTime;
  1073 + if(Verbose) fprintf(stderr,"SetTime(%f): CTime is from argument\n",CTime);
  1074 + }
  1075 + else if(Verbose) fprintf(stderr,"SetTime(%f): CTime is from saved value\n",CTime);
  1076 +
  1077 +/*----------------------------------------------------
  1078 + * Check if is out of Global Time Limits
  1079 + * If the requested time is out of Global Time Limit, the time is reset to the
  1080 + * correct time interval
  1081 + *----------------------------------------------------*/
  1082 + if (CTime <= DD_VarL->GlobalStart) CTime = DD_VarL->GlobalStart + QUANTOFFSET;
  1083 + if (CTime > DD_VarL->GlobalStop) return OUTOFTIME;
  1084 +
  1085 +/*
  1086 + * Check if this VI is not blocked by this or another server
  1087 + */
  1088 + switch(IsTimesLocked(DD_VarL))
  1089 + {
  1090 + case NOLOCK: break;
  1091 + case LOCKED: return TRYAGAIN; break;
  1092 + case LOCKREMOVED: UpdateTimeInfo(DD_VarL);
  1093 + }
  1094 +
  1095 +/*
  1096 + * If Ctime out of valid interval, we can try to get new data in external archive
  1097 + */
  1098 + if((DD_VarL->MinValidTime > CTime)||(DD_VarL->MaxValidTime < CTime))
  1099 + {
  1100 + if(Verbose) fprintf(stderr,"SetTime(): Start Time is out of current data interval\n");
  1101 + if(DD_VarL->ExtCallAllowed)
  1102 + {
  1103 + switch(ExternalReqStatus = ExtDataRequest(DD_VarL,CTime))
  1104 + {
  1105 + case OK: return WAITEXTCALL; /* Request is gone */
  1106 + case NOEXEC: break; /* Call is impossible */
  1107 + case NODATAATTIME: return NODATAATTIME; /* CTime in side NODATA interval */
  1108 + case GAPISSMALL: break; /* Out of data, but gap is too small */
  1109 + case OUTOFTIME: return OUTOFTIME;
  1110 + default: return OUTOFTIME;
  1111 + }
  1112 + } else return OUTOFTIME;
  1113 + }
  1114 +
  1115 +/*
  1116 + * Now we know that CTime SURE in between Tmin and TMax
  1117 + * We start from the middle of the maximal valid interval
  1118 + */
  1119 + Rmin = (size_t)DD_VarL->RValidMin;
  1120 + Rmax = (size_t)DD_VarL->RValidMax;
  1121 + More = 1;
  1122 + while(More)
  1123 + {
  1124 + DD_VarL->TimeRecNumber = (Rmin + Rmax)/2;
  1125 + SearchRight(DD_VarL,Rmin,Rmax); /*--- Go right up to valid interval */
  1126 + start[0] = DD_VarL->TimeRecNumber;
  1127 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StartID,start,TimeCount,StartTime);
  1128 + TestTime = DD_Time2Double(StartTime);
  1129 +
  1130 + if(CTime > TestTime) // StartTime(R) < CTime
  1131 + {
  1132 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime);
  1133 + TestTime = DD_Time2Double(StopTime);
  1134 + if(TestTime >= CTime) /* CTime is really inside this interval */
  1135 + {
  1136 + More = 0;
  1137 + SearchStatus = INSIDE;
  1138 + }
  1139 + else /* CTime is at the right of the R */
  1140 + {
  1141 + RLeft = DD_VarL->TimeRecNumber;
  1142 + DD_VarL->TimeRecNumber++;
  1143 + SearchRight(DD_VarL,Rmin,Rmax); /*R shift right up to the next valid interval */
  1144 + start[0] = DD_VarL->TimeRecNumber;
  1145 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime);
  1146 + TestTime = DD_Time2Double(StopTime);
  1147 + if(TestTime >= CTime) /* CTime is between Stop(R)-1 and Stop(R) */
  1148 + {
  1149 + More = 0;
  1150 + DD_VarL->CurrRmin = (int)RLeft;
  1151 + DD_VarL->CurrRmax = (int)DD_VarL->TimeRecNumber;
  1152 + /*--- Test if it is inside interval ------*/
  1153 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StartID,start,TimeCount,StartTime);
  1154 + TestTime = DD_Time2Double(StartTime);
  1155 + if(TestTime < CTime) SearchStatus = INSIDE;
  1156 + else SearchStatus = DATAATRIGHT; /* Ctime is inbetween the valid intervals */
  1157 + }
  1158 + else /* CTime is on the right from the Stop(R) */
  1159 + {
  1160 + Rmin = DD_VarL->TimeRecNumber;
  1161 + More = 1;
  1162 + }
  1163 + } /* else of CTime is at the right of the R */
  1164 + }
  1165 + else /* StartTime(R) > CTime */
  1166 + {
  1167 + RRight = DD_VarL->TimeRecNumber;
  1168 + DD_VarL->TimeRecNumber--;
  1169 + SearchLeft(DD_VarL,Rmin,Rmax); /*R shift left down to the next valid interval */
  1170 + start[0] = DD_VarL->TimeRecNumber;
  1171 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StartID,start,TimeCount,StartTime);
  1172 + TestTime = DD_Time2Double(StartTime);
  1173 + if(CTime > TestTime) // CTime is inbetween Start(R) and Start(RRight)
  1174 + {
  1175 + More = 0;
  1176 + DD_VarL->CurrRmax = (int)RRight;
  1177 + DD_VarL->CurrRmin = (int)DD_VarL->TimeRecNumber;
  1178 + /*--- Test if it is inside interval ------*/
  1179 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime);
  1180 + TestTime = DD_Time2Double(StopTime);
  1181 + if(TestTime > CTime) SearchStatus = INSIDE;
  1182 + else /* Ctime is inbetween the valid intervals */
  1183 + {
  1184 + DD_VarL->TimeRecNumber++; /* Return to the right interval */
  1185 + SearchStatus = DATAATRIGHT; /* Ctime is inbetween the valid intervals */
  1186 + }
  1187 + }
  1188 + else /* CTime is to the left from Start(R) */
  1189 + {
  1190 + Rmax = DD_VarL->TimeRecNumber;
  1191 + More =1;
  1192 + }
  1193 + } // else StartTime(R) > CTime
  1194 + } // while(More);
  1195 +/*------------------------------------------------------------------------------*/
  1196 + if(Verbose) fprintf(stderr,"SetTime(): Search Status is %d\n",SearchStatus);
  1197 +
  1198 +/*-----------------------------------------------------------------------
  1199 + * Now we check if we can and need to require new data in external archive
  1200 + *-----------------------------------------------------------------------*/
  1201 + if((SearchStatus != INSIDE)&&(DD_VarL->ExtCallAllowed))
  1202 + {
  1203 + switch(ExternalReqStatus = ExtDataRequest(DD_VarL,CTime))
  1204 + {
  1205 + case OK: return WAITEXTCALL; /* Request is gone */
  1206 + case NOEXEC: return NODATAATTIME; /* Call is impossible */
  1207 + case NODATAATTIME:
  1208 + start[0] = DD_VarL->TimeRecNumber;
  1209 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime);
  1210 + CTime = DD_Time2Double(StopTime) + 0.001;
  1211 + if(Verbose) fprintf(stderr,"SetTime(): There was NO Data intreval, CTime is scrolled to %f\n",CTime);
  1212 + return CTIMEISSHIFTED;
  1213 + case GAPISSMALL: DD_VarL->TimeRecNumber = DD_VarL->CurrRmax; break; /* Out of data, but gap is too small */
  1214 + case OUTOFTIME: return OUTOFTIME; break;
  1215 + default: return OUTOFTIME;
  1216 + }
  1217 + }
  1218 +
  1219 +/* Get the file Name and open file */
  1220 + if(Verbose) fprintf(stderr,"SetTime(): File found: %d\n",DD_VarL->TimeRecNumber);
  1221 + if((status = SetNewFile(DD_VarL,0)) < 0) return status;
  1222 +
  1223 +/*=====================================================================
  1224 + * Fit the CTime inside data file
  1225 + *=====================================================================*/
  1226 +/* Get MinTime and MaxTime */
  1227 + status = nc_inq_varid(DD_VarL->ncID,StartName, &StartID);
  1228 + status = nc_inq_varid(DD_VarL->ncID,StopName, &StopID);
  1229 + status = nc_inq_varid(DD_VarL->ncID,TimeName, &TimeID);
  1230 +
  1231 + if (status != NC_NOERR)
  1232 + {
  1233 + if(Verbose) fprintf(stderr,"SetTime(): %s\n",nc_strerror(status));
  1234 + return(DATAFILEERR);
  1235 + }
  1236 +
  1237 + start[0] = 0;
  1238 +
  1239 +
  1240 + status = nc_get_vara_text(DD_VarL->ncID, StartID, start,&TimeCount[1],StartTime);
  1241 + MinTime = DD_Time2Double(StartTime);
  1242 + status = nc_get_vara_text(DD_VarL->ncID, StopID, start,&TimeCount[1],StopTime);
  1243 + MaxTime = DD_Time2Double(StopTime);
  1244 +
  1245 +
  1246 +/* circle of finding of time */
  1247 + More = 1;
  1248 + Rmin = 0; Rmax = DD_VarL->Maxnc_rec - 1;
  1249 +
  1250 + do
  1251 + {
  1252 + start[0] = (Rmin + Rmax)/2;
  1253 + if(start[0] < Rmin) { DD_VarL->nc_rec = Rmin; More = 0;}
  1254 + if(start[0] > Rmax) { DD_VarL->nc_rec = Rmax; More = 0;}
  1255 + if(More > 0)
  1256 + {
  1257 + status = nc_get_vara_text(DD_VarL->ncID, TimeID,start,TimeCount,StartTime);
  1258 + TestTime = DD_Time2Double(StartTime);
  1259 +
  1260 + if(CTime >= TestTime)
  1261 + {
  1262 +// if(start[0] +1 >= DD_VarL->Maxnc_rec) return(OUTOFTIME);
  1263 + if(start[0] +1 >= DD_VarL->Maxnc_rec) // We are in the gap between the last record
  1264 + // and the StopTime of this file
  1265 + {
  1266 + if(Verbose) fprintf(stderr,"SetTime(): The gap between the last record and stop time\n");
  1267 + if((status = SetNewFile(DD_VarL,1)) < 0) return status;
  1268 + DD_VarL->nc_rec = 0;
  1269 + More = 0;
  1270 + if(Verbose) fprintf(stderr,"SetTime(): Pointer is set as %s, TimesRecord %d FileRecord %d\n",StartTime,DD_VarL->TimeRecNumber, DD_VarL->nc_rec);
  1271 + return 1;
  1272 + }
  1273 + start[0]++;
  1274 + status = nc_get_vara_text(DD_VarL->ncID, TimeID,start,TimeCount,StartTime);
  1275 + TestTime = DD_Time2Double(StartTime);
  1276 + if(CTime <= TestTime)
  1277 + {
  1278 + DD_VarL->nc_rec = start[0];
  1279 + More = 0;
  1280 + }
  1281 + else
  1282 + {
  1283 + MinTime = TestTime;
  1284 + Rmin = start[0];
  1285 + More = 1;
  1286 + }
  1287 + }
  1288 + else
  1289 + {
  1290 + if(start[0] <= Rmin) /* 25 Feb 1999 */
  1291 + {
  1292 + DD_VarL->nc_rec = Rmin;
  1293 + More = 0;
  1294 + }
  1295 + else
  1296 + {
  1297 + start[0]--;
  1298 + status = nc_get_vara_text(DD_VarL->ncID, TimeID,start,TimeCount,StartTime);
  1299 + TestTime = DD_Time2Double(StartTime);
  1300 + if(CTime >= TestTime)
  1301 + {
  1302 + DD_VarL->nc_rec = start[0] +1;
  1303 + More = 0;
  1304 + }
  1305 + else
  1306 + {
  1307 + MaxTime = TestTime;
  1308 + Rmax = start[0];
  1309 + More = 1;
  1310 + }
  1311 + }
  1312 + }
  1313 + }
  1314 + if(MaxTime - MinTime < 0.0001)
  1315 + {
  1316 + DD_VarL->nc_rec = start[0];
  1317 + More = 0;
  1318 + }
  1319 + } while(More == 1);
  1320 + if(Verbose) fprintf(stderr,"SetTime(): Pointer is set as %s, TimesRecord %d FileRecord %d\n",StartTime,DD_VarL->TimeRecNumber, DD_VarL->nc_rec);
  1321 +
  1322 + return(1);
  1323 +}
  1324 +/*======================================================================================*/
  1325 +
  1326 +/*--------------------------------------------------------------------------------------*/
  1327 +/* If There was TimeUpdate in one VI, vi have to update all other values in another VI */
  1328 +/*--------------------------------------------------------------------------------------*/
  1329 +int LocalOrigSync(DD_Var_t *Local, DD_Var_t *Orig)
  1330 +{
  1331 + Orig->tmID = Local->tmID;
  1332 + Orig->NameID = Local->NameID;
  1333 + Orig->StartID = Local->StartID;
  1334 + Orig->StopID = Local->StopID;
  1335 + Orig->RValidMin = Local->RValidMin;
  1336 + Orig->RValidMax = Local->RValidMax;
  1337 + Orig->MinValidTime = Local->MinValidTime;
  1338 + Orig->MaxValidTime = Local->MaxValidTime;
  1339 + Orig->CurrRmin = -1;
  1340 + Orig->CurrRmax = -1;
  1341 + Orig->VILocked = Local->VILocked;
  1342 + return 1;
  1343 +}
  1344 +
  1345 +/*--------------------------------------------------------------------------------------*/
  1346 +/* Recovering of the original pointer */
  1347 +/*--------------------------------------------------------------------------------------*/
  1348 +int SetOriginPointer(DD_Var_t *LocalVI, int ID)
  1349 +{
  1350 + if(DD_Var[ID]->NewFileWasOpen)
  1351 + {
  1352 + switch(IsTimesLocked(LocalVI))
  1353 + {
  1354 + case NOLOCK: break;
  1355 + case LOCKED: DD_Var[ID]->LastFileStatus = TRYAGAIN;
  1356 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  1357 + DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original holder that it is locked */
  1358 + DD_Var[ID]->NewFile = 0;
  1359 + DD_Var[ID]->NewFileWasOpen = 1;
  1360 + return MOREDELAY; break;
  1361 + case LOCKREMOVED: UpdateTimeInfo(LocalVI);
  1362 + LocalOrigSync(LocalVI,DD_Var[ID]);
  1363 + SetTime(DD_Var[ID],DD_Var[ID]->SDTime); /* Return to the original status */
  1364 + DD_Var[ID]->LastPacketFlag = OK;
  1365 + DD_Var[ID]->NewFileWasOpen = 0;
  1366 + DD_Var[ID]->NewFile = 0;
  1367 + DD_Var[ID]->LastFileStatus = OK; /* Total reset */
  1368 + return OK;
  1369 + }
  1370 + /* If VI is not locked, try to set new file */
  1371 + switch(DD_Var[ID]->LastFileStatus = SetNewFile(DD_Var[ID],0))
  1372 + {
  1373 + case OK: // Everything is OK
  1374 + DD_Var[ID]->LastPacketFlag = OK;
  1375 + DD_Var[ID]->NewFile = 0; // We have to reset all variables
  1376 + DD_Var[ID]->NewFileWasOpen = 0;
  1377 + return OK;
  1378 + case TRYAGAIN: // just wait and try again
  1379 + if(Verbose) fprintf(stderr,"GetData(%d): Reset to Origin return TRYAGAIN\n",ID);
  1380 + DD_Var[ID]->NewFile = 0;
  1381 + DD_Var[ID]->NewFileWasOpen = 1;
  1382 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  1383 + DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original holder that it is locked */
  1384 + return MOREDELAY;
  1385 + case WAITEXTCALL: // just wait and try again
  1386 + if(Verbose) fprintf(stderr,"GetData(%d): Reset to Origin return WAITEXTCALL\n",ID);
  1387 + DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original holder that it is locked */
  1388 + DD_Var[ID]->NewFile = 0;
  1389 + DD_Var[ID]->NewFileWasOpen = 1;
  1390 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  1391 + return MOREDELAY;
  1392 + case CACHTOOREC: // just wait and try again
  1393 + if(Verbose) fprintf(stderr,"GetData(%d): Reset to Origin returnCACHTOOREC\n",ID);
  1394 + DD_Var[ID]->NewFile = 0;
  1395 + DD_Var[ID]->NewFileWasOpen = 1;
  1396 + DD_Var[ID]->LastPacketFlag = MOREDELAY;
  1397 + return MOREDELAY;
  1398 + case OUTOFTIME: // An accident when we were trying to return to original file
  1399 + default: // Unrecoverable error in the database or out of time
  1400 + if(Verbose) fprintf(stderr,"GetData(%d): Reset to origin: Unrecovararable errorn (including OUT OF TIME)\n",ID);
  1401 + DD_Var[ID]->LastPacketFlag = OK;
  1402 + DD_Var[ID]->NewFile = 0;
  1403 + DD_Var[ID]->NewFileWasOpen = 1;
  1404 + return DD_Var[ID]->LastFileStatus;
  1405 + }
  1406 + }
  1407 + /* If we did not transfer to new file, we can just reset all */
  1408 + DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original the locking state */
  1409 + DD_Var[ID]->LastPacketFlag = OK;
  1410 + DD_Var[ID]->NewFileWasOpen = 0;
  1411 + DD_Var[ID]->NewFile = 0;
  1412 + DD_Var[ID]->LastFileStatus = OK;
  1413 +
  1414 +}
  1415 +/*######################################################################################*/
... ...
src/SERVER/DD_Server.c 0 → 100644
  1 +++ a/src/SERVER/DD_Server.c
... ... @@ -0,0 +1,701 @@
  1 +/*==============================================================
  2 + * DD SYSTEM
  3 + * DD_Server.c
  4 + * V. 6.0
  5 + *
  6 + * Description:
  7 + *
  8 + * See ../DOC/TECHDOC/DDServFunct.html for complete information
  9 + *
  10 + * List of revisions:
  11 + * September, 1995 - Fedorov, First realisation: V 1.0
  12 + * Oct 1997 - Fedorov, Acces security V 3.0
  13 + * Sep 4, 2002 - Fedorov, Some changes V 3.5
  14 + * Oct 28, 2002 - Fedorov, Communication ideology is changed V 4.1
  15 + * May 1, 2003 - Fedorov, The buffered send is added V.4.2
  16 + * Jul 16, 2004 - Fedorov, Check the buffer state V.4.3
  17 + * March 15, 2007 - Fedorov, V.5.0 Bug in cach, Fedorov
  18 + * March 24, 2007 - Fedorov, V.5.2 Bug in free memory
  19 + * Jun 17, 2007 - Fedorov, V.5.5 Create new VI and Fill data via external calls
  20 + * Jun 20, 2007 - Fedorov, V.5.51 Adjust to createVI**.php
  21 + * Sep 23, 2007 - Fedorov, V.5.6 SetTime has another interface
  22 + * Sep 24, 2007 - Fedorov, V.5.6 New Get_Data processing
  23 + * May 21, 2008 - Fedorov, V.5.7 Try SetTime several times
  24 + * Apr 12, 2009 - Fedorov, V.5.8 Correct procession of OUTOFTIME
  25 + * Nov 18, 2012 - Fedorov, V.6.0 New call to get the variable info
  26 + *===============================================================*/
  27 +#include "DD_Access.h"
  28 +#include <sys/time.h>
  29 +#include <sys/types.h>
  30 +#include <unistd.h>
  31 +#include "DD.h"
  32 +#include "DD_comm.h"
  33 +
  34 +/*-------------- Global definitions ------------------------*/
  35 +extern int errno;
  36 +int Verbose; /* Verbose mode (variable for all subroutines)*/
  37 +static int err; /* Common error for this file */
  38 +static fd_set rfds; // For function select to look
  39 +static struct timeval tv; // if send can be done
  40 +
  41 +
  42 +/*--------------------- SET_LISTENER ------------------------*/
  43 +/* function returns socket ID of listener or -1 as ERROR */
  44 +
  45 +int SetListener()
  46 +{
  47 +/*-------- Variables for resource file -----------------*/
  48 + char rname[PATHLENGTH]; /* name of res file */
  49 + char line[PATHLENGTH];
  50 + char *path;
  51 + FILE *resfile; /* resource file */
  52 +
  53 +/*---------- Variables for network ---------------------*/
  54 + static struct hostent *Host; /* name & internet (32b) address for
  55 + remote hosts (see netdb.h) */
  56 + static char RemSerName[PATHLENGTH]; /* name of remote server */
  57 +
  58 + static struct sockaddr_in IntAFAddr; /* structure of internet address of type AF_INET
  59 + see <netinet/in.h>
  60 + to get name of socket we should
  61 + to convert pointer to this structure
  62 + to pointer to "srtruct sockaddr" where
  63 + all fields are "char array". */
  64 +
  65 + int SocketID; /* socket ID (use as well file ID) */
  66 +
  67 + int cc,i,j;
  68 + int arg = 0;
  69 +
  70 +/*
  71 + *---------- Getting socket and its address ---------------------
  72 +*/
  73 +/*---------------- HOST and PORT ------------------------------*/
  74 + if((path = getenv("DDPATH")) == NULL)
  75 + {
  76 + (void *)strcpy(rname,"DD.res");
  77 + }
  78 + else
  79 + {
  80 + (void *)strcpy(rname,path);
  81 + (void *)strcpy(rname + strlen(rname), "/DD.res");
  82 + }
  83 +
  84 + if((resfile = fopen(rname,"r")) == NULL)
  85 + {
  86 + fprintf(stderr,"No resource file, sorry\n");
  87 + exit(1);
  88 + }
  89 +
  90 + fgets(RemSerName, PATHLENGTH, resfile);
  91 + RemSerName[strlen(RemSerName)-1] = '\0';
  92 + fgets(line, PATHLENGTH, resfile);
  93 + sscanf(line,"%hu",&(IntAFAddr.sin_port));
  94 + IntAFAddr.sin_port = htons(IntAFAddr.sin_port); /* Conversion of the port number to
  95 + universal network form */
  96 + fclose(resfile);
  97 +/*---------------- END of FILE READING --------------------------*/
  98 +
  99 +/*
  100 + *------- Trying to open socket with this address and name ---------
  101 + */
  102 + if((Host = gethostbyname(RemSerName)) == NULL) /* Get address and other information by
  103 + host name, see netdb.h */
  104 + {
  105 + fprintf(stderr,"Server %s not found\n",RemSerName);
  106 + return(-1);
  107 + }
  108 +
  109 + if((SocketID = socket(PF_INET,SOCK_STREAM,PROTOCOL)) < 0)
  110 + {
  111 + perror("Socket:"); return(-1);
  112 + }
  113 +/*
  114 + * Filling full internet address for socket "name"
  115 + * this address will be used to bind point
  116 + */
  117 + IntAFAddr.sin_family = AF_INET;
  118 + memcpy(&IntAFAddr.sin_addr.s_addr,Host->h_addr_list[0],Host->h_length);
  119 +/*
  120 + IntAFAddr.sin_family = Host->h_addrtype;
  121 + IntAFAddr.sin_addr.s_addr = INADDR_ANY;
  122 +*/
  123 +/* Naming of socket */
  124 + if(bind(SocketID,(struct sockaddr *)&IntAFAddr,sizeof(IntAFAddr))<0)
  125 + {
  126 + perror("Bind:"); return(-1);
  127 + }
  128 +
  129 + /* Registration of socket as passive for external requests */
  130 + if(listen(SocketID,SOMAXCONN) < 0)
  131 + {
  132 + perror("Listen:"); return(-1);
  133 + }
  134 + fprintf(stderr, "DD_SERVER was connected...!\n");
  135 +
  136 + /* Watch sochet before each send. */
  137 + FD_ZERO(&rfds);
  138 + FD_SET(SocketID, &rfds);
  139 +
  140 +
  141 +
  142 + return(SocketID);
  143 +}
  144 +/*---------------- End of SET_LISTENER ---------------------*/
  145 +
  146 +/*----------------- SendToNet ------------------------------*/
  147 +/*
  148 + * Enhanced send function.
  149 + * It buffers the packed end trying to send it by several attampts
  150 + */
  151 +int SendToNet(int SocketID, char *buff, int length)
  152 +{
  153 + int cc, pointer;
  154 + int retval;
  155 +
  156 + pointer = 0;
  157 + while(pointer < length)
  158 + {
  159 + /* Wait up to 30 seconds. */
  160 +// tv.tv_sec = 30;
  161 +// tv.tv_usec = 0;
  162 +
  163 +// retval = select(SocketID+1,NULL, &rfds, NULL, &tv);
  164 +// if(retval < 0) return -1;
  165 + if((cc = send(SocketID,buff+pointer,length - pointer,0)) < 0)
  166 + {
  167 + if(Verbose) perror("Send Data:");
  168 + return -1;
  169 + }
  170 +/*
  171 + fprintf(stderr,"send: p = %d, l = %d, cc = %d\n",pointer, length,cc);
  172 + fprintf(stderr,"buff: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n",
  173 + buff[0],buff[1],buff[2],buff[3],buff[4],buff[5],buff[6],
  174 + buff[7],buff[8],buff[9],buff[10],buff[11]);
  175 +*/
  176 + pointer += cc;
  177 + }
  178 + return 0;
  179 +}
  180 +
  181 +/*------------------ PUTHEADER -----------------------------*
  182 +/*
  183 + * Encode end send Reply Header
  184 + */
  185 +int PutHeader(int a1, int a2, int a3,int SocketID)
  186 +{
  187 + int cc;
  188 + XDR xdrs;
  189 + char buf[REPLYLENGTH];
  190 +
  191 + xdrmem_create(&xdrs, buf, REPLYLENGTH, XDR_ENCODE);
  192 + xdr_int(&xdrs,&a1);
  193 + xdr_int(&xdrs,&a2);
  194 + xdr_int(&xdrs,&a3);
  195 +
  196 + xdr_destroy(&xdrs);
  197 +
  198 +/* if((cc = send(SocketID,buf,REPLYLENGTH,0)) < 0) */
  199 + if((cc = SendToNet(SocketID,buf, REPLYLENGTH)) < 0)
  200 + {
  201 + if(Verbose) perror("PutHeader:");
  202 + return(REPLYRECERR);
  203 + }
  204 + return(0);
  205 +}
  206 +/*------------------------end of PutHeader ------------------------*/
  207 +
  208 +/*===================== Send Constant Packet ====================)*/
  209 +int SendConstantPacket(DD_Var_t *Data,int SocketID)
  210 +{
  211 + caddr_t buff;
  212 + XDR xdrs;
  213 + int PacketSize,i,cc;
  214 + u_int MaxNumber,Number;
  215 + int error = OK;
  216 +
  217 + MaxNumber = 1;
  218 + for(i = 0;i < Data->AttrData.DimNumber; i++)
  219 + MaxNumber = MaxNumber * Data->AttrData.Dimensions[i];
  220 + PacketSize = xdrlen[DD_INT] + /* Number of elements in Dimensions array */
  221 + xdrlen[DD_INT] * Data->AttrData.DimNumber + /* Dimensions array */
  222 + xdrlen[DD_INT] + /* Number of elements in data array */
  223 + MaxNumber * xdrlen[Data->AttrData.type]; /* Data Array */
  224 +
  225 +/* Sending Header */
  226 + if((error = PutHeader(Data->AttrData.type,
  227 + Data->AttrData.DimNumber,
  228 + PacketSize,SocketID)) < 0) return error;
  229 +
  230 + buff =(caddr_t)malloc(PacketSize);
  231 + xdrmem_create(&xdrs, buff, (u_int)PacketSize, XDR_ENCODE);
  232 +
  233 +/* Packing Dimensions */
  234 + if(Data->AttrData.DimNumber > 0)
  235 + {
  236 + Number = (u_int)Data->AttrData.DimNumber;
  237 + xdr_array(&xdrs, (caddr_t *)&(Data->AttrData.Dimensions),
  238 + &Number,
  239 + (u_int)Data->AttrData.DimNumber,
  240 + unixlen[DD_INT],
  241 + (xdrproc_t)xdr_int);
  242 + }
  243 +
  244 +/* Packing Variables */
  245 + xdr_array(&xdrs,(caddr_t *)&(Data->AttrData.Variables[0]),
  246 + &MaxNumber,
  247 + MaxNumber,
  248 + unixlen[Data->AttrData.type],
  249 + (xdrproc_t)ConvFunc[Data->AttrData.type]);
  250 +
  251 +/* Sending Packet */
  252 +/* if((cc = send(SocketID,buff,PacketSize,0)) < 0)*/
  253 + if((cc = SendToNet(SocketID,buff, PacketSize)) < 0)
  254 + {
  255 + if(Verbose) perror("Send Constant Packet: ");
  256 + error = REPLYRECERR;
  257 + }
  258 + xdr_destroy(&xdrs);
  259 + free(buff);
  260 + return error;
  261 +}
  262 +/*------------------- End Send Constant Packet -------------------------------*/
  263 +
  264 +/*===================== Send Data Packet ====================)*/
  265 +int SendDataPacket(DD_Var_t *Data, int SocketID, int LastFlag)
  266 +{
  267 + caddr_t buff;
  268 + XDR xdrs;
  269 + int PacketSize,i,cc,il;
  270 + u_int MaxNumber,Number;
  271 + int error = OK;
  272 +
  273 + for(il = 0; il < Data->ParamSize; il++)
  274 + {
  275 + MaxNumber = 1;
  276 + for(i = 0;i < Data->VarData[il].DimNumber; i++)
  277 + MaxNumber = MaxNumber * Data->VarData[il].Dimensions[i];
  278 +
  279 + PacketSize = xdrlen[DD_INT] + /* Flag */
  280 + xdrlen[DD_INT] + /* arrays number */
  281 + xdrlen[DD_INT] + /* Sise of dimensions array */
  282 + xdrlen[DD_INT] *(Data->VarData[il].DimNumber+1) + /* dimensions array */
  283 + MaxNumber*xdrlen[Data->VarData[il].type]*Data->VarData[il].VarNumber + /* set if data arrays */
  284 + xdrlen[DD_INT] * Data->VarData[il].VarNumber; /* data arrays sizes */
  285 +
  286 + /* Sending header */
  287 + if((error = PutHeader(Data->VarData[il].type,
  288 + Data->VarData[il].DimNumber+1,
  289 + PacketSize,SocketID)) < 0) return error;
  290 +
  291 + buff =(caddr_t)malloc(PacketSize);
  292 + xdrmem_create(&xdrs, buff, (u_int)PacketSize, XDR_ENCODE);
  293 +
  294 + /* Packing flag and Variables number */
  295 + xdr_int(&xdrs, &LastFlag);
  296 + xdr_int(&xdrs, &Data->VarData[il].VarNumber);
  297 +
  298 + /* Packing dimensions */
  299 + if(Data->VarData[il].DimNumber > 0)
  300 + {
  301 + Number = (u_int)Data->VarData[il].DimNumber;
  302 + xdr_array(&xdrs,
  303 + (caddr_t*)(&Data->VarData[il].Dimensions),
  304 + &Number,
  305 + (u_int )Data->VarData[il].DimNumber,
  306 + unixlen[DD_INT],
  307 + (xdrproc_t)xdr_int);
  308 + }
  309 +
  310 + /*Packing Variables */
  311 + for(i = 0; i < Data->VarData[il].VarNumber; i++)
  312 + {
  313 + Number = MaxNumber;
  314 + xdr_array(&xdrs,
  315 + (caddr_t *)(&Data->VarData[il].Variables[i]),
  316 + &Number,
  317 + MaxNumber,
  318 + unixlen[Data->VarData[il].type],
  319 + (xdrproc_t)ConvFunc[Data->VarData[il].type]);
  320 + }
  321 +
  322 + /* Sending Data Packet */
  323 + if((cc = SendToNet(SocketID,buff, PacketSize)) < 0)
  324 + {
  325 + if(Verbose) perror("SendDataPacket(): ");
  326 + error = REPLYRECERR;
  327 + }
  328 + xdr_destroy(&xdrs);
  329 + free(buff);
  330 + if(Verbose) fprintf(stderr,"SendDataPacket()[%d] succesful\n",il);
  331 + } // FOR il
  332 + return error;
  333 +}
  334 +/*----------------------- End Send Data Packet -------------*/
  335 +
  336 +/*--------------------- SERV -------------------------------*/
  337 +/*
  338 + * Read requests from socket, call appropriate function and
  339 + * return packets with information
  340 + * Start of this subroutine is the start of new communication session
  341 + */
  342 +
  343 +void Serv(int SocketID)
  344 +{
  345 + int cc;
  346 + int i,nlen;
  347 + char *bbt, GetTime[20];int bbtt[100],j, NoAccessToWork = 0,DD_id;
  348 + char Acc_Int[20]; double TimeInt,TimeStart,TimeStop;
  349 + int ReqType;
  350 + static char *ReqName = NULL;
  351 + static char *ReqTime = NULL;
  352 + static char *ReqHost = NULL;
  353 + static char *ReqTicket = NULL;
  354 + static char *ReqLogin = NULL;
  355 + static char *STReqLogin = NULL;
  356 +
  357 + /*------- Variables to create new VI ---------------*/
  358 + static char *NewVIName = NULL; /* Full name of VI (data set to generate )*/
  359 + static char *RemSetID = NULL; /* ID of remote Data Set */
  360 + static char *RemBaseName = NULL; /* Base Name of remote WEB service */
  361 + static char Command[MAXCOMMANDL]; /*Memory for command in system()
  362 + /*--------------------------------------------------*/
  363 +
  364 + /*---------------------------------------------------
  365 + * Variables need for the multy variavles
  366 + * Data Get
  367 + *---------------------------------------------------*/
  368 + int PacketSize; // The size of the packet to get after the header packet
  369 + static int VarSize=0; // The number of variables to get
  370 + static char **VarNames = NULL; // Pointer to the C strings with the variable names
  371 + char *VarBuffer = NULL;
  372 + int BackFlag; // Variable for multi variable call
  373 + int il;
  374 + /*---------------------------------------------------*/
  375 +
  376 + char *STReqHost = NULL;
  377 + int STid;
  378 + char *ReqBuf= NULL;
  379 + XDR xdrs;
  380 + int id=-1,lenall;
  381 + int op;
  382 + int errTick,serr;
  383 + DD_Var_t *Data;
  384 + int RemainID =0; /* Number of remained ID in use */
  385 + static int TicketID = NOPERMISSION;
  386 + static int uid, FileAccID;
  387 + int GoOut = 0; /* The flag of finishing of session */
  388 + int LastFlag; /* The flag of the end of data transmission */
  389 +
  390 +/* WORKING */
  391 + if(ReqName == NULL) ReqName = malloc(MAXSETLENGTH);
  392 + if(ReqTime == NULL) ReqTime = malloc(TIMELENGTH);
  393 + if(ReqBuf == NULL) ReqBuf = malloc(REQUESTLENGTH);
  394 + if(ReqHost == NULL) ReqHost = malloc(MAXHOSTLENGTH);
  395 + if(ReqTicket == NULL) ReqTicket = malloc(TICKETLENGTH);
  396 + if(ReqLogin == NULL) ReqLogin = malloc(USRLENGTH);
  397 + if(STReqLogin == NULL) STReqLogin = malloc(USRLENGTH);
  398 + if(STReqHost == NULL) STReqHost = malloc(MAXHOSTLENGTH);
  399 + /*==============================================*/
  400 +
  401 +/*------------------------- General Data Array Preparation ---------------------------*/
  402 +
  403 + DD_Var = (DD_Var_t **)malloc(MaxIDNumber * sizeof(DD_Var_t *));
  404 + for(i=0;i<MaxIDNumber;i++) DD_Var[i] = NULL;
  405 +
  406 +/*-----------------------Open Access Virtual instrument ----------------------------------*/
  407 +/**
  408 + sleep(60);
  409 +**/
  410 + FileAccID = OpenInstr(ACCINSTR);
  411 + if(FileAccID < 0)
  412 + {
  413 + err = FileAccID;
  414 + fprintf(stderr,"Error while open %s VI\n",ACCINSTR);
  415 + goto endend;
  416 + }
  417 +
  418 +/*------------------------- Read Requests ---------------------------------------*/
  419 + do
  420 + {
  421 + /* Get request from client */
  422 + while((cc = recv(SocketID,ReqBuf,REQUESTLENGTH,0)) < 0);
  423 +
  424 + err = 0;
  425 +
  426 +/* Decode Request */
  427 + xdrmem_create(&xdrs, ReqBuf, REQUESTLENGTH, XDR_DECODE);
  428 + xdr_int(&xdrs,&ReqType);
  429 +
  430 + switch (ReqType)
  431 + {
  432 + case OPENINSREQ:
  433 + xdr_string(&xdrs,&ReqName,MAXSETLENGTH);
  434 +
  435 + xdrmem_create(&xdrs, ReqBuf,REQUESTLENGTH , XDR_FREE);
  436 + while((cc = recv(SocketID,ReqBuf,REQUESTLENGTH,0)) < 0); /* Receive identification packet */
  437 + xdrmem_create(&xdrs, ReqBuf,REQUESTLENGTH, XDR_DECODE);
  438 + xdr_int(&xdrs,&uid);
  439 + xdr_string(&xdrs,&ReqHost,MAXHOSTLENGTH);
  440 + xdr_string(&xdrs,&ReqLogin,USRLENGTH);
  441 + if(Verbose)printf("Serv():OPENINSREQ: Client Pasport: ID = %d, Host <%s>\n",uid,ReqHost);
  442 +
  443 + break;
  444 +
  445 + case CLOSEINSREQ :
  446 + xdr_int(&xdrs,&id);
  447 + break;
  448 +
  449 + case TIMESETREQ:
  450 + xdr_int(&xdrs,&id);
  451 + xdr_string(&xdrs,&ReqTime,TIMELENGTH);
  452 + break;
  453 +
  454 + case DATAINFOREQ:
  455 + xdr_int(&xdrs,&id);
  456 + xdr_string(&xdrs,&ReqName,MAXVARLENGTH);
  457 + break;
  458 +
  459 + /*--------------------------------------------
  460 + * This request needs to receive the
  461 + * additinal information from the client
  462 + *------------------------------------------*/
  463 + case DATAGETREQ:
  464 + /** sleep(60); **/
  465 + /*----------------------------------------
  466 + * Clear the list of variables
  467 + *---------------------------------------*/
  468 + if(VarNames != NULL)
  469 + {
  470 + for(il=0;il < VarSize; il++) free(VarNames[il]);
  471 + free(VarNames);
  472 + VarNames = NULL;
  473 + VarSize = 0;
  474 + }
  475 + /*-----------------------------------------
  476 + * Decode the heading packet
  477 + *---------------------------------------*/
  478 + xdr_int(&xdrs,&id);
  479 + xdr_string(&xdrs,&ReqTime,TIMELENGTH);
  480 + xdr_int(&xdrs,&PacketSize);
  481 + xdr_destroy(&xdrs);
  482 + /*-----------------------------------------
  483 + * Receive and Decode the variable packet
  484 + *---------------------------------------*/
  485 + if(VarBuffer != NULL) free(VarBuffer);
  486 + VarBuffer = (char *)malloc(sizeof(char)*PacketSize);
  487 + while((cc = recv(SocketID,VarBuffer,PacketSize,0)) < 0);
  488 + xdrmem_create(&xdrs, VarBuffer,PacketSize, XDR_DECODE);
  489 + xdr_int(&xdrs,&VarSize);
  490 + VarNames = (char **)malloc(sizeof(char *) * VarSize);
  491 + for(il=0;il < VarSize; il++)
  492 + {
  493 + VarNames[il] = (char *)malloc(sizeof(char) * MAXVARLENGTH);
  494 + xdr_string(&xdrs,&(VarNames[il]),MAXVARLENGTH);
  495 + if(Verbose) fprintf(stderr,"Serv():DATAGETREQ: Variable[%d] %s\n",il,VarNames[il]);
  496 + }
  497 + xdr_int(&xdrs,&BackFlag);
  498 + break;
  499 +
  500 + case ADDVIREQ:
  501 + xdr_string(&xdrs,&NewVIName,MAXSETLENGTH);
  502 + xdr_string(&xdrs,&RemSetID,MAXVARLENGTH);
  503 + xdr_string(&xdrs,&RemBaseName,MAXVARLENGTH);
  504 + break;
  505 +
  506 + case GETTICKETREQ:
  507 + xdrmem_create(&xdrs, ReqBuf,REQUESTLENGTH , XDR_FREE);
  508 + while((cc = recv(SocketID,ReqBuf,REQUESTLENGTH,0)) < 0);
  509 + xdrmem_create(&xdrs, ReqBuf, REQUESTLENGTH, XDR_DECODE);
  510 +
  511 + xdr_int(&xdrs,&uid);
  512 + xdr_string(&xdrs,&ReqLogin,USRLENGTH);
  513 + xdr_string(&xdrs,&ReqTicket,TICKETLENGTH);
  514 + xdr_string(&xdrs,&ReqHost,MAXHOSTLENGTH);
  515 +
  516 + break;
  517 +
  518 +
  519 + case SHOWTICKETREQ:
  520 + xdr_int(&xdrs,&STid);
  521 + xdr_string(&xdrs,&STReqHost,MAXHOSTLENGTH);
  522 + xdr_string(&xdrs,&STReqLogin,USRLENGTH);
  523 + break;
  524 + default: err = REQSENDERR;
  525 + } /* switch REQTYPE */
  526 + xdr_destroy(&xdrs);
  527 +
  528 + /*------------------------------------------------
  529 + * Call data functions and response generation
  530 + *----------------------------------------------*/
  531 +
  532 + switch(ReqType)
  533 + {
  534 + case OPENINSREQ:
  535 + if(Verbose) fprintf(stderr,"Serv():OPENINSREQ:ShowTicket; Host %s\n",ReqHost);
  536 + err = ShowTicket(uid,ReqHost,ReqLogin);
  537 + if(err >= 0)
  538 + {
  539 + id = OpenInstr(ReqName);
  540 + err = id;
  541 + if(id >= 0) strcpy(DD_Var[id]->InstrName,ReqName);
  542 + err = PutHeader(id,0,0,SocketID); /* return error if something is wrong */
  543 + }
  544 + else PutHeader(err,0,0,SocketID);
  545 + break;
  546 + case CLOSEINSREQ:
  547 + if(id < 0){err = NOID;PutHeader(err,0,0,SocketID);}
  548 + if(Verbose) fprintf(stderr,"Serv():CLOSEINSREQ: ID = %d\n",id);
  549 + RemainID = CloseID(id);
  550 + if(RemainID < 1)
  551 + {
  552 + err = NOID;
  553 + PutHeader(err,0,0,SocketID);
  554 + }
  555 + else
  556 + {
  557 + err = PutHeader(RemainID-1,0,0,SocketID);
  558 + if(RemainID == 1) GoOut = 1;
  559 + }
  560 + break;
  561 + case TIMESETREQ:
  562 + if(id < 0) err = NOID;
  563 + if(err >= 0) err = SetTime(DD_Var[id],DD_Time2Double(ReqTime));
  564 + if(err == CTIMEISSHIFTED) err = SetTime(DD_Var[id],-1.0);
  565 + if(err >= 0) PutHeader(0,0,0,SocketID);
  566 + else PutHeader(err,0,0,SocketID);
  567 + break;
  568 +
  569 + case DATAINFOREQ:
  570 + if(id < 0) err = NOID;
  571 + else err = GetAttribute(id,ReqName);
  572 + if(err >= 0) err = SendConstantPacket(DD_Var[id],SocketID);
  573 + else PutHeader(err,0,0,SocketID);
  574 + break;
  575 +
  576 + case DATAGETREQ:
  577 + if(id < 0) err = NOID;
  578 + /*------ Call data until LastPacket Flag (OK) returns --------*/
  579 + else do
  580 + {
  581 + err = GetMultiData(id,VarSize,VarNames,ReqTime,BackFlag);
  582 + if(err >= 0)
  583 + {
  584 + serr = SendDataPacket(DD_Var[id],SocketID,DD_Var[id]->LastPacketFlag); /* OK, MOREDATA, MOREDELAY */
  585 + if(Verbose) fprintf(stderr, "Server:DATAGETRQ (ID=%d):GetMultiData->SentPackets\n", id);
  586 + }
  587 + }
  588 + while((err >= 0) && (DD_Var[id]->LastPacketFlag == MOREDATA));
  589 + if(err < 0) PutHeader(err,0,0,SocketID);
  590 + break;
  591 +
  592 + case ADDVIREQ:
  593 + sprintf(Command,ADDDATASETCALL,getenv("DDBASEBIN"),RemBaseName,RemSetID,NewVIName);
  594 + if(Verbose) fprintf(stderr, "Serv:ADDVIREQ: Command = %s\n", Command);
  595 + err = system(Command);
  596 + switch(err)
  597 + {
  598 + case 0: PutHeader(OK,0,0,SocketID); break;
  599 + case NOPHP: PutHeader(NOEXEC,0,0,SocketID); break;
  600 + case NOSCRIPT: PutHeader(NOEXEC,0,0,SocketID); break;
  601 + default: PutHeader(NOEXEC,0,0,SocketID);
  602 + }
  603 + GoOut = 1;
  604 + break;
  605 +
  606 + case GETTICKETREQ:
  607 + errTick = CheckTicket(ReqLogin, ReqTicket);
  608 + Put2Log(uid,ReqHost,ReqLogin,errTick); /* Log file */
  609 + if(errTick >= 0) TicketID = GetTicket(uid,ReqHost,errTick);
  610 + if(Verbose) printf("GETTICKETREQ: uid= %d ReqHost = %s ErrTick = %d\n",uid,ReqHost ,errTick);
  611 + PutHeader(TicketID,0,0,SocketID);
  612 + GoOut = 1;
  613 + break;
  614 +
  615 + case SHOWTICKETREQ:
  616 + if(Verbose) printf("SHOWTICKETREQ; ShowTicket; Host %s\n",STReqHost);
  617 + err = ShowTicket(STid,STReqHost,STReqLogin);
  618 + PutHeader(err,0,0,SocketID);
  619 + GoOut = 1;
  620 + break;
  621 + } /* swithch Reqtype */
  622 +
  623 + } while(GoOut == 0);/* end while(GoOut) */
  624 + if(Verbose) fprintf(stderr,"DD_SERVER:Exit child process, communication closed\n");
  625 +
  626 +
  627 +endend:
  628 + if(Verbose)
  629 + fprintf(stderr, "Serv():EndEnd:Close session %d at %s by error %d\n",SocketID,Double2DD_Time((double)time(NULL)),err);
  630 + RemainID = CloseID(FileAccID);
  631 + if(Verbose) fprintf(stderr, "Serv():EndEnd:Last Open VI (Access) is closed\n");
  632 +
  633 + if(RemainID < 0) err = NOID;
  634 +
  635 + free(ReqName);
  636 + free(ReqTime);
  637 + free(ReqBuf);
  638 + free(ReqHost);
  639 + free(ReqTicket);
  640 + free(ReqLogin);
  641 + free(STReqLogin);
  642 + free(STReqHost);
  643 + free(DD_Var);
  644 +
  645 + shutdown(SocketID,2);
  646 + close(SocketID);
  647 + exit(0);
  648 +}
  649 +/*---------------------end of SERV ------------------------*/
  650 +
  651 +/*-----------------------MAIN ------------------------------*/
  652 +int main(int argc, char **argv)
  653 +{
  654 + int ListenerID;
  655 + int NewSocketID;
  656 + struct sockaddr NewSocketAddr;
  657 + socklen_t NewSocketLen;
  658 + int stat_loc;
  659 +
  660 + if(argc < 2) Verbose = 0;
  661 + else if(((argv[1])[1] == 'v') || ((argv[1])[1] == 'V')) Verbose = 1;
  662 + else Verbose = 0;
  663 +
  664 + if((ListenerID = SetListener()) < 0)
  665 + {
  666 + fprintf(stderr,"DD_server: I cant set Listener Socket\n");
  667 + exit(1);
  668 + }
  669 +
  670 +/*------- Define the maximum number of open Virtual Instruments ----------------*/
  671 + MaxIDNumber = (size_t)(sysconf(_SC_OPEN_MAX) / 3L - 5L);
  672 +
  673 +/*-------- Endless listen ----------------------------------------------*/
  674 + while(1)
  675 + {
  676 + NewSocketLen = sizeof(NewSocketAddr);
  677 + if((NewSocketID = accept(ListenerID,&NewSocketAddr,&NewSocketLen)) < 0)
  678 + {
  679 + // printf(" %d %d %d \n", ListenerID, (int)NewSocketLen, NewSocketID);
  680 + if(Verbose) perror("DD_Server: Accept: ");
  681 + }
  682 + else
  683 + {
  684 + if(Verbose) fprintf(stderr, "There is connection from ...\n");
  685 + if(fork() == 0) /* I am child */
  686 + {
  687 + if(fork() == 0)
  688 + {
  689 + Serv(NewSocketID); /*Real working */
  690 + }
  691 + else exit(0);
  692 + }
  693 + else wait(&stat_loc); /* wait of finishing of child */
  694 + close(NewSocketID);
  695 + }
  696 + }
  697 + /* Unreachable point */
  698 +
  699 + close(ListenerID);
  700 + return 0;
  701 +}
... ...
src/SERVER/ExtDataRequest.c 0 → 100644
  1 +++ a/src/SERVER/ExtDataRequest.c
... ... @@ -0,0 +1,303 @@
  1 +/**
  2 + * @file ExtDataRequest.c
  3 + * @version $Id: ExtDataRequest.c,v 1.6 2009/07/07 12:24:23 budnik Exp $
  4 + *=====================================================================
  5 + * ExtDataRequest.c
  6 + * V.2.6
  7 + * Functions set to call external script to get more data for
  8 + * current database.
  9 + *
  10 + * Versions:
  11 + * Aug 3, 2007, V.1.0, Fedorov
  12 + * Sep 20, 2007, V.2.0, Fedorov, New solution for IsTimesLocked()
  13 + * Sep 20, 2007, V.2.1, Fedorov, New solution for IsTimesLocked()
  14 + * Sep 25, 2007, V.2.2, Fedorov, Variable GAP
  15 + * May 21, 2008, V.2.3, Fedorov, skip no data file
  16 + * May 22, 2008, V.2.4, Fedorov, Measuring of elapsed time of Lock
  17 + * Apr 11, 2009, V.2.5, Fedorov, Do not call new file if the data out of general limits
  18 + * Jul 07, 2009, V.2.6, Budnik, Special external call if there is empty times.nc;
  19 + * if(DStop <= DD_Var->GlobalStart)
  20 + * if(DStart >= DD_Var->GlobalStop)
  21 + *=====================================================================*/
  22 +
  23 +#include <unistd.h>
  24 +#include <string.h>
  25 +#include "DD.h"
  26 +#include "DD_comm.h"
  27 +
  28 +extern int Verbose;
  29 +
  30 +/*=====================================================================
  31 + * Double2ISOTime()
  32 + * Covert double time to ISO time
  33 + * return pointer to statis string inside function
  34 + *=====================================================================*/
  35 +char *Double2ISOTime(double CTime)
  36 +{
  37 + static char ISO[25];
  38 + unsigned *UT;
  39 +
  40 + UT = Double2UT(CTime);
  41 + sprintf(ISO,ISOTIMEP,UT[0],UT[1],UT[2],UT[3],UT[4],UT[5],UT[6]);
  42 + return (char *)ISO;
  43 +}
  44 +
  45 +/*=====================================================================
  46 + * DoRequest
  47 + * Read request.
  48 + * return OK, or NOEXEC
  49 + *=====================================================================*/
  50 + int DoRequest(DD_Var_t *DD_Var, double Start, double Stop)
  51 + {
  52 + static char Command[MAXCOMMANDL]; /*Memory for command in system() */
  53 + static char StartISO[25],StopISO[25];
  54 + int err;
  55 + struct timeval tv;
  56 + struct timezone tz;
  57 +
  58 + /*======================================================
  59 + * Lock the VI
  60 + * Set 1 means that VI is locked by THIS DD_Var and external program did not set LockFile yet
  61 + *=====================================================*/
  62 + DD_Var->VILocked = 1;
  63 + gettimeofday(&tv,&tz);
  64 + memcpy(&(DD_Var->LockStartTime),&(tv.tv_sec),sizeof(time_t));
  65 +
  66 + strcpy(StartISO,Double2ISOTime(Start));
  67 + strcpy(StopISO,Double2ISOTime(Stop));
  68 + sprintf(Command,GETNEWDATACALL,getenv("DDBASEBIN"),DD_Var->BaseName,DD_Var->RemSetID,DD_Var->path,StartISO,StopISO);
  69 + if(Verbose) fprintf(stderr, "DoRequest(): Command = %s\n", Command);
  70 + err = system(Command);
  71 +
  72 + switch(err)
  73 + {
  74 + case 0: return OK;
  75 + case NOPHP: return NOEXEC;
  76 + case NOSCRIPT: return NOEXEC;
  77 + default: return NOEXEC;
  78 + }
  79 +
  80 + return NOEXEC;
  81 + }
  82 +
  83 +/*======================================================================
  84 + * ExtDataRequest
  85 + * Return folowing values:
  86 + * OK - request is accepted SERVER has to wait when LOCK file is gone
  87 + * NOEXEC - error in external executable
  88 + * NODATAATTIME - time corresponds to the NODATA interval
  89 + * GAPISSMALL - Time is inside too small gap
  90 + *======================================================================*/
  91 + int ExtDataRequest(DD_Var_t *DD_Var, double CTime)
  92 + {
  93 + size_t Rmin,Rmax;
  94 + static size_t start[2] = {0,0};
  95 + static size_t TimeCount[2] = {1,TIMELENGTH};
  96 + char StartTime[TIMELENGTH];
  97 + char StopTime[TIMELENGTH];
  98 + double DStart, DStop;
  99 + int SearchResult, More, status;
  100 +
  101 + if(Verbose) fprintf(stderr,"ExtDataRequest: Rmin,Rmax = %d %d, CTime = %f\n",DD_Var->CurrRmin,DD_Var->CurrRmax, CTime);
  102 +
  103 + /*
  104 + * Search if there is an emtpy space ...
  105 + */
  106 + if(DD_Var->CurrRmin >= 0) Rmin = (size_t)DD_Var->CurrRmin; else Rmin = 0;
  107 + if(DD_Var->CurrRmax >= 0) Rmax = (size_t)DD_Var->CurrRmax; else Rmax = DD_Var->MaxTimeRecNum - 1;
  108 +
  109 + if(Verbose) fprintf(stderr,"ExtDataRequest: CTime = %s\n",Double2DD_Time(CTime));
  110 + /*
  111 + * No yet Records in times.nc
  112 + */
  113 + if (Rmax == -1) {
  114 +
  115 + DStart = CTime - REQTIMEINT;
  116 + DStop = CTime + REQTIMEINT;
  117 + if(DStart > DD_Var->GlobalStop)
  118 + {
  119 + if(Verbose) fprintf(stderr, "ExtDataRequest: Request exceeds the global stop\n");
  120 + return OUTOFTIME;
  121 + }
  122 + if(DStop < DD_Var->GlobalStart)
  123 + {
  124 + if(Verbose) fprintf(stderr, "ExtDataRequest: Request is less than global start\n");
  125 + return OUTOFTIME;
  126 + }
  127 + return DoRequest(DD_Var, DStart, DStop);
  128 +
  129 + }
  130 +
  131 + More = 1;
  132 + while(More)
  133 + {
  134 + start[0] = (Rmin + Rmax)/2;
  135 +
  136 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime);
  137 + DStart = DD_Time2Double(StartTime);
  138 +
  139 + if(CTime > DStart)
  140 + {
  141 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime);
  142 + DStop = DD_Time2Double(StopTime);
  143 + if(DStop >= CTime) /* This is really INSIDE NODATA */
  144 + {
  145 + DD_Var->TimeRecNumber = start[0];
  146 + More = 0;
  147 + return NODATAATTIME;
  148 + }
  149 + else /* Try interval at the right */
  150 + {
  151 + if(start[0] >= DD_Var->MaxTimeRecNum - 1) /* It was the last record */
  152 + {
  153 + More = 0;
  154 + DD_Var->TimeRecNumber = DD_Var->MaxTimeRecNum - 1;
  155 + SearchResult = DATAATLEFT; /* We are on the right of all records */
  156 +
  157 + }
  158 + else
  159 + {
  160 + if(Verbose) fprintf(stderr,"ExtDataRequest: We have to move to %d record, CTime = %s\n", start[0]+1,Double2DD_Time(CTime));
  161 + start[0]++;
  162 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime);
  163 + DStart = DD_Time2Double(StartTime);
  164 + if(DStart >= CTime) /* No data interval is at the RIGHT */
  165 + {
  166 + DD_Var->TimeRecNumber = start[0];
  167 + More = 0;
  168 + SearchResult = DATAATRIGHT;
  169 + }
  170 + else
  171 + {
  172 + Rmin = start[0];
  173 + if(Rmax <= Rmin) Rmax = Rmin;
  174 + More = 1;
  175 + }
  176 + } /* else start[0] >= maximal */
  177 + } /* else of TestTime >= CTime */
  178 +
  179 + } /*(CTime > DStart) */
  180 + else /* StartTime(R) > CTime */
  181 + {
  182 + if(start[0] <= 0) /* CTime is on the left from the first interval */
  183 + {
  184 + More = 0;
  185 + DD_Var->TimeRecNumber = 0;
  186 + SearchResult = DATAATRIGHT;
  187 + }
  188 + else
  189 + {
  190 + start[0]--; /* Try interval at the left */
  191 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime);
  192 + DStop = DD_Time2Double(StopTime);
  193 + if(CTime > DStop) /* Correct interval is on the right */
  194 + {
  195 + DD_Var->TimeRecNumber = start[0] + 1;
  196 + More = 0;
  197 + SearchResult = DATAATRIGHT;
  198 + }
  199 + else
  200 + {
  201 + Rmax = start[0];
  202 + More =1;
  203 + }
  204 + }
  205 + }
  206 + } /* while(More) */
  207 +
  208 + /*
  209 + * Probably we at the left or at the right of interval
  210 + */
  211 + if(SearchResult == DATAATLEFT) // Data are on the left of requested data
  212 + {
  213 + start[0] = DD_Var->TimeRecNumber;
  214 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime);
  215 + DStart = DD_Time2Double(StopTime); // Left boundary
  216 + if((CTime - DStart) > REQTIMEINT) DStart = CTime - REQTIMEINT;
  217 + DStop = CTime + REQTIMEINT;
  218 + if(DStart >= DD_Var->GlobalStop)
  219 + {
  220 + if(Verbose) fprintf(stderr, "ExtDataRequest: Request exceeds the global stop\n");
  221 + return OUTOFTIME;
  222 + }
  223 + return DoRequest(DD_Var, DStart, DStop);
  224 + }
  225 +
  226 + if(DD_Var->TimeRecNumber == 0) // All data is on the right
  227 + {
  228 + start[0] = DD_Var->TimeRecNumber;
  229 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime);
  230 + DStop = DD_Time2Double(StartTime); /* Right boundary */
  231 + if((DStop - CTime) > REQTIMEINT) DStop = CTime + REQTIMEINT;
  232 + DStart = CTime - REQTIMEINT;
  233 + if(DStop <= DD_Var->GlobalStart)
  234 + {
  235 + if(Verbose) fprintf(stderr, "ExtDataRequest: Request is less than global start\n");
  236 + return OUTOFTIME;
  237 + }
  238 + return DoRequest(DD_Var, DStart, DStop);
  239 + }
  240 +
  241 + /*
  242 + * Now we are between two records
  243 + * We have to check if the gap is big enough
  244 + */
  245 + start[0] = DD_Var->TimeRecNumber;
  246 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime);
  247 + DStop = DD_Time2Double(StartTime); /* GAP! */
  248 +
  249 + start[0]--;
  250 + status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime);
  251 + DStart = DD_Time2Double(StopTime); /* GAP! */
  252 +
  253 +
  254 + if((DStop - DStart) < DD_Var->MinGap) return GAPISSMALL;
  255 +
  256 +
  257 + if((CTime - DStart) > REQTIMEINT) DStart = CTime - REQTIMEINT;
  258 + if((DStop - CTime) > REQTIMEINT) DStop = CTime + REQTIMEINT;
  259 + /*
  260 + if(Verbose)
  261 + {
  262 + fprintf(stderr,"DStart-GlobalStart = %f\n",DStart - DD_Var->GlobalStart);
  263 + fprintf(stderr,"DStop-GlobalStop = %f\n",DStop - DD_Var->GlobalStop);
  264 + }
  265 + if((DStop > DD_Var->GlobalStop) || (DStart < DD_Var->GlobalStart)) return OUTOFTIME;
  266 + */
  267 + return DoRequest(DD_Var, DStart, DStop);
  268 + }
  269 +
  270 +/*======================================================================
  271 + * IsTimesLocked
  272 + * Return 1 if there is LOCK in the VI directory or if the corresponding flag in DD_Var is UP
  273 + *======================================================================*/
  274 + int IsTimesLocked(DD_Var_t *DD_VarL)
  275 + {
  276 + int status;
  277 + char FullPath[PATHLENGTH];
  278 + struct timeval tv;
  279 + struct timezone tz;
  280 +
  281 +
  282 + strcpy(FullPath,DD_VarL->path);
  283 + strcat(FullPath,DIRLOCK);
  284 + status = access(FullPath, F_OK); /* negative if there is no file */
  285 + switch(DD_VarL->VILocked)
  286 + {
  287 + case 0: if(status < 0) return NOLOCK; /* NO LOCK */
  288 + else {DD_VarL->VILocked = 2; return LOCKED;} /* LOCK was made by another server */
  289 + break;
  290 + case 1: if(status < 0) /* LOCK was made by THIS server, PHP is not ready yet OR already removed(!)*/
  291 + {
  292 + gettimeofday(&tv,&tz);
  293 + if(difftime(tv.tv_sec,DD_VarL->LockStartTime) > 1.5)
  294 + {DD_VarL->VILocked = 0; return LOCKREMOVED;} /* PHP alreadyremoved LOCK */
  295 + else return LOCKED;
  296 + }
  297 + else {DD_VarL->VILocked = 2; return LOCKED;} /* Now even PHP setup LOCK */
  298 + break;
  299 + case 2: if(status < 0) {DD_VarL->VILocked = 0; return LOCKREMOVED;} /* PHP removed LOCK */
  300 + else return LOCKED; /*Keep LOCK condition */
  301 + }
  302 + }
  303 +/*=============================================================================================*/
... ...
src/SERVER/UpdateTimeInfo.c 0 → 100644
  1 +++ a/src/SERVER/UpdateTimeInfo.c
... ... @@ -0,0 +1,185 @@
  1 +/*=====================================================================
  2 + * DD SYSTEM base package
  3 + * DD_Server library
  4 + * UpdateTimeInfo.c
  5 + * V.1.1
  6 + * Functions to updete time constant in the DD_Var structure and
  7 + * auxial functions to search in the "times" file.
  8 + *
  9 + * Versions:
  10 + * Sep 20, 2007, V.1.0, Fedorov
  11 + * Sep 23, 2007, V.1.1, Fedorov, SHARE MODE
  12 + *=====================================================================*/
  13 +
  14 +#include <netcdf.h>
  15 +#include "DD.h"
  16 +#include "DD_comm.h"
  17 +
  18 +extern int Verbose;
  19 +/*---------------------------------------------------------
  20 + * SearchRight()
  21 + *---------------------------------------------------------*/
  22 +int SearchRight(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax)
  23 +{
  24 + static size_t start[2] = {0,0};
  25 + static size_t TimeCount[2] = {1,TIMELENGTH};
  26 + static size_t FileCount[2] = {1,MAXFILENAME};
  27 + char TimeIntName[MAXSETLENGTH]; /* File name associated with the given time interval */
  28 + int NoDataFlag;
  29 + int status;
  30 +
  31 + start[0] = DD_VarL->TimeRecNumber;
  32 +
  33 + NoDataFlag = 1;
  34 + while(NoDataFlag)
  35 + {
  36 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->NameID,start,FileCount,TimeIntName);
  37 + if(strcmp(TimeIntName,NODATASTR) == 0) /* No data for this time interval */
  38 + {
  39 + start[0]++; /* Go right */
  40 + if(start[0] > Rmax) return REACHRIGHT; /* End of alowed interval is reached */
  41 + }
  42 + else
  43 + {
  44 + DD_VarL->TimeRecNumber = start[0];
  45 + NoDataFlag = 0;
  46 + }
  47 + }
  48 + return OKRIGHT;
  49 +}
  50 +
  51 +/*---------------------------------------------------------
  52 + * SearchLeft()
  53 + *---------------------------------------------------------*/
  54 +int SearchLeft(DD_Var_t *DD_VarL, size_t Rmin, size_t Rmax)
  55 +{
  56 + static size_t start[2] = {0,0};
  57 + static size_t TimeCount[2] = {1,TIMELENGTH};
  58 + static size_t FileCount[2] = {1,MAXFILENAME};
  59 + char TimeIntName[MAXSETLENGTH]; /* File name associated with the given time interval */
  60 + int NoDataFlag;
  61 + int status;
  62 +
  63 + start[0] = DD_VarL->TimeRecNumber;
  64 +
  65 + NoDataFlag = 1;
  66 + while(NoDataFlag)
  67 + {
  68 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->NameID,start,FileCount,TimeIntName);
  69 + if(strcmp(TimeIntName,NODATASTR) == 0) /* No data for this time interval */
  70 + {
  71 + if(start[0] > 0) start[0]--; else return REACHLEFT; /* Go left */
  72 + if(start[0] < Rmin) return REACHLEFT; /* End of alowed interval is reached */
  73 + }
  74 + else
  75 + {
  76 + DD_VarL->TimeRecNumber = start[0];
  77 + NoDataFlag = 0;
  78 + }
  79 + }
  80 + return OKLEFT;
  81 +}
  82 +/*-----------------------------------------------------------------*/
  83 +
  84 +/*---------------------------------------------------------
  85 + * UpdateTimeInfo()
  86 + *---------------------------------------------------------*/
  87 +int UpdateTimeInfo(DD_Var_t *DD_VarL)
  88 +{
  89 + static char StartName[] = "StartTime";
  90 + static char StopName[] = "StopTime";
  91 + static char FileName[] = "FileName"; /* Variable IDs */
  92 + static char RecDimName[] = "record";
  93 + static int RecDimID;
  94 + static size_t start[2] = {0,0};
  95 + static size_t TimeCount[2] = {1,TIMELENGTH};
  96 + char TimeS[TIMELENGTH];
  97 + size_t Rmin,Rmax;
  98 + int SearchStatus;
  99 + int status;
  100 + /*---- Close file if it is open ---------------------------*/
  101 + if(DD_VarL->tmID > -1) status = nc_close(DD_VarL->tmID);
  102 +
  103 + if(Verbose) fprintf(stderr,"UpdateTimeInfo(%s): Start\n",DD_VarL->TimesFileName);
  104 +
  105 + /*---- Reopen times file ----------------------------------*/
  106 + status = nc_open(DD_VarL->TimesFileName, NC_NOWRITE|NC_SHARE,&(DD_VarL->tmID));
  107 + if(status != NC_NOERR)
  108 + {
  109 + if(Verbose) fprintf(stderr,"UpdateTimeInfo(%s): open file: message: %s\n",DD_VarL->TimesFileName,nc_strerror(status));
  110 + return(NOTIMESFILE);
  111 + }
  112 + /*
  113 + * Init corresponding constants
  114 + */
  115 + status = nc_inq_varid(DD_VarL->tmID,FileName, &(DD_VarL->NameID));
  116 + status = nc_inq_varid(DD_VarL->tmID,StartName,&(DD_VarL->StartID));
  117 + status = nc_inq_varid(DD_VarL->tmID,StopName, &(DD_VarL->StopID));
  118 + if (status != NC_NOERR)
  119 + {
  120 + if(Verbose) fprintf(stderr,"UpdateTimeInfo(%s): Get parameters times file %s\n",DD_VarL->TimesFileName,nc_strerror(status));
  121 + return(NOTIMESFILE);
  122 + }
  123 +
  124 + /* Get MaxRecord Number */
  125 + status = nc_inq_dimid(DD_VarL->tmID,RecDimName, &RecDimID);
  126 + if (status != NC_NOERR)
  127 + {
  128 + if(Verbose) fprintf(stderr,"UpdateTimeInfo(%s): Get Max records in Times file %s\n",DD_VarL->TimesFileName,nc_strerror(status));
  129 + return(NOTIMESFILE);
  130 + }
  131 + status = nc_inq_dimlen(DD_VarL->tmID,RecDimID, &(DD_VarL->MaxTimeRecNum));
  132 +
  133 +/* -----------------------------------------------------------------
  134 + * Search the extreme left and right valid intervals
  135 + * -----------------------------------------------------------------*/
  136 + Rmin = 0; Rmax = DD_VarL->MaxTimeRecNum - 1;
  137 + DD_VarL->TimeRecNumber = 0;
  138 + switch(SearchRight(DD_VarL,Rmin,Rmax))
  139 + {
  140 + case REACHRIGHT: SearchStatus = NOONEDATA;
  141 + DD_VarL->RValidMin = -1;
  142 + DD_VarL->RValidMax = -1;
  143 + DD_VarL->MinValidTime = -1.0;
  144 + break;
  145 + case OKRIGHT: DD_VarL->RValidMin = DD_VarL->TimeRecNumber;SearchStatus = IDLE;
  146 + }
  147 +
  148 + if(SearchStatus != NOONEDATA) /* Ther is something in the right */
  149 + {
  150 + DD_VarL->TimeRecNumber = Rmax;
  151 + switch(SearchLeft(DD_VarL,Rmin,Rmax))
  152 + {
  153 + case REACHLEFT: DD_VarL->RValidMin = -1;
  154 + DD_VarL->RValidMax = -1;
  155 + DD_VarL->MaxValidTime = -1.0;
  156 + break; /* Impossible */
  157 + case OKLEFT: DD_VarL->RValidMax = (int)DD_VarL->TimeRecNumber;
  158 + }
  159 + }
  160 +
  161 + /*------ Define min and max valid times ------------------------*/
  162 + if(DD_VarL->RValidMin >= 0)
  163 + {
  164 + start[0] = (size_t)DD_VarL->RValidMin;
  165 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StartID,start,TimeCount,TimeS);
  166 + DD_VarL->MinValidTime = DD_Time2Double(TimeS);
  167 + }
  168 + else DD_VarL->MinValidTime = -1.0;
  169 + if(DD_VarL->RValidMax >= 0)
  170 + {
  171 + start[0] = (size_t)DD_VarL->RValidMax;
  172 + status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,TimeS);
  173 + DD_VarL->MaxValidTime = DD_Time2Double(TimeS);
  174 + }
  175 + else DD_VarL->MaxValidTime = -1.0;
  176 +
  177 +
  178 + /*------- Init other values ------------------------------------*/
  179 + DD_VarL->CurrRmin = -1;
  180 + DD_VarL->CurrRmax = -1;
  181 + /*-----------------------------------------------------------------------*/
  182 + if(Verbose) fprintf(stderr,"UpdateTimeInfo(%s): OK\n",DD_VarL->TimesFileName);
  183 + return OK;
  184 +}
  185 +/*====================================================================================*/
... ...
src/SERVER/ncfileop.c 0 → 100755
  1 +++ a/src/SERVER/ncfileop.c
... ... @@ -0,0 +1,498 @@
  1 +/*=====================================================================
  2 + * DD SYSTEM base package
  3 + * DD_Server library
  4 + * ncfileop.c
  5 + * V.6.7
  6 + * Last revision:
  7 + * Oct 24, 2002 New calculation of the maximum record size V 4.1
  8 + * work with NC files is now in file ncfileop.c
  9 + * Nov 19, 2004 Bug in the cach operation.
  10 + * Aug 16, 2005 Cach improved
  11 + * Mar 15, 2007 V.4.7 Some errors with cash
  12 + * Jul 10, 2007 V.5.0 According to Server protocol 4.5.1 Call external database if need.
  13 + * If "times" has "NODATA" string as name of the file, return "NOTIME"
  14 + * Sep 22, 2007 V.6.0 New approach. It tries to get new data between two files
  15 + * Sep 25, 2007 V.6.1 Variable Minimal Gap
  16 + * May 06, 2008 V.6.2 Fedorov, Max Records number processing
  17 + * May 12, 2008 V.6.3 Fedorov, In Max Records error in malloc sizeof(int *)!!! important for 64
  18 + * May 15, 2008 V.6.4 Fedorov, NoData interval processing. Just go to the next correct data interval.
  19 + * Apr 08, 2009 V.6.5 Fedorov, Unziped files can be touched by groupe
  20 + * Apr 14, 2009 V.6.6 Fedorov, nc_sync
  21 + * Feb 02, 2010 V.6.7 Lena, wait to remove an old file in the cache
  22 + *======================================================================*/
  23 +#include <netcdf.h>
  24 +#include "DD.h"
  25 +#include "DD_comm.h"
  26 +
  27 +/*------------------ GLOBAL VARIABLES --------------------------*/
  28 +extern int Verbose;
  29 +
  30 +/*=============================================================
  31 + * CloseOldFile
  32 + *===========================================================*/
  33 +int CloseOldFile(DD_Var_t *D)
  34 +{
  35 + size_t CashStart[2] = {0L,0L};
  36 + size_t CashCount[2] = {1L,MAXFILENAME};
  37 + int status;
  38 +
  39 + if(D->Maxnc_rec > 0)
  40 + {
  41 + status = nc_close(D->ncID);
  42 + if(status < 0)
  43 + {
  44 + D->LastFileStatus = DATAFILEERR;
  45 + if(Verbose) fprintf(stderr,"CloseOldFile: file %s, error while closed\n",&(D->Cash.names[D->CurrCushN][0]),D->CurrCushN);
  46 + return DATAFILEERR;
  47 + }
  48 + if(Verbose) fprintf(stderr,"CloseOldFile: file %s, %d closed\n",&(D->Cash.names[D->CurrCushN][0]),D->CurrCushN);
  49 + D->CurrCushN = -1;
  50 + D->Maxnc_rec = 0;
  51 + }
  52 + else if(Verbose) fprintf(stderr,"CloseOldFile: Nothing To close\n");
  53 +
  54 + return 1;
  55 +}
  56 +
  57 +/*##############################################################*/
  58 +/*-----------------------SETNEWFILE-----------------------------*/
  59 +/*##############################################################*/
  60 +
  61 +int SetNewFile(DD_Var_t *D, int N)
  62 +/*
  63 + * Function tries to get new data for the gap beetween files, or just
  64 + * open a new data file according to offset N referring to current position in the times file.
  65 + * The current position changed if file is succesefully open.
  66 + * Return values:
  67 + * OK
  68 + * OUTOFTIME - next interval exceeeds GlobalStart/Stop
  69 + * TIMEINEMPTY - next interval marked as "NODATA"
  70 + * TRYAGAIN - the VI is blocked while new data is arriving
  71 + * WAITEXTCALL - new data is requested
  72 + * CACHTOOREC - now free space in the CACH
  73 + * CHACHERR - unrecovable error in CACH
  74 + * DATAFILEERR - unrecovable error in data file
  75 + *----------------------------------------------------------------
  76 + * At the entry we are assuming that VI is not locked!
  77 + */
  78 +{
  79 + static char TimeDimName[] = "Time";
  80 + static size_t CashStart[2] = {0L,0L};
  81 + static size_t CashCount[2] = {1L,MAXFILENAME};
  82 + static size_t TimeCount[2] = {1,TIMELENGTH};
  83 +
  84 + char Name[MAXFILENAME]; /* Name of data nc file */
  85 + char FullName[PATHLENGTH]; /* Full name of nc file */
  86 + char StartTime[TIMELENGTH];
  87 + char StopTime[TIMELENGTH];
  88 + static int NameID,TimeDimID; /* NC variables ID for Times file */
  89 + static size_t start[2] = {0,0}; /* NV start array */
  90 + static size_t FileCount[2] = {1,MAXFILENAME}; /* NC count array for Times file */
  91 + static size_t DimArray[NC_MAX_DIMS]; /* NC_MAX_DIMS is in netcdf.h */
  92 + static int DimIDArray[NC_MAX_DIMS];
  93 + size_t TestNumber; /* To test the new file number */
  94 + int FileNumber, Find, OldestNumber, NewAttempt;
  95 + char command[300];
  96 + int dltt;
  97 + int status;
  98 + time_t CurrentTime;
  99 + double FirstTime, LastTime;
  100 + int More;
  101 +
  102 +/*--------------- Calculate the next file to open ---------------*/
  103 + TestNumber = D->TimeRecNumber + N;
  104 + if(Verbose) fprintf(stderr,"SetNewFile(): Record %d\n",TestNumber);
  105 +
  106 + D->TimeRecNumber = TestNumber;
  107 + start[0] = TestNumber;
  108 +
  109 +/*----------------------------------------------------------------*
  110 + * Some test and call external archive we have to make only if N > 0
  111 + * Otherwise we just reopen existing file
  112 + *----------------------------------------------------------------*/
  113 + if(N > 0)
  114 + {
  115 + if(TestNumber > D->RValidMax) /* Out of existing data files */
  116 + {
  117 + if(Verbose) fprintf(stderr,"SetNewFile(): TestNumber %d exides D->RValidMax %d\n",TestNumber,D->RValidMax);
  118 +
  119 + if(D->ExtCallAllowed)
  120 + {
  121 + More = 1;
  122 + while(More)
  123 + {
  124 + switch(status = ExtDataRequest(D, D->CDTime+D->MinGap))
  125 + {
  126 + case OK: return WAITEXTCALL;
  127 + case NODATAATTIME: /* The last files in the data base are only NODATA, let us try again with StopTime of TestNumber */
  128 + start[0] = TestNumber;
  129 + status = nc_get_vara_text(D->tmID, D->StopID,start,TimeCount,StopTime);
  130 + D->CDTime = DD_Time2Double(StopTime) + 0.001;
  131 + if(Verbose) fprintf(stderr,"SetNewFile(): We found no data, Let us try another CDTime = %s\n",Double2DD_Time(D->CDTime));
  132 + More = 1;
  133 + break;
  134 + case GAPISSMALL: return TIMEINEMPTY; break;
  135 + case OUTOFTIME: return OUTOFTIME; break;
  136 + default: return DATAFILEERR;
  137 + }
  138 + }
  139 + } else return OUTOFTIME;
  140 + }
  141 + }
  142 +
  143 + /*--------------- Get File Name and start Time ---------------------*/
  144 + status = nc_get_vara_text(D->tmID,D->NameID,start,FileCount,Name);
  145 + status = nc_get_vara_text(D->tmID, D->StartID,start,TimeCount,StartTime);
  146 + if(status != NC_NOERR)
  147 + {
  148 + if(Verbose) fprintf(stderr,"SetNewFile(): Get File Name and StartTime %s\n",nc_strerror(status));
  149 + D->LastFileStatus = DATAFILEERR;
  150 + return DATAFILEERR;
  151 + }
  152 + FirstTime = DD_Time2Double(StartTime);
  153 +
  154 + if(N > 0)
  155 + {
  156 + if(strncmp(Name,"NODATA",6) == 0) /* Next record marked as NODATA */
  157 + {
  158 + if(D->ExtCallAllowed && (FirstTime - D->CDTime > D->MinGap)) /* Try to fill the gap between the data
  159 + * and NODATA segment if there is enough gap
  160 + */
  161 + {
  162 + if(Verbose) fprintf(stderr,"SetNewFile(): There is a gap %d\n",FirstTime - D->CDTime);
  163 + switch(status = ExtDataRequest(D, D->CDTime+D->MinGap))
  164 + {
  165 + case OK: return WAITEXTCALL;
  166 + case NODATAATTIME:
  167 + case GAPISSMALL: return TIMEINEMPTY; break;
  168 + case OUTOFTIME: return OUTOFTIME; break;
  169 + default: return DATAFILEERR;
  170 + }
  171 + }
  172 + else /* Gap to NODATA interval is too small and we wiil try next time interval */
  173 + {
  174 + if(Verbose) fprintf(stderr,"SetNewFile(): Next File is NODATA, try file %d\n",++TestNumber);
  175 + status = nc_get_vara_text(D->tmID, D->StopID,start,TimeCount,StopTime);
  176 + D->CDTime = DD_Time2Double(StopTime);
  177 +
  178 + switch( status = SetNewFile(D,1) )
  179 + {
  180 + case OK: return OK;
  181 + case WAITEXTCALL: return WAITEXTCALL;
  182 + case TIMEINEMPTY: return TIMEINEMPTY;
  183 + case OUTOFTIME: return OUTOFTIME;
  184 + case CACHERR: return CACHERR;
  185 + default: return DATAFILEERR;
  186 + }
  187 + }
  188 +
  189 + }
  190 + else /* Next record is valid */
  191 + {
  192 +// sleep(40);
  193 + if(D->ExtCallAllowed && ((FirstTime - D->CDTime) > D->MinGap))
  194 + {
  195 + if(Verbose) fprintf(stderr,"SetNewFile(): File OK, but there is a gap %d %d\n",FirstTime - D->CDTime, D->MinGap);
  196 + switch(status = ExtDataRequest(D, D->CDTime+D->MinGap))
  197 + {
  198 + case OK: return WAITEXTCALL;
  199 + case NODATAATTIME:
  200 + case GAPISSMALL: return TIMEINEMPTY; break;
  201 + case OUTOFTIME: return OUTOFTIME; break;
  202 + default: return DATAFILEERR;
  203 + }
  204 + } /* else just continue */
  205 + }
  206 + }
  207 +
  208 +/*-------------- refresh the Cache table ---------------------------*/
  209 + status = nc_sync(D->Cash.ID);
  210 + if(status != NC_NOERR)
  211 + {
  212 + if(Verbose) fprintf(stderr,"SetNewFile(): Cache Synchro: %s\n",nc_strerror(status));
  213 + return CACHERR;
  214 + }
  215 + for(CashStart[0] = 0; CashStart[0] < CASHLEN; CashStart[0]++)
  216 + {
  217 + status = nc_get_vara_text(D->Cash.ID, D->Cash.nameID,CashStart,CashCount,D->Cash.names[CashStart[0]]);
  218 + if(status != NC_NOERR)
  219 + {
  220 + if(Verbose) fprintf(stderr,"SetNewFile(): Cache Names: %s\n",nc_strerror(status));
  221 + D->LastFileStatus = CACHERR;
  222 + return CACHERR;
  223 + }
  224 + status = nc_get_vara_long(D->Cash.ID, D->Cash.timeID,CashStart,CashCount,&(D->Cash.times[CashStart[0]]));
  225 + if(status != NC_NOERR)
  226 + {
  227 + if(Verbose) fprintf(stderr,"SetNewFile(): Cache Times %s\n",nc_strerror(status));
  228 + D->LastFileStatus = CACHERR;
  229 + return CACHERR;
  230 + }
  231 + }
  232 +
  233 +/*----------- Close the old file ----------------------*/
  234 + if((status = CloseOldFile(D)) < 0) return DATAFILEERR;
  235 +
  236 + strcpy(FullName,D->path);
  237 + strcpy(FullName+strlen(D->path), Name);
  238 +// if(Verbose) fprintf(stderr,"SetNewFile(): New file to open: %s\n",FullName);
  239 +
  240 + NewAttempt = 0;
  241 +
  242 + while (NewAttempt < 3)
  243 + {
  244 + /*----- Search the new requested file in the cache and the oldest file ----------*/
  245 + FileNumber = 0;
  246 + CurrentTime = time(NULL); Find = 0; OldestNumber = -1;
  247 +
  248 + while((FileNumber < CASHLEN) && // Cache is finished
  249 + ((Find = strcmp(&(D->Cash.names[FileNumber][0]),Name)) != 0) && // File is already in the Cache
  250 + (D->Cash.names[FileNumber][0] != ' ')) // There is empty space
  251 + {
  252 + if((D->Cash.times[FileNumber] < (CurrentTime - FILEACCMARG) ) && (OldestNumber == -1)) OldestNumber = FileNumber;
  253 + dltt = (int)(D->Cash.times[OldestNumber] - D->Cash.times[FileNumber]);
  254 + if(dltt > 0) OldestNumber = FileNumber;
  255 + FileNumber++;
  256 + }
  257 +
  258 + /* ====================================================
  259 + * Sometimes it is possible, that:
  260 + * 1) No corresponding file in the cache (Find != 0)
  261 + * 2) The oldest file is not found (OldestNumber == -1)
  262 + * 3) cach is full (FileNumber == CASHLEN)
  263 + * Then we need to repeat the search after one sec delay
  264 + *==================================================== */
  265 + if((Find != 0) && (FileNumber == CASHLEN) && (OldestNumber == -1))
  266 + {
  267 + NewAttempt++;
  268 + sleep((unsigned )(FILEACCMARG));
  269 +
  270 + if (Verbose)
  271 + fprintf(stderr,"Waiting %d secs to get the Oldest File\n", FILEACCMARG);
  272 +
  273 + } else NewAttempt = 3;
  274 + }
  275 +
  276 +//---------- Parsing resultat of search -------------
  277 +// if(Verbose)
  278 +// {
  279 +// if(OldestNumber > -1) fprintf(stderr,"SetNewFile(): Search: Is Oldest File %d %d %d\n", OldestNumber,D->Cash.times[OldestNumber],CurrentTime);
  280 +// else fprintf(stderr,"SetNewFile(): Search: No Oldest File %d %d\n", OldestNumber,CurrentTime);
  281 +// }
  282 +
  283 + if(Find != 0)
  284 +/*---------------- No request file in the CACHE ----------------------*/
  285 + {
  286 + if(FileNumber < CASHLEN)
  287 + {
  288 + if(D->Cash.names[FileNumber][0] == ' ') /* There is empty space in the table */
  289 + {
  290 + strcpy(command, "gunzip -c ");
  291 + strcat(command, FullName);
  292 + strcat(command, ".gz > ");
  293 + strcat(command, FullName);
  294 + system(command); /* File is unzipped */
  295 + sprintf(command, "chmod g+w %s\0",FullName);
  296 + system(command); /* File is unzipped */
  297 +
  298 + strcpy(&(D->Cash.names[FileNumber][0]),Name);
  299 + D->Cash.times[FileNumber] = CurrentTime;
  300 + CashStart[0] = FileNumber;
  301 + D->CurrCushN = FileNumber;
  302 + }
  303 + else
  304 + {
  305 + D->LastFileStatus = CACHERR;
  306 + return CACHERR; /* Unrecoverable error */
  307 + }
  308 + }
  309 + else /* No empty space. It is necessury to remove one file */
  310 + {
  311 + if (OldestNumber > -1) //------ Oldest file is found -------
  312 + {
  313 + strcpy(command, "gunzip -c ");
  314 + strcat(command, FullName);
  315 + strcat(command, ".gz > ");
  316 + strcat(command, FullName);
  317 + system(command); /* File is unzipped */
  318 + sprintf(command, "chmod g+w %s\0",FullName);
  319 + system(command); /* File is unzipped */
  320 +
  321 + strcpy(command, "rm ");
  322 + strcat(command,D->path);
  323 + strcat(command,&(D->Cash.names[OldestNumber][0]));
  324 + strcat(command, " &");
  325 + system(command); /* Old file removed */
  326 + strcpy(&(D->Cash.names[OldestNumber][0]),Name);
  327 + D->Cash.times[OldestNumber] = CurrentTime;
  328 + CashStart[0] = OldestNumber;
  329 + D->CurrCushN = OldestNumber;
  330 + }
  331 + else {
  332 + if(Verbose) fprintf(stderr,"SetNewFile(): return CACHTOOREC\n");
  333 + D->LastFileStatus = CACHTOOREC;
  334 + D->TimeRecNumber -= N;
  335 + return CACHTOOREC; //----- Say client that all files are too new
  336 + }
  337 + }
  338 + /*------------ The place for new cache is found --------------*/
  339 + status = nc_put_vara_text(D->Cash.ID, D->Cash.nameID,CashStart,CashCount,&(D->Cash.names[CashStart[0]][0]));
  340 + status = nc_put_vara_long(D->Cash.ID, D->Cash.timeID,CashStart,CashCount,&(D->Cash.times[CashStart[0]]));
  341 + if(status != NC_NOERR)
  342 + {
  343 + if(Verbose) fprintf(stderr,"SetNewFile(): Write Name and Time to cash: %s\n",nc_strerror(status));
  344 + D->LastFileStatus = CACHERR;
  345 + return CACHERR;
  346 + }
  347 + status = nc_sync(D->Cash.ID);
  348 + }
  349 +//------------------ There is FILE already in the CACHE --------------
  350 + else /*------- The requested file is already in the cache just refresh the time */
  351 + {
  352 + CashStart[0] = FileNumber;
  353 + D->Cash.times[FileNumber] = CurrentTime; /* refresh the time */
  354 + D->CurrCushN = FileNumber;
  355 + status = nc_put_vara_long(D->Cash.ID, D->Cash.timeID,CashStart,CashCount,&(D->Cash.times[CashStart[0]]));
  356 + if(status != NC_NOERR)
  357 + {
  358 + if(Verbose) fprintf(stderr,"SetNewFile(): File In Cache: %s\n",nc_strerror(status));
  359 + D->LastFileStatus = CACHERR;
  360 + return CACHERR;
  361 + }
  362 + status = nc_sync(D->Cash.ID);
  363 + }
  364 +
  365 +// if(Verbose) fprintf(stderr,"SetNewFile(): file %s, %d to be open\n",FullName,D->CurrCushN);
  366 +
  367 +
  368 +/*--------------- CACHE refreshed and requested file is unzipped ------------------------*/
  369 +/*----------------- Open requested file -----------------------------------------------*/
  370 +
  371 + status = nc_open(FullName,NC_NOWRITE,&(D->ncID));
  372 + if(status != NC_NOERR)
  373 + {
  374 + if(Verbose) fprintf(stderr,"SetNewFile(): Error while File Open: %s\n",nc_strerror(status));
  375 + D->LastFileStatus =DATAFILEERR ;
  376 + return DATAFILEERR;
  377 + }
  378 + if(Verbose) fprintf(stderr,"SetNewFile(): %s is open\n",FullName);
  379 +
  380 +/* Recover time dimension */
  381 + status = nc_inq_dimid(D->ncID,TimeDimName,&TimeDimID);
  382 + if(status != NC_NOERR)
  383 + {
  384 + if(Verbose) fprintf(stderr,"SetNewFile(): Get Time Dim: %s\n",nc_strerror(status));
  385 + D->LastFileStatus = DATAFILEERR;
  386 + return DATAFILEERR;
  387 + }
  388 + status = nc_inq_dimlen(D->ncID,TimeDimID,&(D->Maxnc_rec));
  389 + if(status != NC_NOERR)
  390 + {
  391 + if(Verbose) fprintf(stderr,"SetNewFile: GetFile Length: %s\n",nc_strerror(status));
  392 + D->LastFileStatus = DATAFILEERR;
  393 + return DATAFILEERR;
  394 + }
  395 +
  396 +/* Setup current position in the new open file */
  397 + if(N > 0) D->nc_rec = 0;
  398 + if(N < 0) D->nc_rec = D->Maxnc_rec-1;
  399 +
  400 + D->LastFileStatus = OK;
  401 + return OK;
  402 +}
  403 +/*------------------------------------------------------------------------------------*/
  404 +
  405 +/*----------------- VarSize -----------------------------------*/
  406 +int VarSize(nc_type type)
  407 +{
  408 + switch(type)
  409 + {
  410 + case NC_BYTE: return sizeof(char);
  411 + case NC_CHAR: return sizeof(char);
  412 + case NC_SHORT: return sizeof(short);
  413 + case NC_INT: return sizeof(int);
  414 + case NC_FLOAT: return sizeof(float);
  415 + case NC_DOUBLE: return sizeof(double);
  416 + default: return 1;
  417 + }
  418 +}
  419 +
  420 +/*##############################################################*/
  421 +/*----------------------- MaxRecord -----------------------------*/
  422 +/*##############################################################*/
  423 +
  424 +size_t MaxRecord(int ncID)
  425 +/* ncID - ID of already open NC file */
  426 +{
  427 + int timedimid; /* ID for dimension "Time" */
  428 +
  429 + int nvars;
  430 + int ndims;
  431 + int *ndims_arr; /* Array to keep number of dimensions of each variable */
  432 + size_t *dimleng_arr; /* Array to keep all length of dimensions */
  433 + nc_type *vartype_arr; /* Array to keep all types of variables */
  434 + int **dimid_arr; /* array of pointers to arrays of variable dimensions */
  435 +
  436 + int status; /* Error indicator */
  437 + int iv, id;
  438 + int cvarsize; /* size of variable */
  439 + int maxsize; /* maximal size */
  440 + int recordsize; /* size by units */
  441 + size_t RecordNumber;
  442 +
  443 + /*--- general information -------*/
  444 + status = nc_inq_ndims(ncID,&ndims);
  445 + status = nc_inq_nvars(ncID,&nvars);
  446 + status = nc_inq_unlimdim(ncID, &timedimid); /* What is unlimited dimension ID */
  447 +
  448 + /*---- memory allocation --------*/
  449 + dimleng_arr = (size_t *)malloc(ndims * sizeof(size_t));
  450 + vartype_arr = (nc_type *)malloc(nvars * sizeof(nc_type));
  451 + dimid_arr = (int **)malloc(nvars * sizeof(int *));
  452 + ndims_arr = (int *)malloc(nvars * sizeof(int));
  453 +
  454 + /* Length of each dimension */
  455 + for(id = 0; id < ndims; id++)
  456 + {
  457 + if(id == timedimid) dimleng_arr[id] = 1;
  458 + else status = nc_inq_dimlen(ncID, id, &(dimleng_arr[id]));
  459 + }
  460 +
  461 + /* type and dimension of each variable */
  462 + for(iv = 0; iv < nvars; iv++)
  463 + {
  464 + status = nc_inq_vartype(ncID,iv,&(vartype_arr[iv]));
  465 + status = nc_inq_varndims(ncID,iv,&(ndims_arr[iv]));
  466 + dimid_arr[iv] = (int *)malloc(ndims_arr[iv]*sizeof(int)); /* memory for dim ID array */
  467 + status = nc_inq_vardimid(ncID,iv,dimid_arr[iv]);
  468 + }
  469 +
  470 + /* calculation of size of variable and maximum size of variables */
  471 + maxsize = 0;
  472 + for(iv = 0; iv < nvars; iv++)
  473 + {
  474 + recordsize = 1;
  475 + for(id = 0; id < ndims_arr[iv]; id++)
  476 + recordsize *= dimleng_arr[(dimid_arr[iv])[id]];
  477 + cvarsize = recordsize * VarSize(vartype_arr[iv]);
  478 + if(cvarsize > maxsize) maxsize = cvarsize;
  479 + }
  480 +
  481 + /* calculation record number */
  482 + RecordNumber = (size_t)(MAXPACKSIZE / maxsize);
  483 + if(RecordNumber == 0)
  484 + {
  485 + if(Verbose) fprintf(stderr,"MaxRecord(%d): Error in calculation of records number,MAXPACKSIZE = %d, maxsize = %d\n",ncID,MAXPACKSIZE,maxsize);
  486 + }
  487 +
  488 + /* Free all */
  489 + for(iv = 0; iv < nvars; iv++) free(dimid_arr[iv]);
  490 + free(ndims_arr);
  491 + free(dimid_arr);
  492 + free(vartype_arr);
  493 + free(dimleng_arr);
  494 +
  495 + return RecordNumber;
  496 +}
  497 +/*----------------------------------------------------------------------*/
  498 +
... ...