Commit 4243d674e6ecf6047b63c98da0165ef74442d966
0 parents
Exists in
master
and in
10 other branches
First commit
Showing
20 changed files
with
5854 additions
and
0 deletions
Show diff stats
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) | |
... | ... |
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 | |
... | ... |
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 | +) | |
... | ... |
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 | + | |
... | ... |
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 | |
... | ... |
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) | |
... | ... |
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 -------------------------------*/ | |
... | ... |
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 | +/*=======================================================================*/ | |
... | ... |
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 | |
... | ... |
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 | + | |
... | ... |
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 | + | |
... | ... |
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 */ | |
... | ... |
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) | |
... | ... |
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 | + | |
... | ... |
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 | +/*######################################################################################*/ | |
... | ... |
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 | +} | |
... | ... |
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 | +/*=============================================================================================*/ | |
... | ... |
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 | +/*====================================================================================*/ | |
... | ... |
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 | + | |
... | ... |