1 /*
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name: suggsrv.c
27 *
28 * Author:  Yuri Sadykov
29 *
30 * Version Creation Date:   08/14/95
31 *
32 * $Revision: 6.1 $
33 *
34 * File Description:
35 *       Implementation of Suggest server. Here it is only server specific
36 *       part, mainly related with reading of requests from a client and writing
37 *       responces. The implementaion of the processing of data is in suggest.c
38 *       and adjust.c
39 *
40 * Modifications:
41 * --------------------------------------------------------------------------
42 * Date     Name        Description of modification
43 * -------  ----------  -----------------------------------------------------
44 *
45 * ==========================================================================
46 *
47 *
48 * RCS Modification History:
49 * $Log: suggsrv.c,v $
50 * Revision 6.1  2004/04/01 13:43:07  lavr
51 * Spell "occurred", "occurrence", and "occurring"
52 *
53 * Revision 6.0  1997/08/25 18:40:59  madden
54 * Revision changed to 6.0
55 *
56 * Revision 1.6  1996/07/09 21:40:29  epstein
57 * add kludge Nlm_Main() to allow program to be built with shared libs
58 *
59  * Revision 1.5  1995/12/12  18:52:54  kans
60  * now uses functions in suggslp.c
61  *
62  * Revision 1.4  1995/11/27  21:03:40  sad
63  * Fixed error related with initializing global structure;
64  *
65  * Fixed error while writing interval's fields from and to, which had
66  * values less then required;
67  *
68  * Added writing strand values in output intervals;
69  *
70  * Now all intervals with the same product are within single feature;
71  *
72 */
73 
74 #include <ncbinet.h>
75 #include <seqport.h>
76 #include <suggslp.h>
77 #include <suggen.h>
78 
79 /*****************************************************************************
80  * External function prototipes
81  */
82 
83 /*****************************************************************************
84  * Function prototipes
85  */
86 static Boolean
87 ServeClient(AsnIoPtr pAsnIn, AsnIoPtr pAsnOut);
88 
89 static SuggestErrorPtr
90 GetLastSuggestError(void);
91 
92 static MsgAnswer LIBCALLBACK
93 SuggestMessageHook(MsgKey msgKey, ErrSev errSev,
94                    const char *pchCaption, const char *pchMessage);
95 
96 static void
97 SetSuggestMessageHook(void);
98 
99 static void
100 RestoreMessageHook(void);
101 
102 static SuggestErrorPtr
103 GetLastSuggestError(void);
104 
105 static void
106 ClearSuggestError(void);
107 
108 /*============================================================================*\
109  * Function:
110  *      main
111  *
112  * Purpose:
113  *      Entry point. This function is for suggest if it is built as a server.
114  *
115  * Parameters:
116  *      Only one option to the application is acceptable "-d" which means that
117  * the application must running without network capability and input and output
118  * of data are through the local files. It's very convinient for debugging.
119  *
120  * Return:
121  *      Error code
122 \*----------------------------------------------------------------------------*/
123 int
main(int argc,char * argv[])124 main(int argc, char *argv[])
125 {
126     int         iArg;
127     int         iReadTimeout;
128     Boolean     bDebug = FALSE;
129     AsnIoPtr    pAsnIoIn;
130     AsnIoPtr    pAsnIoOut;
131     Char        achBuff[100];
132     NI_HandPtr  pHand;
133 
134     if (argc > 1) {
135         iArg = 1;
136         if (StrCmp(argv[1], "-d") == 0) {
137             iArg++;
138             bDebug = TRUE;
139         }
140     }
141 
142     if (bDebug) {
143         /* For debugging of the server only.
144          * Read and write local files only, no communication
145          * with clients.
146          */
147         pAsnIoIn = AsnIoOpen("suggsrv.in", "r");
148         pAsnIoOut = AsnIoOpen("suggsrv.out", "w");
149     } else {
150         /* Send acknowledgment--all right
151          */
152         NI_ServerACK();
153 
154         /* Create connection with client, i.e. input and output
155          */
156         pHand = NI_OpenASNIO();
157 
158         /* this read-timeout is effectively an idle timeout for
159          * the server process; the process will terminate upon
160          * read-timeout
161          */
162         GetAppParam("NCBI", "NET_SRV", "SERV_INACT_TIMER",
163                     "10", achBuff, sizeof(achBuff));
164         iReadTimeout = atoi(achBuff) * 60;      /* param is minutes */
165         MsgSetReadTimeout(pHand, iReadTimeout);
166         pAsnIoIn = pHand->raip;
167         pAsnIoOut = pHand->waip;
168     }
169 
170     suggestOut.bServer = TRUE;
171 
172     /* Serve a client
173      */
174     while (ServeClient(pAsnIoIn, pAsnIoOut))
175         ;
176 
177     AsnIoClose(pAsnIoIn);
178     AsnIoClose(pAsnIoOut);
179 }
180 
181 /*****************************************************************************\
182  * Function:
183  *      ServeClient
184  *
185  * Purpose:
186  *      Reads one request from a client and sends to it the result of
187  *      processing.
188  *
189  * Parameter:
190  *      pAsnIoIn        - input file from which the request are read;
191  *      pAsnIoOut       - output file to which
192  *
193  * Return:
194  *      FALSE if nothing more to process or error occurred and farther
195  *      processing is not possible, otherwise TRUE.
196  *
197 \*****************************************************************************/
198 static Boolean
ServeClient(AsnIoPtr pAsnIn,AsnIoPtr pAsnOut)199 ServeClient(AsnIoPtr pAsnIn, AsnIoPtr pAsnOut)
200 {
201     short       iErrAct;
202     ErrDesc     err;
203     Boolean     bOnceMore = TRUE;
204     Uint2       errLevel;
205     SuggestErrorPtr     pSError;
206     SuggestRequestPtr   pReq;
207     SuggestResponsePtr  pResp;
208     SuggestIntervalsPtr pSIntervals;
209 
210     /* Encountering  EOF on reading is a "normal" occurrence,
211      * and does not merit an error message
212      */
213     ErrGetOpts(&iErrAct, NULL);
214     ErrSetOpts(ERR_IGNORE, 0);
215     ErrFetch(&err);     /* clear any pending error, which can be ignored */
216 
217     pReq = SuggestRequestAsnRead (pAsnIn, NULL);
218 
219     if (ErrFetch(&err)) {
220         ErrPostEx(SEV_ERROR, 1, 1, "Error encountered on AsnReadId %d", err);
221 
222         return FALSE;
223     }
224 
225     ErrSetOpts(iErrAct, 0);
226 
227     if (pReq == NULL) {
228         ErrPostEx(SEV_ERROR, 1, 1, "Null AsnReadId");
229 
230         return FALSE;
231     }
232 
233     switch (pReq->choice) {
234       case SuggestRequest_init: /* Initializing */
235         pResp = ValNodeNew(NULL);
236         SetSuggestMessageHook();
237         if (InitSuggest()) {
238             /* Init successful, send OK.
239              */
240             pResp->choice = SuggestResponse_init;
241             pResp->data.ptrvalue = NULL;
242         } else {
243             /* Error while init, send error
244              */
245             pResp->choice = SuggestResponse_error;
246             pResp->data.ptrvalue = (Pointer)GetLastSuggestError();
247             bOnceMore = FALSE;  /* Cancel farther processing */
248         }
249         SuggestResponseAsnWrite(pResp, pAsnOut, NULL);
250         RestoreMessageHook();
251         pResp->data.ptrvalue = NULL;    /* It's not necessary to free
252                                          * SuggestError structure.
253                                          */
254         SuggestResponseFree(pResp);
255         pReq->data.ptrvalue = NULL;
256         break;
257 
258       case SuggestRequest_intervals:    /* What this server does */
259         pSIntervals = pReq->data.ptrvalue;
260 
261         pResp = ValNodeNew(NULL);
262         SetSuggestMessageHook();
263 
264         /* The main task of this application, process the data
265          */
266         SuggestClientService (pSIntervals);
267 
268         /* Check for error while the processing
269          */
270         pSError = GetLastSuggestError();
271         errLevel = pSError->level;
272 
273         if (errLevel == Suggest_error_level_error ||
274             errLevel == Suggest_error_level_fatal)
275         {
276             /* Fatal error occurs, send error message to athe client
277              * and flags that the application must exit
278              */
279             pResp->choice = SuggestResponse_error;
280             pResp->data.ptrvalue = GetLastSuggestError();
281             if (errLevel == Suggest_error_level_fatal)
282                 bOnceMore = FALSE;
283 
284 /****       SeqAnnotFree(suggestOut.out.pSeqAnnot); */
285         } else {
286             pResp->choice = SuggestResponse_intervals;
287             pResp->data.ptrvalue = suggestOut.out.pSeqAnnot;
288         }
289 
290         SuggestResponseAsnWrite(pResp, pAsnOut, NULL);
291         RestoreMessageHook();
292         SuggestResponseFree(pResp);
293         suggestOut.out.pSeqAnnot = NULL;
294         break;
295 
296       case SuggestRequest_fini: /* Deinitializing */
297         pResp = ValNodeNew(NULL);
298         pResp->choice = SuggestResponse_fini;
299         pResp->data.ptrvalue = NULL;
300         SuggestResponseAsnWrite(pResp, pAsnOut, NULL);
301         SuggestResponseFree(pResp);
302         pReq->data.ptrvalue = NULL;
303         bOnceMore = FALSE;
304         break;
305 
306       default:
307         /* All request types must be processed.
308          * No default processing.
309          */
310         ASSERT(FALSE);
311     }
312 
313     AsnIoReset(pAsnOut);
314     SuggestRequestFree(pReq);   /* free read request */
315 
316     return bOnceMore;
317 }
318 
319 static MsgAnswer LIBCALLBACK
SuggestMessageHook(MsgKey msgKey,ErrSev errSev,const char * pchCaption,const char * pchMessage)320 SuggestMessageHook(MsgKey msgKey, ErrSev errSev,
321                    const char *pchCaption, const char *pchMessage)
322 {
323     switch (errSev) {
324       case MSG_ERROR:
325         suggestError.level = Suggest_error_level_error;
326         break;
327 
328       case MSG_FATAL:
329         suggestError.level = Suggest_error_level_fatal;
330         break;
331     }
332 
333     if (suggestError.msg != NULL)
334         MemFree(suggestError.msg);
335 
336     suggestError.msg = StringSave(pchMessage);
337 
338     return ANS_NONE;
339 }
340 
341 /*============================================================================*\
342  * Function:
343  *      SetSuggesstMessageHook
344  *
345  * Purpose:
346  *      Sets hook function for intercepting all calls to Message
347  *
348  * Parameters:
349  *      None
350  *
351  * Return:
352  *      None
353  *
354 \*----------------------------------------------------------------------------*/
355 static void
SetSuggestMessageHook(void)356 SetSuggestMessageHook(void)
357 {
358     fOldMsgHook = SetMessageHook(SuggestMessageHook);
359     ClearSuggestError();
360 }
361 
362 /*============================================================================*\
363  * Function:
364  *      RestoreMessageHook
365  *
366  * Purpose:
367  *      Resotore old hook function.
368  *
369  * Parameters:
370  *      none
371  *
372  * Return:
373  *      none
374  *
375 \*----------------------------------------------------------------------------*/
376 static void
RestoreMessageHook(void)377 RestoreMessageHook(void)
378 {
379     fOldMsgHook = SetMessageHook(fOldMsgHook);
380     ClearSuggestError();
381 }
382 
383 /*============================================================================*\
384  * Function:
385  *      GetLastSuggestError
386  *
387  * Purpose:
388  *
389  *
390  * Parameters:
391  *      none
392  *
393  * Return:
394  *      pointer to SuggestError structure, which contains information about
395  * last error.
396  *
397 \*----------------------------------------------------------------------------*/
398 static SuggestErrorPtr
GetLastSuggestError(void)399 GetLastSuggestError(void)
400 {
401     return &suggestError;
402 }
403 
404 /*============================================================================*\
405  * Function:
406  *      ClearSuggestError
407  *
408  * Purpose:
409  *      Sets last error to a state which corresponds to no error.
410  *
411  * Parameters:
412  *      none
413  *
414  * Return:
415  *      none
416  *
417 \*----------------------------------------------------------------------------*/
418 static void
ClearSuggestError(void)419 ClearSuggestError(void)
420 {
421     suggestError.level = Suggest_error_level_none;
422     if (suggestError.msg != NULL)
423         MemFree(suggestError.msg);
424 
425     suggestError.msg = NULL;
426 }
427 
428 Int2
Nlm_Main(void)429 Nlm_Main(void)
430 {
431     fprintf(stderr,"Kludge main executed in file %s", __FILE__);
432     exit (1);
433 }
434