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: netblap3.c
27 *
28 * Author: Tom Madden
29 *
30 * Version Creation Date:   05/8/97
31 *
32 * File Description:
33 *       Application Programming Interface (API) for BLAST network server
34 *
35 * RCS Modification History:
36 * $Log: netblap3.c,v $
37 * Revision 1.110  2007/05/07 13:30:08  kans
38 * added casts for Seq-data.gap (SeqDataPtr, SeqGapPtr, ByteStorePtr)
39 *
40 * Revision 1.109  2005/10/12 19:49:46  kans
41 * EntrezSetServer was removed, so commented out here
42 *
43 * Revision 1.108  2005/09/13 18:03:57  madden
44 * Fix so that tweak_parameters cna be in other_options
45 *
46 * Revision 1.107  2005/08/04 15:54:41  kans
47 * local variable defined before ASSERT in s_addTweakToOtherOptions for strict C compliance (CodeWarrior Carbon complained)
48 *
49 * Revision 1.106  2005/08/04 15:40:33  madden
50 * Add static functions s_parseOtherOptions and s_addTweakToOtherOptions to allow composition-based info to be passed
51 *
52 * Revision 1.105  2004/01/27 20:53:12  dondosha
53 * Value of no_traceback megablast option is now Uint1 instead of Boolean
54 *
55 * Revision 1.104  2003/01/13 18:08:26  bealer
56 * - Replace nonstandard snprintf() function with strcpy/strcat/strlen.
57 *
58 * Revision 1.103  2003/01/10 21:45:06  bealer
59 * - Modify to return errors from BLASTGetUidsFromQuery instead of logging them.
60 *
61 * Revision 1.102  2002/10/30 18:54:58  madden
62 * NULL out SeqLoc for lower-case masking
63 *
64 * Revision 1.101  2002/10/29 14:36:53  madden
65 * Fix problem with repeated error messages
66 *
67 * Revision 1.100  2002/10/24 16:41:23  merezhuk
68 * update to the BlastBioseq, will return all Blast-error responses instead off the first one
69 *
70 * Revision 1.99  2002/08/08 20:50:39  madden
71 * Remove SPLIT_BLAST macros
72 *
73 * Revision 1.98  2002/05/23 22:57:03  dondosha
74 * Made GetResponsePtr external
75 *
76 * Revision 1.97  2002/05/15 16:32:51  madden
77 * Make QueryIsProteinFromType extern
78 *
79 * Revision 1.96  2002/05/10 12:56:27  madden
80 * Allow network version of matrix as input
81 *
82 * Revision 1.95  2002/04/24 17:59:03  dondosha
83 * Added handling of parameters for database splitting and megablast with discontiguous words
84 *
85 * Revision 1.94  2002/04/03 16:29:48  dondosha
86 * Added SPLIT_BLAST macro to allow simultaneous use in current and new system
87 *
88 * Revision 1.93  2002/03/01 19:19:45  dondosha
89 * Previous change made in a wrong place
90 *
91 * Revision 1.92  2002/03/01 19:04:24  dondosha
92 * Set window size option to 0 for Web Mega BLAST
93 *
94 * Revision 1.91  2002/02/20 21:45:17  madden
95 * Add protection against truncated posFreq sequence
96 *
97 * Revision 1.90  2001/09/06 20:27:10  dondosha
98 * threshold_first removed from options
99 *
100 * Revision 1.89  2001/08/31 14:31:30  dondosha
101 * Correction to previous change needed for Mac
102 *
103 * Revision 1.88  2001/08/30 17:53:05  dondosha
104 * Fixed memory leak in Blast3GetDbinfo
105 *
106 * Revision 1.87  2001/05/02 19:42:48  egorov
107 * Make the NetBlastGetMatrix() external
108 *
109 * Revision 1.86  2001/04/26 21:55:43  juran
110 * Squelch compiler warnings.
111 *
112 * Revision 1.85  2001/04/02 18:49:13  dondosha
113 * Removed readdb_new_ex call
114 *
115 * Revision 1.84  2001/03/01 17:42:51  madden
116 * Removed unneeded line
117 *
118 * Revision 1.83  2001/03/01 15:16:46  dondosha
119 * Do pass matrix as well as pseudo frequences, if the former is provided
120 *
121 * Revision 1.82  2001/02/16 16:13:08  dondosha
122 * If posFreqs are present, do not copy matrix to and from net matrix
123 *
124 * Revision 1.81  2001/01/19 21:30:09  dondosha
125 * Call readdb...._ex functions to possibly save some time when finding db length
126 *
127 * Revision 1.80  2001/01/19 20:56:46  dondosha
128 * In NetDbinfo2TxDbinfo get database total length information from readdb
129 *
130 * Revision 1.79  2001/01/04 15:54:17  dondosha
131 * Added percent identity to the search parameters
132 *
133 * Revision 1.78  2000/12/19 18:41:37  madden
134 * Calls to BlastSetUserErrorString and BlastDeleteUserErrorString moved to blastool.c
135 *
136 * Revision 1.77  2000/11/16 22:26:31  dondosha
137 * Add endpoint results from Mega BLAST to search response
138 *
139 * Revision 1.76  2000/09/28 16:46:40  dondosha
140 * Changed MegaBlast related code to get a single SeqAlignPtr from server
141 *
142 * Revision 1.75  2000/09/20 22:10:25  madden
143 * Fix memory leaks
144 *
145 * Revision 1.74  2000/09/13 13:47:48  dondosha
146 * Typo fix
147 *
148 * Revision 1.73  2000/09/12 21:55:10  dondosha
149 * Pass the correct scoring matrix to ShowTextAlignFromAnnot
150 *
151 * Revision 1.72  2000/08/28 15:16:51  dondosha
152 * Added functionality to process megablast searches
153 *
154 * Revision 1.71  2000/08/03 20:54:51  shavirin
155 * Fixed some C++ specific errors.
156 *
157 * Revision 1.70  2000/08/03 18:32:27  shavirin
158 * Fixed bug in the function BlastNetMatrixToBlastMatrix()
159 *
160 * Revision 1.69  2000/06/22 18:01:49  shavirin
161 * Added check for 0s passed for required end and required start from
162 * the network.
163 *
164 * Revision 1.68  2000/06/19 19:02:52  dondosha
165 * Pass required_start and required_end between parameters and options - these are from and to positions on query
166 *
167 * Revision 1.67  2000/06/15 20:02:48  egorov
168 * Allow dispatcher == NULL in NetFini.  We need
169 * this when call SubmitRequest->ReestablishNetBlast() from an external
170 * program, eg. blastque
171 *
172 * Revision 1.66  2000/06/15 16:22:44  egorov
173 * Make SubmitRequest() external
174 *
175 * Revision 1.65  2000/06/07 17:16:17  shavirin
176 * Added handligng of posFreqs matrix - S&W blastpgp specific.
177 *
178 * Revision 1.64  2000/06/06 14:08:54  madden
179 * Fill in matrix name if NULL, required for ASN.1
180 *
181 * Revision 1.63  2000/05/30 15:08:57  shavirin
182 * Rolled back revision without swaping UIDs from Entrez query.
183 *
184 * Revision 1.60  2000/05/05 18:44:05  shavirin
185 * Added protection against uids== NULL in BLASTGetUidsFromQuery().
186 *
187 * Revision 1.59  2000/05/04 18:09:26  shavirin
188 * Added new function  BLASTGetUidsFromQuery().
189 *
190 * Revision 1.58  2000/04/28 18:05:46  shavirin
191 * Added parameter is_rps_blast to Network BLAST ASN.1
192 *
193 * Revision 1.57  2000/04/18 16:30:37  madden
194 * Fix memory leaks
195 *
196 * Revision 1.56  2000/01/20 18:37:13  madden
197 * Add vecscrn.h to includes
198 *
199 * Revision 1.55  2000/01/20 18:33:36  madden
200 * Use VSMakeSeqLoc in place of VSMakeDisplaySeqLoc
201 *
202 * Revision 1.54  2000/01/20 14:35:06  madden
203 * Updated VecScreen calls
204 *
205 * Revision 1.53  1999/12/03 16:43:22  egorov
206 * Add additional mutex in formating, which protects network fetch callbacks
207 * from MT-unsafe operations.
208 *
209 * Revision 1.52  1999/12/02 22:14:27  shavirin
210 * Fixed bug with printing H parameter in the bottom of Blast output.
211 *
212 * Revision 1.51  1999/11/24 21:42:30  vakatov
213 * Fixed for the C++ and/or MSVC DLL compilation
214 *
215 * Revision 1.50  1999/11/16 15:52:55  egorov
216 * Put additional mutex to protect GenericGetService function
217 *
218 * Revision 1.49  1999/11/12 16:35:00  shavirin
219 * Added adjustement of use_best_align parameters in OptionsToParameters
220 * and parameteresTooptions().
221 *
222 * Revision 1.48  1999/11/05 16:59:30  madden
223 * Fix more leaks
224 *
225 * Revision 1.47  1999/11/05 15:30:08  madden
226 * Fix some memory leaks
227 *
228 * Revision 1.46  1999/10/27 15:57:52  madden
229 * Changes for use_real_db_size
230 *
231 * Revision 1.45  1999/10/27 13:00:02  madden
232 * Changes to return-parts
233 *
234 * Revision 1.44  1999/09/22 14:06:26  madden
235 * NULL out gilist to prevent double freeing
236 *
237 * Revision 1.43  1999/08/19 19:37:48  shavirin
238 * Added new functions corresponding to the PHI/PSI Blast.
239 *
240 * Revision 1.41  1999/06/21 20:33:58  madden
241 * Plug some leaks
242 *
243 * Revision 1.40  1999/05/04 19:41:45  madden
244 * done now goes through callback
245 *
246 * Revision 1.39  1999/04/21 20:54:46  madden
247 * Make BlastBioseq non-private
248 *
249 * Revision 1.38  1999/04/20 14:51:35  madden
250 * BlastBioseqNetCore and BlastSeqLocNetCore have return status
251 *
252 * Revision 1.37  1999/04/16 19:05:40  madden
253 * Change done
254 *
255 * Revision 1.36  1999/04/16 15:53:25  madden
256 * Add TraditionalBlastReportExtra function
257 *
258 * Revision 1.35  1999/04/13 14:59:30  madden
259 * Add more options (searchsp, culling, strand)
260 *
261 * Revision 1.34  1999/04/02 16:25:53  madden
262 * Reestablish logic
263 *
264 * Revision 1.33  1999/03/19 21:47:38  madden
265 * Add Blast3GetDbinfo function
266 *
267 * Revision 1.32  1999/03/15 21:56:10  madden
268 * fix for error message that was freed
269 *
270 * Revision 1.31  1999/03/05 15:42:35  madden
271 * Fixed memory leaks
272 *
273 * Revision 1.30  1999/03/05 15:02:43  egorov
274 * Bug fixed.  Return NULL if no kablk found in the list of responses in the BlastGetKaParams function.
275 *
276 * Revision 1.29  1999/03/04 17:59:57  egorov
277 * Allow error_returns == NULL on input
278 *
279 * Revision 1.28  1999/03/01 20:55:59  egorov
280 * Fix infinite loop reestablishing connection to blast server (thanx to Sergei Shavirin)
281 *
282 * Revision 1.27  1999/01/12 21:05:58  victorov
283 * server will now report an error if the ni-queue if full
284 *
285 * Revision 1.26  1998/12/09 15:27:05  madden
286 * Add wordsize
287 *
288 * Revision 1.25  1998/11/03 21:46:19  egorov
289 * Add support for entrez-query and org-name
290 *
291 * Revision 1.24  1998/10/26 19:42:57  madden
292 * Check for NULL matrix or filter_string
293 *
294 * Revision 1.23  1998/10/06 18:28:07  egorov
295 * Fix MT problem with dispatcher_lock
296 *
297 * Revision 1.22  1998/09/22 16:12:53  egorov
298 * Use BlastErrorPrintExtra instead of BlastErrorPrint to redirect error messages both to log and to program output file
299 *
300 * Revision 1.21  1998/09/01 20:17:03  madden
301 *  Fixed uninitialzed problem in BlastNetBioseqFetchDisable, changed prototype
302 *
303 * Revision 1.20  1998/08/14 17:43:26  madden
304 * non-NULL f_order and g_order in formatting
305 *
306 * Revision 1.19  1998/08/14 16:04:48  egorov
307 * Create TLS for BlastNetFetchStruct to make it multi-thread safe.  Using some of global variables is commented out
308 *
309 * Revision 1.18  1998/07/28 16:57:51  egorov
310 * Make StringSave() for some CharPtr in assignments to save memory and avoid memory crashes
311 *
312 * Revision 1.16  1998/06/08 21:58:36  madden
313 * Check for NULL Bioseq in FetchFunc, print out Error message if NULL
314 *
315 * Revision 1.15  1998/05/08 21:40:15  vakatov
316 * fixed a tiny type cast(one more *)
317 *
318 * Revision 1.14  1998/05/08 20:56:22  madden
319 * Fix PC compile warnings, rename callback
320 *
321 * Revision 1.13  1998/05/08 01:08:09  madden
322 * Removed unused variables
323 *
324 * Revision 1.12  1998/04/24 18:35:50  madden
325 * Do not send Seq-descr to server
326 *
327 * Revision 1.11  1998/04/24 16:01:41  egorov
328 * Remove BlastErrorPrint from BlastSeqLocNetCore
329 *
330 * Revision 1.10  1998/04/23 14:19:31  egorov
331 * Allow other_returns in BlastSeqLocNet to be NULL
332 *
333 * Revision 1.9  1998/04/22 18:10:06  egorov
334 * Add support for SeqLoc to blastcl3
335 *
336 * Revision 1.8  1998/04/17 19:24:00  madden
337 * Transmit expect value, hitlist_size, and genetic codes to server
338 *
339 * Revision 1.7  1998/04/16 19:35:31  madden
340 * Added Int4Ptr arg to TraditionalBlastReport specifying the numbers of hits
341 *
342 * Revision 1.6  1998/04/09 16:16:33  madden
343 * Added BlastNetFetchCompare function
344 *
345 * Revision 1.5  1997/12/16 19:10:51  madden
346 * Fixed Codecenter errors
347 *
348 * Revision 1.4  1997/12/01 22:05:51  madden
349 * Changed call to BlastValidateOptionsEx
350 *
351 * Revision 1.3  1997/11/28 18:17:39  madden
352 * Changes for multiple db searches
353 *
354 * Revision 1.1  1997/10/08 19:27:20  madden
355 * Network support for gapped blast
356 *
357 */
358 
359 #include <ncbinet.h>
360 #include <ncbithr.h>
361 #include <txalign.h>
362 #include <jzmisc.h>
363 #include <blastpat.h>
364 #include <netblap3.h>
365 #include <vecscrn.h>
366 #include <ent2api.h>
367 
368 #define BLAST_SERVER_RETRIES  2
369 
370 #define BLASTNET_SHORT_BUFLEN 25
371 #define BLASTNET_BUF_SIZE 255
372 #define BLASTNET_INIT 0
373 #define BLASTNET_READY 1
374 #define BLASTNET_DISABLE 2
375 
376 typedef struct _blastnetbioseqfetch {
377 	Uint1 BlastNetFetchState;
378 	CharPtr dbname;	/* Name of the database. */
379 	BlastNet3Hptr bl3hp;	/* Network connection. */
380 	Uint2 ctr;
381 	Boolean is_prot; /* Is it a protein or not. */
382 } BlastNetFetchStruct, PNTR BlastNetFetchStructPtr;
383 
384 static TNlmTls blastnetfetch_tls = NULL;
385 
386 static Int2 num_attached = 0;
387 static NI_DispatcherPtr dispatcher = NULL;
388 /* Mutex for dispatcher. */
389 TNlmMutex dispatcher_lock = NULL;
390 
391 static TNlmMutex formating_mutex; /* Mutex to regulate formating in TraditionalBlastReport */
392 
393 static Boolean BlastInitEx PROTO((CharPtr program_name, BlastNet3Hptr bl3hp, BlastResponsePtr PNTR respp, Boolean reesatblish));
394 
395 static Boolean RealSubmitRequest PROTO((BlastNet3Hptr bl3hptr, BlastRequestPtr blreqp, BlastResponsePtr PNTR response, NetProgressCallback callback));
396 
397 /* error_occurred and old_error_hook should not be accessed directly.
398 The functions BlastSetErrorStatus, BlastGetErrorStatus, and BlastSetErrorHook
399 will change these variables. */
400 static Boolean error_occurred;
401 static ErrHookProc old_error_hook;
402 
403 /*
404 	The next five functions set an error hook and detect
405 	whether an error occurred (i.e., contact with the
406 	server was lost).
407 
408 	BlastSetErrorHook should be called first, the function
409 	BlastErrHookProc is set as the "handler"; BlastSetErrorStatus
410 	should then be called to set the error status to FALSE;
411 	BlastGetErrorStatus should be called to determine if an error
412 	occurred; and then BlastResetOldHook should be called to restore
413 	the original hook, in case BLAST is called from within another
414 	application that uses this (original) hook.
415 
416 	BlastSetErrorStatus is also called, to set the error status
417 	sometimes if a BlastAsnRead fails.  This is taken as evidence
418 	of an error, even if none is reported.
419 */
420 
421 static int LIBCALLBACK
BlastErrHookProc(const ErrDesc * err)422 BlastErrHookProc(const ErrDesc *err)
423 
424 {
425 	error_occurred = TRUE;
426 	return 1;
427 }
428 
429 static void
BlastSetErrorHook(void)430 BlastSetErrorHook(void)
431 
432 {
433 	old_error_hook = Nlm_ErrSetHandler(BlastErrHookProc);
434 	return;
435 }
436 
437 static void
BlastSetErrorStatus(Boolean status)438 BlastSetErrorStatus(Boolean status)
439 
440 {
441 	error_occurred = status;
442 }
443 
444 static Boolean
BlastGetErrorStatus(void)445 BlastGetErrorStatus(void)
446 
447 {
448 	return error_occurred;
449 }
450 
451 static void
BlastResetOldHook(void)452 BlastResetOldHook(void)
453 
454 {
455 	Nlm_ErrSetHandler(old_error_hook);
456 	return;
457 }
458 
459 /*****************************************************************************
460 *
461 *   NetInit ()
462 *
463 *****************************************************************************/
464 
NetInit(void)465 static Boolean NetInit(void)
466 {
467 	Boolean retval = FALSE;
468 
469 	NlmMutexLockEx(&dispatcher_lock);
470 
471 	if(num_attached++ > 0)
472 	{
473 	    NlmMutexUnlock(dispatcher_lock);
474 	    return TRUE;
475 	}
476 
477     	dispatcher = NI_GenericInit(NULL, NULL, TRUE, NULL, 0);
478 
479 	if (dispatcher)
480 		retval = TRUE;
481 
482 	NlmMutexUnlock(dispatcher_lock);
483 
484 	return retval;
485 }
486 
487 
488 /*****************************************************************************
489 *
490 *   ForceNetInit ()
491 *
492 *****************************************************************************/
493 
ForceNetInit(void)494 static Boolean ForceNetInit(void)
495 {
496 	Boolean retval;
497 
498 	NlmMutexLockEx(&dispatcher_lock);
499 
500 	num_attached = 0; /* force re-attempt to contact dispatcher */
501 	retval = NetInit();
502 
503 	NlmMutexUnlock(dispatcher_lock);
504 
505 	return retval;
506 }
507 
508 /*****************************************************************************
509 *
510 *   NetFini ()
511 
512 	BlastNet3Hptr bl3hp: was returned by BlastInit
513 	Boolean deallocate: should BlastNet3Hptr be deallocated (or will it be reused for
514 		a reconnection).
515 *
516 *****************************************************************************/
517 
NetFini(BlastNet3Hptr bl3hp,Boolean deallocate)518 static Boolean NetFini(BlastNet3Hptr bl3hp, Boolean deallocate)
519 {
520     NlmMutexLockEx(&dispatcher_lock);
521 
522 	if (num_attached > 0)
523 		num_attached--;
524 
525 	if (bl3hp != NULL)
526 	{
527 		NI_ServiceDisconnect(bl3hp->svcp);
528 		if (deallocate)
529                     bl3hp = (BlastNet3Hptr) MemFree(bl3hp);
530 
531 		if (num_attached == 0)
532 		{	/* Disconnect if last service to dispatcher. */
533 			if (dispatcher)
534 			    NI_EndServices (dispatcher);
535 			dispatcher = NULL;
536 		}
537 	}
538 
539 	NlmMutexUnlock(dispatcher_lock);
540 
541     return TRUE;
542 }
543 
544 
545 /*****************************************************************************
546 *
547 *   GenericReestablishNet ()
548 *
549 *****************************************************************************/
550 
GenericReestablishNet(CharPtr svcName,Boolean showErrs,BlastNet3Hptr bl3hp)551 static Boolean GenericReestablishNet(CharPtr svcName, Boolean showErrs, BlastNet3Hptr bl3hp)
552 {
553     Handle mon = NULL;
554     Boolean retval;
555     CharPtr buf;
556 
557     buf = (CharPtr) MemNew(2 * StrLen(svcName) + 60);
558 
559     if (showErrs) {
560         sprintf (buf, "Re-establishing %s Service", svcName);
561         mon = MonitorStrNew(buf, 40);
562         sprintf (buf, "Requesting %s service", svcName);
563         MonitorStrValue((MonitorPtr) mon, buf);
564     }
565 
566     NetFini(bl3hp, FALSE);
567 
568     retval = BlastInitEx(NULL, bl3hp, NULL, FALSE);
569 
570     if (!retval)
571     {
572         sprintf (buf, "%s get failed; re-contacting dispatcher", svcName);
573         MonitorStrValue((MonitorPtr) mon, buf);
574         retval = FALSE;
575         if (ForceNetInit())
576         { /* successfully established contact w/dispatcher */
577             sprintf (buf, "%s get failed; re-requesting %s service",
578                      svcName, svcName);
579             MonitorStrValue((MonitorPtr) mon, buf);
580 	    retval = BlastInitEx(NULL, bl3hp, NULL, FALSE);
581         }
582         else {
583             ErrPost(CTX_UNKNOWN, 1, "Unable to re-contact dispatcher");
584             if (showErrs) {
585                 ErrShow();
586             }
587         }
588     }
589 
590     MonitorFree((MonitorPtr) mon);
591 
592     if (! retval )
593     {
594         sprintf (buf, "Unable to re-establish %s service", svcName);
595         ErrPost(CTX_UNKNOWN, 1, buf);
596         if (showErrs) {
597             ErrShow();
598         }
599     }
600 
601     MemFree(buf);
602     return retval;
603 }
604 
605 /*****************************************************************************
606 *
607 *   ReestablishNetBlast ()
608 *
609 *****************************************************************************/
610 
ReestablishNetBlast(BlastNet3Hptr bl3hp)611 static Boolean ReestablishNetBlast(BlastNet3Hptr bl3hp)
612 {
613     return GenericReestablishNet("NETBLAST", TRUE, bl3hp);
614 }
615 
616 /*****************************************************************************
617 *
618 *   BlastInit ()
619 *
620 *****************************************************************************/
621 
BlastInitEx(CharPtr program_name,BlastNet3Hptr bl3hp,BlastResponsePtr PNTR respp,Boolean reestablish)622 static Boolean BlastInitEx (CharPtr program_name, BlastNet3Hptr bl3hp, BlastResponsePtr PNTR respp, Boolean reestablish)
623 
624 {
625 	BlastRequestPtr request;
626 	BlastResponsePtr response;
627 	NI_HandPtr svcp = NULL;
628 
629 	if (bl3hp == NULL)
630 	{
631 		return FALSE;
632 	}
633 
634 
635 	if (!NetInit())
636     	{
637        	 	ErrPostEx(SEV_ERROR, 0, 0, "NI_ServiceGet [%s] (%s)", ni_errlist[ni_errno], ni_errtext);
638 		return FALSE;
639 	}
640 
641 	NlmMutexLockEx(&dispatcher_lock);
642     	svcp = NI_GenericGetService(dispatcher, NULL, "NETBLAST", "blast3", FALSE);
643 	NlmMutexUnlock(dispatcher_lock);
644 
645     	if (svcp == NULL)
646     	{
647        	 	ErrPostEx(SEV_ERROR, 0, 0, "NI_ServiceGet [%s] (%s)", ni_errlist[ni_errno], ni_errtext);
648        	 	BlastFini(NULL);
649        	 	return FALSE;
650     	}
651 
652 	bl3hp->svcp = svcp;
653 
654 
655 	request = ValNodeNew(NULL);
656 	request->choice = BlastRequest_init;
657 
658 	SubmitRequest(bl3hp, request, &response, NULL, reestablish);
659     	BlastRequestFree (request);
660 
661 	if (respp)
662 		*respp = response;
663 	else
664     		BlastResponseFree (response);
665 
666 	return TRUE;
667 
668 }
669 
670 /*****************************************************************************
671 *
672 *   BlastInit ()
673 *
674 *****************************************************************************/
675 
676 NLM_EXTERN Boolean LIBCALL
BlastInit(CharPtr program_name,BlastNet3Hptr PNTR bl3hpp,BlastResponsePtr PNTR respp)677 BlastInit (CharPtr program_name, BlastNet3Hptr PNTR bl3hpp, BlastResponsePtr PNTR respp)
678 
679 {
680 	BlastNet3Hptr bl3hp_pri;
681 
682 	if (bl3hpp == NULL)
683 	{
684      ErrPostEx(SEV_ERROR, 0, 0, "BlastInitMT, BlastNet3Hptr PNTR is NULL");
685      return FALSE;
686 	}
687 
688 	bl3hp_pri = (BlastNet3Hptr) MemNew(sizeof(BlastNet3Hptr));
689 	if (bl3hp_pri == NULL)
690 		return FALSE;
691 
692 	*bl3hpp = bl3hp_pri;
693 
694 	return BlastInitEx(program_name, bl3hp_pri, respp, TRUE);
695 }
696 
697 /*****************************************************************************
698 *
699 *   BlastFini ()
700 *
701 *****************************************************************************/
702 
s_BlastFini(BlastNet3Hptr bl3hptr)703 static Boolean s_BlastFini (BlastNet3Hptr bl3hptr)
704 
705 {
706 	Boolean retval = TRUE;
707 	BlastRequestPtr request;
708 	BlastResponsePtr response;
709 
710 
711 	if (bl3hptr == NULL || bl3hptr->svcp == NULL)
712 		return FALSE;
713 
714         request = ValNodeNew(NULL);
715         request->choice = BlastRequest_fini;
716 	SubmitRequest(bl3hptr, request, &response, NULL, FALSE);
717         BlastRequestFree (request);
718         BlastResponseFree (response);
719 
720 	NetFini(bl3hptr, TRUE);
721 	return retval;
722 }
723 
724 /* the only thing done here is to suppress errors */
725 
726 NLM_EXTERN Boolean LIBCALL
BlastFini(BlastNet3Hptr bl3hptr)727 BlastFini (BlastNet3Hptr bl3hptr)
728 
729 {
730     short erract;
731     ErrDesc err;
732     Boolean retval;
733 
734     ErrGetOpts(&erract, NULL);
735     ErrSetOpts(ERR_IGNORE, 0);
736     ErrFetch(&err);
737 
738     retval = s_BlastFini(bl3hptr);
739 
740     ErrSetOpts(erract, 0);
741     ErrFetch(&err);
742 
743     return retval;
744 }
745 
746 void static
s_addTweakToOtherOptions(Uint1 tweak_parameters,BlastParametersPtr parameters)747 s_addTweakToOtherOptions(Uint1 tweak_parameters, BlastParametersPtr parameters)
748 {
749         const Int4 kBuffSize=128;
750         ASSERT(parameters);
751 
752         if (tweak_parameters > 0)
753         {
754              char* other_options = NULL;
755              Int4 len = 0;
756              if (parameters->other_options && StringLen(parameters->other_options) > 0)
757              {
758                  len = 1 + StringLen(parameters->other_options);
759                  other_options = MemNew((len+kBuffSize)*sizeof(char));
760                  StrCpy(other_options, parameters->other_options);
761                  MemFree(parameters->other_options);
762              }
763              else
764              {
765                  other_options = MemNew((kBuffSize)*sizeof(char));
766              }
767              sprintf(other_options+len, "-t%ld", (long) tweak_parameters);
768              parameters->other_options = other_options;
769         }
770 
771         return;
772 }
773 
774 NLM_EXTERN BlastParametersPtr LIBCALL
BlastOptionsToParameters(BLAST_OptionsBlkPtr options)775 BlastOptionsToParameters (BLAST_OptionsBlkPtr options)
776 
777 {
778 	BlastParametersPtr parameters;
779 
780 
781 	if (options == NULL)
782 	{
783 		return NULL;
784 	}
785 
786 	parameters = BlastParametersNew();
787 	parameters->gapped_alignment = options->gapped_calculation;
788 	if (options->cutoff_s == 0)
789 	{
790 		parameters->Cutoff_cutoff = ValNodeAddFloat(NULL, Cutoff_cutoff_evalue, options->expect_value);
791 	}
792 	else
793 	{
794 		parameters->Cutoff_cutoff = ValNodeAddInt(NULL, Cutoff_cutoff_score, options->cutoff_s);
795 	}
796 	if (options->cutoff_s2 == 0)
797 	{
798 		parameters->Cutoff2_cutoff2 = ValNodeAddFloat(NULL, Cutoff2_cutoff2_evalue, options->e2);
799 	}
800 	else
801 	{
802 		parameters->Cutoff2_cutoff2 = ValNodeAddInt(NULL, Cutoff2_cutoff2_score, options->cutoff_s2);
803 	}
804 	parameters->hitlist_size = options->hitlist_size;
805 	parameters->first_threshold = options->threshold_second;
806 	parameters->second_threshold = options->threshold_second;
807 	parameters->nucl_penalty = options->penalty;
808 	parameters->nucl_reward = options->reward;
809 	parameters->gap_open = options->gap_open;
810 	parameters->gap_extend = options->gap_extend;
811 	parameters->genetic_code = options->genetic_code;
812 	parameters->db_genetic_code = options->db_genetic_code;
813 	parameters->low_complexity_filtering = options->filter;
814 	parameters->ethresh = options->ethresh;
815         parameters->max_num_passes = options->maxNumPasses;
816         parameters->pseudo_count_const = options->pseudoCountConst;
817 
818         parameters->gifile = StringSave(options->gifile);
819         parameters->gilist = options->gilist;
820         parameters->matrix = StringSave(options->matrix);
821         parameters->filter_string = StringSave(options->filter_string);
822 	parameters->entrez_query = StringSave(options->entrez_query);
823         parameters->word_size = options->wordsize;
824         parameters->db_length = options->db_length;
825         parameters->searchsp_eff = options->searchsp_eff;
826         parameters->hsp_range_max = options->hsp_range_max;
827         parameters->block_width = options->block_width;
828         parameters->perform_culling = options->perform_culling;
829         parameters->strand_option = options->strand_option;
830 
831         parameters->phi_pattern = StringSave(options->phi_pattern);
832         parameters->use_real_db_size = options->use_real_db_size;
833 #if 0
834         parameters->db_dir_prefix = StringSave(options->db_dir_prefix);
835 #endif
836         parameters->use_best_align = options->use_best_align;
837 
838         if(options->required_start != 0)
839             parameters->required_start = options->required_start;
840 
841         if(options->required_end != 0)
842             parameters->required_end = options->required_end;
843 
844         parameters->is_rps_blast = options->is_rps_blast;
845 
846         parameters->tweak_parameters = options->tweak_parameters;
847         if (options->tweak_parameters > 0)
848              s_addTweakToOtherOptions(options->tweak_parameters, parameters);
849 
850         parameters->smith_waterman = options->smith_waterman;
851         parameters->is_megablast = options->is_megablast_search;
852         parameters->query_lcase_mask = (ValNodePtr) options->query_lcase_mask;
853         parameters->endpoint_results = (Boolean) options->no_traceback;
854         parameters->percent_identity = (FloatHi) options->perc_identity;
855         parameters->first_db_seq = options->first_db_seq;
856         parameters->final_db_seq = options->final_db_seq;
857         parameters->window_size = options->window_size;
858         parameters->mb_template_length = options->mb_template_length;
859         parameters->mb_disc_type = options->mb_disc_type;
860 
861 	return parameters;
862 }
863 
864 /*
865 	Translates the BlastDbinfoPtr into TxDfDbInfoPtr.
866 */
867 
868 NLM_EXTERN TxDfDbInfoPtr LIBCALL
NetDbinfo2TxDbinfo(BlastDbinfoPtr net_dbinfo)869 NetDbinfo2TxDbinfo(BlastDbinfoPtr net_dbinfo)
870 {
871 	TxDfDbInfoPtr dbinfo=NULL, dbinfo_head;
872 
873 	dbinfo_head = NULL;
874 	while (net_dbinfo)
875 	{
876 		dbinfo = TxDfDbInfoNew(dbinfo);
877 		dbinfo->is_protein = net_dbinfo->is_protein;
878 		dbinfo->name = StringSave(net_dbinfo->name);
879 		dbinfo->definition = StringSave(net_dbinfo->definition);
880 		dbinfo->date = StringSave(net_dbinfo->date);
881                 dbinfo->total_length = net_dbinfo->total_length;
882                 /* total length in net_dbinfo is Int4, might be incorrect */
883                 if (dbinfo->total_length < 0)
884                    dbinfo->total_length += sizeof(Int4);
885                 dbinfo->number_seqs = net_dbinfo->number_seqs;
886 		if (dbinfo_head == NULL)
887 			dbinfo_head = dbinfo;
888 		net_dbinfo = net_dbinfo->next;
889 	}
890 
891 	return dbinfo_head;
892 }
893 
894 NLM_EXTERN BlastNet3BlockPtr LIBCALL
BlastNet3BlockDestruct(BlastNet3BlockPtr blnet)895 BlastNet3BlockDestruct(BlastNet3BlockPtr blnet)
896 
897 {
898 	BlastResponsePtr next, response;
899 
900 	if (blnet == NULL)
901 		return NULL;
902 
903 	/* The entire gilist is not copied, so this prevents an error. */
904 	if (blnet->parameters)
905 		blnet->parameters->gilist = NULL;
906 
907         /* The following is not allocated here */
908     	blnet->parameters->query_lcase_mask = NULL;
909 
910 	BlastParametersFree(blnet->parameters);
911 	/* individual elements freed elsewhere. */
912 	response = blnet->response;
913 	while(response)
914 	{
915 		next = response->next;
916 		response->data.ptrvalue = NULL;
917 		BlastResponseFree(response);
918 		response = next;
919 	}
920 	MemFree(blnet->dbname);
921 	MemFree(blnet);
922 
923 	return NULL;
924 }
925 
926 /*
927 	Creates a new BlastNet3BlockNew, used for searching.
928 */
929 NLM_EXTERN BlastNet3BlockPtr LIBCALL
BlastNet3BlockNew(CharPtr program,CharPtr dbname)930 BlastNet3BlockNew(CharPtr program, CharPtr dbname)
931 
932 {
933 	BlastNet3BlockPtr retval=NULL;
934 
935 	retval = (BlastNet3BlockPtr) MemNew(sizeof(BlastNet3Block));
936 
937 	if (retval)
938 	{
939 		if (StringICmp("blastn", program) == 0)
940 			retval->prog_type = Blast_search_program_blastn;
941 		else if (StringICmp("blastp", program) == 0)
942 			retval->prog_type = Blast_search_program_blastp;
943 		else if (StringICmp("blastx", program) == 0)
944 			retval->prog_type = Blast_search_program_blastx;
945 		else if (StringICmp("tblastn", program) == 0)
946 			retval->prog_type = Blast_search_program_tblastn;
947 		else if (StringICmp("tblastx", program) == 0)
948 			retval->prog_type = Blast_search_program_tblastx;
949 		if (dbname)
950 			retval->dbname = StringSave(dbname);
951 	}
952 
953 	return retval;
954 }
955 
956 NLM_EXTERN Boolean LIBCALL
QueryIsProteinFromType(Uint2 type)957 QueryIsProteinFromType(Uint2 type)
958 {
959 	switch (type)
960 	{
961 		case Blast_search_program_blastn:
962 			return FALSE;
963 		case Blast_search_program_blastp:
964 			return TRUE;
965 		case Blast_search_program_blastx:
966 			return FALSE;
967 		case Blast_search_program_tblastn:
968 			return TRUE;
969 		case Blast_search_program_tblastx:
970 			return FALSE;
971 		default:
972 			return FALSE;
973 	}
974 }
975 
GetResponsePtr(BlastResponsePtr response,Nlm_Uint1 choice)976 BlastResponsePtr GetResponsePtr(BlastResponsePtr response, Nlm_Uint1 choice)
977 
978 {
979 	while (response)
980 	{
981 		if (response->choice == choice)
982 		{
983 			break;
984 		}
985 		response = response->next;
986 	}
987 
988 	return response;
989 }
990 
991 NLM_EXTERN BlastDbinfoPtr LIBCALL
BlastRequestDbInfo(BlastNet3Hptr bl3hp,CharPtr database,Boolean is_prot)992 BlastRequestDbInfo (BlastNet3Hptr bl3hp, CharPtr database, Boolean is_prot)
993 
994 {
995 	BlastRequestPtr request=NULL;
996 	BlastResponsePtr response=NULL;
997 	BlastDbinfoPtr dbinfo=NULL;
998 	BlastDbinfoGetPtr dbinfo_get;
999 
1000 
1001 	dbinfo_get = BlastDbinfoGetNew();
1002 	dbinfo_get->name = database;
1003 
1004 	if (is_prot)
1005 		dbinfo_get->type = Blast_dbinfo_get_type_protein;
1006 	else
1007 		dbinfo_get->type = Blast_dbinfo_get_type_nucleotide;
1008 
1009 	ValNodeAddPointer(&request, BlastRequest_db_info_specific, dbinfo_get);
1010 	SubmitRequest(bl3hp, request, &response, NULL, TRUE);
1011 	response = (BlastResponsePtr)
1012            GetResponsePtr(response, BlastResponse_db_info_specific);
1013 
1014 	if (response)
1015 	{
1016 		dbinfo = (BlastDbinfoPtr) response->data.ptrvalue;
1017 		response->data.ptrvalue = NULL;
1018 		BlastResponseFree(response);
1019 	}
1020 
1021 	dbinfo_get->name = NULL;	/* Not owned by this function. */
1022         BlastRequestFree(request);
1023 
1024 	return dbinfo;
1025 }
1026 
1027 NLM_EXTERN BlastDbinfoPtr LIBCALL
BlastGetDbInfo(BlastNet3BlockPtr blnet3blkptr)1028 BlastGetDbInfo (BlastNet3BlockPtr blnet3blkptr)
1029 
1030 {
1031 	BlastResponsePtr response;
1032 	BlastDbinfoPtr dbinfo=NULL, dbinfo_head, last;
1033 
1034 	last = NULL;
1035 	dbinfo = NULL;
1036 	dbinfo_head = NULL;
1037 	response = blnet3blkptr->response;
1038 	while (response)
1039 	{
1040 		response = (BlastResponsePtr)
1041                    GetResponsePtr(response, BlastResponse_db_info_specific);
1042 		if (response)
1043 		{
1044 			last = dbinfo;
1045 			dbinfo = (BlastDbinfoPtr) response->data.ptrvalue;
1046 			if (dbinfo_head == NULL)
1047 				dbinfo_head = dbinfo;
1048 			if (last)
1049 				last->next = dbinfo;
1050 			response = response->next;
1051 		}
1052 	}
1053 
1054 	return dbinfo_head;
1055 }
1056 
1057 BlastMatrixPtr LIBCALL
NetBlastGetMatrix(BlastNet3BlockPtr blnet3blkptr)1058 NetBlastGetMatrix(BlastNet3BlockPtr blnet3blkptr)
1059 
1060 {
1061 	BlastResponsePtr response;
1062 	BlastMatrixPtr matrix=NULL;
1063 
1064 
1065 	response = (BlastResponsePtr)
1066            GetResponsePtr(blnet3blkptr->response, BlastResponse_matrix);
1067 
1068 	if (response)
1069 		matrix = (BlastMatrixPtr) response->data.ptrvalue;
1070 
1071 	return matrix;
1072 }
1073 
1074 NLM_EXTERN CharPtr LIBCALL
BlastGetParameterBuffer(BlastNet3BlockPtr blnet3blkptr)1075 BlastGetParameterBuffer (BlastNet3BlockPtr blnet3blkptr)
1076 
1077 {
1078 	BlastResponsePtr response;
1079 	CharPtr buffer=NULL;
1080 
1081 	response = (BlastResponsePtr)
1082            GetResponsePtr(blnet3blkptr->response, BlastResponse_parameters);
1083 
1084 	if (response)
1085 		buffer = (CharPtr) response->data.ptrvalue;
1086 
1087 	return buffer;
1088 }
1089 
1090 /*
1091 	Find the BlastKABlkPtr of the type (gapped or ungapped) specified.
1092 */
1093 NLM_EXTERN BlastKABlkPtr LIBCALL
BlastGetKaParams(BlastNet3BlockPtr blnet3blkptr,Boolean gapped)1094 BlastGetKaParams (BlastNet3BlockPtr blnet3blkptr, Boolean gapped)
1095 
1096 {
1097 	BlastResponsePtr response;
1098 	BlastKABlkPtr kablk=NULL;
1099 
1100 
1101 	response = blnet3blkptr->response;
1102 	while (response)
1103 	{
1104 		response =(BlastResponsePtr)
1105                    GetResponsePtr(response, BlastResponse_kablk);
1106 		if (response)
1107 		{
1108                     kablk = (BlastKABlkPtr) response->data.ptrvalue;
1109 			if (kablk->gapped == gapped)
1110 				break;
1111 			response = response->next;
1112 			kablk = NULL;
1113 		}
1114 	}
1115 
1116 	return kablk;
1117 }
1118 
1119 /*
1120 	Converts 'standard' BLAST matrix to network matrix.
1121 */
1122 
1123 NLM_EXTERN BlastMatrixPtr LIBCALL
BlastMatrixToBlastNetMatrix(BLAST_MatrixPtr matrix)1124 BlastMatrixToBlastNetMatrix(BLAST_MatrixPtr matrix)
1125 
1126 {
1127     BlastMatrixPtr net_matrix;
1128     Int4 index1, index2;
1129     ValNodePtr vnp = NULL, newvnp = NULL;
1130 
1131     if (matrix == NULL)
1132         return NULL;
1133 
1134     net_matrix = (BlastMatrixPtr) MemNew(sizeof(BlastMatrix));
1135 
1136     net_matrix->is_protein = matrix->is_prot;
1137 
1138     if (matrix->name)
1139         net_matrix->name = StringSave(matrix->name);
1140     else
1141         net_matrix->name = StringSave("unknown");
1142 
1143     net_matrix->row_length = matrix->rows;
1144     net_matrix->column_length = matrix->columns;
1145     net_matrix->karlinK = matrix->karlinK;
1146 
1147     if(matrix->posFreqs != NULL) {
1148         for (vnp=NULL,index1 = matrix->rows-1; index1 >= 0; index1--) {
1149             for (index2 = matrix->columns-1; index2 >= 0; index2--) {
1150                 newvnp = (ValNodePtr) Nlm_MemNew(sizeof(ValNode));
1151                 newvnp->data.realvalue =  matrix->posFreqs[index1][index2];
1152                 newvnp->next = vnp;
1153                 vnp = newvnp;
1154             }
1155         }
1156         net_matrix->posFreqs = vnp;
1157     }
1158     if (matrix->matrix != NULL) {
1159        for (vnp=NULL,index1 = matrix->rows-1; index1 >= 0; index1--) {
1160           for (index2 = matrix->columns-1; index2 >= 0; index2--) {
1161              newvnp = (ValNodePtr) Nlm_MemNew(sizeof(ValNode));
1162              newvnp->data.intvalue =  matrix->matrix[index1][index2];
1163              newvnp->next = vnp;
1164              vnp = newvnp;
1165           }
1166        }
1167        net_matrix->scores = vnp;
1168     }
1169     return net_matrix;
1170 
1171 }
1172 
1173 /*
1174 	Coverts the 'network' matrix to a 'tools' matrix.
1175 */
1176 NLM_EXTERN BLAST_MatrixPtr LIBCALL
BlastNetMatrixToBlastMatrix(BlastMatrixPtr net_matrix)1177 BlastNetMatrixToBlastMatrix (BlastMatrixPtr net_matrix)
1178 
1179 {
1180     BLAST_MatrixPtr blast_matrix;
1181     Int4 index1, index2;
1182     Int4Ptr PNTR matrix;
1183     Nlm_FloatHi **posFreqs;
1184     ValNodePtr vnp;
1185 
1186     if (net_matrix == NULL)
1187         return NULL;
1188 
1189     blast_matrix = (BLAST_MatrixPtr) MemNew(sizeof(BLAST_Matrix));
1190 
1191     blast_matrix->is_prot = net_matrix->is_protein;
1192     blast_matrix->name = StringSave(net_matrix->name);
1193     blast_matrix->rows = net_matrix->row_length;
1194     blast_matrix->columns = net_matrix->column_length;
1195     blast_matrix->karlinK = net_matrix->karlinK;
1196 
1197     if(net_matrix->posFreqs != NULL) {
1198         vnp = net_matrix->posFreqs;
1199         posFreqs = (Nlm_FloatHi **)
1200             MemNew(blast_matrix->rows*sizeof(Nlm_FloatHi *));
1201 
1202         for (index1=0; index1<blast_matrix->rows && vnp; index1++) {
1203             posFreqs[index1] = (Nlm_FloatHi *) MemNew(blast_matrix->columns*sizeof(Nlm_FloatHi));
1204             for (index2=0; index2<blast_matrix->columns && vnp; index2++) {
1205                 posFreqs[index1][index2] = (Nlm_FloatHi) vnp->data.realvalue;
1206                 vnp = vnp->next;
1207             }
1208         }
1209         blast_matrix->posFreqs = posFreqs;
1210 
1211 	/* Check if matrix was truncated. */
1212 	if (index1 != blast_matrix->rows || index2 != blast_matrix->columns)
1213 	{
1214 		posFreqs = MemFree(posFreqs);
1215 		blast_matrix->name = MemFree(blast_matrix->name);
1216 		blast_matrix = MemFree(blast_matrix);
1217 		return NULL;
1218 	}
1219     }
1220 
1221     if (net_matrix->scores != NULL) {
1222        vnp = net_matrix->scores;
1223        matrix = (Int4Ptr PNTR) MemNew(blast_matrix->rows*sizeof(Int4Ptr));
1224        for (index1=0; index1<blast_matrix->rows; index1++) {
1225           matrix[index1] = (Int4Ptr) MemNew(blast_matrix->columns*sizeof(Int4));
1226           for (index2=0; index2<blast_matrix->columns; index2++) {
1227              matrix[index1][index2] = (Int4) vnp->data.intvalue;
1228              vnp = vnp->next;
1229           }
1230        }
1231        blast_matrix->matrix = matrix;
1232     }
1233 
1234 
1235     return blast_matrix;
1236 }
1237 
1238 NLM_EXTERN ValNodePtr LIBCALL
BlastGetMaskedLoc(BlastNet3BlockPtr blnet3blkptr)1239 BlastGetMaskedLoc (BlastNet3BlockPtr blnet3blkptr)
1240 
1241 {
1242 	BlastResponsePtr response;
1243 	BlastMaskPtr blast_mask;
1244 	ValNodePtr mask_loc=NULL;
1245 
1246 	response = blnet3blkptr->response;
1247 
1248 	while (response)
1249 	{
1250 		response = (BlastResponsePtr)
1251                    GetResponsePtr(response, BlastResponse_mask);
1252 		if (response)
1253 		{
1254 			blast_mask = (BlastMaskPtr) response->data.ptrvalue;
1255 			/* location is turned over to calling routine to be deallocated. */
1256 			ValNodeAddPointer(&mask_loc, blast_mask->frame, blast_mask->location);
1257 			blast_mask->location = NULL;
1258 			BlastMaskFree(blast_mask);
1259 			response = response->next;
1260 		}
1261 	}
1262 
1263 	return mask_loc;
1264 }
1265 
1266 static BioseqPtr
PrivateBlastGetBioseq(BlastNet3Hptr bl3hptr,CharPtr database,SeqIdPtr sip,Boolean is_prot)1267 PrivateBlastGetBioseq(BlastNet3Hptr bl3hptr, CharPtr database, SeqIdPtr sip, Boolean is_prot)
1268 
1269 {
1270 	BioseqPtr bsp=NULL;
1271 	BlastSeqIdPtr blast_sip;
1272 	BlastRequestPtr request = NULL;
1273 	BlastResponsePtr response = NULL;
1274 
1275 	blast_sip = BlastSeqIdNew();
1276 	blast_sip->is_protein = is_prot;
1277 	blast_sip->database = database;
1278 	blast_sip->id = sip;
1279 	ValNodeAddPointer(&request, BlastRequest_db_seq_get, blast_sip);
1280 	SubmitRequest(bl3hptr, request, &response, NULL, TRUE);
1281 
1282 	response = (BlastResponsePtr)
1283            GetResponsePtr(response, BlastResponse_db_seq_get);
1284 	if (response)
1285 	{
1286 		bsp = (BioseqPtr) response->data.ptrvalue;
1287 		response->data.ptrvalue = NULL;
1288 		BlastResponseFree(response);
1289 	}
1290 
1291 	/* These two were not allocated here. */
1292 	blast_sip->id = NULL;
1293 	blast_sip->database = NULL;
1294 	BlastRequestFree(request);
1295 
1296 	return bsp;
1297 }
1298 
1299 NLM_EXTERN BioseqPtr LIBCALL
BlastGetBioseq(BlastNet3BlockPtr blnet3blkptr,SeqIdPtr sip)1300 BlastGetBioseq(BlastNet3BlockPtr blnet3blkptr, SeqIdPtr sip)
1301 
1302 {
1303 	BioseqPtr bsp;
1304 
1305 	bsp = PrivateBlastGetBioseq(blnet3blkptr->bl3hptr, blnet3blkptr->dbname, sip, QueryIsProteinFromType(blnet3blkptr->prog_type));
1306 
1307 	return bsp;
1308 }
1309 
1310 /*
1311 	Basic functions to submit BLAST runs.
1312 
1313 */
1314 
1315 NLM_EXTERN SeqAlignPtr LIBCALL
BlastBioseq(BlastNet3BlockPtr blnet3blkptr,ValNodePtr * error_returns,Boolean PNTR status,ValNodePtr * other_returns)1316 BlastBioseq (BlastNet3BlockPtr blnet3blkptr, ValNodePtr *error_returns, Boolean
1317              PNTR status, ValNodePtr *other_returns)
1318 
1319 {
1320 	BlastRequestPtr request = NULL;
1321 	BlastSearchPtr search = NULL;
1322 	BlastResponsePtr response = NULL;
1323 	ValNodePtr node;
1324 	SeqAlignPtr seqalign=NULL;
1325 	/* Uint1 err_id; */
1326 
1327 #if 0
1328 	err_id = BlastSetUserErrorString("netblast:", blnet3blkptr->bsp->id, TRUE);
1329 #endif
1330 
1331 	search = BlastSearchNew();
1332 	search->program = blnet3blkptr->prog_type;
1333 /*
1334 	search->query = (struct struct_Bioseq *) blnet3blkptr->bsp;
1335 */
1336 	search->query = blnet3blkptr->bsp;
1337 	search->database = blnet3blkptr->dbname;
1338 	search->parameters = blnet3blkptr->parameters;
1339 	search->mask = blnet3blkptr->mask;
1340 	if (blnet3blkptr->blast_matrix)
1341 	{
1342 		search->matrix =
1343 		   BlastMatrixToBlastNetMatrix(blnet3blkptr->blast_matrix);
1344 	}
1345 	else
1346 	{
1347 		search->matrix = blnet3blkptr->net_matrix;
1348 	}
1349 	search->query_set = blnet3blkptr->bsp_set;
1350 
1351         ValNodeAddPointer(&request, BlastRequest_search, search);
1352         *status = SubmitRequest(blnet3blkptr->bl3hptr, request, &response, blnet3blkptr->callback, TRUE);
1353 
1354         blnet3blkptr->response = response;
1355         node = (BlastResponsePtr)
1356            GetResponsePtr(response, BlastResponse_alignment);
1357         if (node)
1358            seqalign = (SeqAlignPtr) node->data.ptrvalue;
1359 
1360         if (other_returns) {
1361            /* MegaBLAST endpoint returns */
1362            node = (BlastResponsePtr)
1363               GetResponsePtr(response, BlastResponse_mbalign);
1364            if (node) {
1365               ValNodeAddPointer(other_returns, BlastResponse_mbalign,
1366                                 node->data.ptrvalue);
1367            }
1368         }
1369 	if (error_returns)
1370 	{
1371 	  /* return all blast error responses */
1372 	    node = (BlastResponsePtr)
1373 	      GetResponsePtr(response, BlastResponse_error);
1374 	    while (node)
1375 	    {
1376 		ValNodeAddPointer(error_returns, BlastResponse_error, node->data.ptrvalue);
1377 		node = node->next;
1378 	    	node = (BlastResponsePtr)
1379 	      		GetResponsePtr(node, BlastResponse_error);
1380 	    }
1381 	}
1382 
1383 	/* These six are not allocated here. */
1384 	search->query = NULL;
1385 	search->database = NULL;
1386 	search->parameters = NULL;
1387 	search->mask = NULL;
1388 	search->query_set = NULL;
1389 	search->matrix = NULL;
1390         BlastRequestFree(request);
1391 #if 0
1392 	BlastDeleteUserErrorString(err_id);
1393 #endif
1394 
1395 	return seqalign;
1396 }
1397 
1398 /*
1399 	Functions to submit BLAST runs and get back parts.
1400 
1401 */
1402 
1403 static BlastPartsPtr
BlastBioseqByParts(BlastNet3BlockPtr blnet3blkptr,ValNodePtr * error_returns,Boolean PNTR status)1404 BlastBioseqByParts (BlastNet3BlockPtr blnet3blkptr, ValNodePtr *error_returns, Boolean PNTR status)
1405 
1406 {
1407 	BlastRequestPtr request = NULL;
1408 	BlastSearchPtr search = NULL;
1409 	BlastResponsePtr response = NULL;
1410 	ValNodePtr node;
1411 	BlastPartsPtr blast_parts=NULL;
1412 	/* Uint1 err_id; */
1413 
1414 #if 0
1415 	err_id = BlastSetUserErrorString("netblast:", blnet3blkptr->bsp->id, TRUE);
1416 #endif
1417 
1418 	search = BlastSearchNew();
1419 	search->program = blnet3blkptr->prog_type;
1420 /*
1421 	search->query = (struct struct_Bioseq *) blnet3blkptr->bsp;
1422 */
1423 	search->query = blnet3blkptr->bsp;
1424 	search->database = blnet3blkptr->dbname;
1425 	search->parameters = blnet3blkptr->parameters;
1426 	search->mask = blnet3blkptr->mask;
1427 	search->matrix = BlastMatrixToBlastNetMatrix(blnet3blkptr->blast_matrix);
1428 	search->return_parts = TRUE;
1429 	ValNodeAddPointer(&request, BlastRequest_search, search);
1430 	*status = SubmitRequest(blnet3blkptr->bl3hptr, request, &response, blnet3blkptr->callback, TRUE);
1431 
1432 	blnet3blkptr->response = response;
1433 	node = (BlastResponsePtr)
1434            GetResponsePtr(response, BlastResponse_parts);
1435 	if (node)
1436             blast_parts = (BlastPartsPtr) node->data.ptrvalue;
1437 
1438 	if (error_returns)
1439 	{
1440 	    node = (BlastResponsePtr)
1441                GetResponsePtr(response, BlastResponse_error);
1442 	    if (node)
1443 	    	ValNodeAddPointer(error_returns, BlastResponse_error, node->data.ptrvalue);
1444 	}
1445 
1446 	/* These four are not allocated here. */
1447 	search->query = NULL;
1448 	search->database = NULL;
1449 	search->parameters = NULL;
1450 	search->mask = NULL;
1451         BlastRequestFree(request);
1452 #if 0
1453 	BlastDeleteUserErrorString(err_id);
1454 #endif
1455 
1456 	return blast_parts;
1457 }
1458 
1459 /* ------------ Set os functions to support PHI-Blast ----------- */
1460 
1461 static BlastPhialignPtr LIBCALL
SeedBioseq(BlastNet3BlockPtr blnet3blkptr,ValNodePtr * error_returns,Boolean PNTR status,ValNodePtr PNTR vnp_out)1462 SeedBioseq (BlastNet3BlockPtr blnet3blkptr, ValNodePtr *error_returns,
1463             Boolean PNTR status, ValNodePtr PNTR vnp_out)
1464 
1465 {
1466     BlastRequestPtr request = NULL;
1467     BlastSearchPtr search = NULL;
1468     BlastResponsePtr response = NULL;
1469     ValNodePtr node, vnp = NULL;
1470     /* Uint1 err_id; */
1471     BlastPhialignPtr bphp = NULL;
1472 
1473     search = BlastSearchNew();
1474     search->program = blnet3blkptr->prog_type;
1475     search->query = blnet3blkptr->bsp;
1476     search->database = blnet3blkptr->dbname;
1477     search->parameters = blnet3blkptr->parameters;
1478     search->mask = blnet3blkptr->mask;
1479     search->matrix = BlastMatrixToBlastNetMatrix(blnet3blkptr->blast_matrix);
1480     ValNodeAddPointer(&request, BlastRequest_search, search);
1481     *status = SubmitRequest(blnet3blkptr->bl3hptr, request, &response,
1482                             blnet3blkptr->callback, TRUE);
1483 
1484     blnet3blkptr->response = response;
1485     node = (BlastResponsePtr)
1486        GetResponsePtr(response, BlastResponse_phialign);
1487     if (node)
1488         bphp = (BlastPhialignPtr) node->data.ptrvalue;
1489 
1490     if (error_returns) {
1491         node = (BlastResponsePtr)
1492            GetResponsePtr(response, BlastResponse_error);
1493         if (node)
1494             ValNodeAddPointer(error_returns, BlastResponse_error,
1495                               node->data.ptrvalue);
1496     }
1497 
1498     /* Now re-creating ValNode from SeqAligns */
1499 
1500     while (response) {
1501         if (response->choice == BlastResponse_alignment) {
1502             ValNodeAddPointer(&vnp, BlastResponse_alignment,
1503                               response->data.ptrvalue);
1504         }
1505         response = response->next;
1506     }
1507     *vnp_out = vnp;
1508     response = blnet3blkptr->response;
1509 
1510     /* These four are not allocated here. */
1511     search->query = NULL;
1512     search->database = NULL;
1513     search->parameters = NULL;
1514     search->mask = NULL;
1515     BlastRequestFree(request);
1516 #if 0
1517     BlastDeleteUserErrorString(err_id);
1518 #endif
1519 
1520     return bphp;
1521 }
1522 
1523 NLM_EXTERN BlastPhialignPtr LIBCALL
SeedBioseqNetCore(BlastNet3Hptr bl3hp,BioseqPtr bsp,CharPtr program,CharPtr database,BLAST_OptionsBlkPtr options,ValNodePtr * other_returns,ValNodePtr * error_returns,NetProgressCallback callback,BLAST_MatrixPtr blast_matrix,Boolean PNTR ret_status,ValNodePtr PNTR vnp_out)1524 SeedBioseqNetCore(BlastNet3Hptr bl3hp, BioseqPtr bsp, CharPtr program,
1525                   CharPtr database, BLAST_OptionsBlkPtr options,
1526                   ValNodePtr *other_returns, ValNodePtr *error_returns,
1527                   NetProgressCallback callback, BLAST_MatrixPtr blast_matrix,
1528                   Boolean PNTR ret_status, ValNodePtr PNTR vnp_out)
1529 {
1530     BlastKABlkPtr ka_blk;
1531     BlastDbinfoPtr dbinfo;
1532     BlastMatrixPtr net_matrix;
1533     BLAST_MatrixPtr matrix;
1534     BlastNet3BlockPtr blnet;
1535     Boolean options_allocated = FALSE;
1536     CharPtr params_buffer;
1537     Int2 status;
1538     TxDfDbInfoPtr txdbinfo;
1539     ValNodePtr descr, mask;
1540 
1541     BlastPhialignPtr bphp = NULL;
1542 
1543 
1544     if (bl3hp == NULL || bsp == NULL || program == NULL || database == NULL)
1545         return NULL;
1546 
1547     if (error_returns)
1548         *error_returns = NULL;
1549 
1550     if (other_returns)
1551         *other_returns = NULL;
1552 
1553     /* If no options, use default. */
1554     if (options == NULL) {
1555         options = BLASTOptionNew(program, FALSE);
1556         options_allocated = TRUE;
1557     }
1558 
1559     status = BLASTOptionValidateEx(options, program, error_returns);
1560     if (status != 0) {	/* error messages in other_returns? */
1561         return NULL;
1562     }
1563 
1564     blnet = BlastNet3BlockNew(program, database);
1565     /*
1566        Remove the Seq-descr as this is not needed for
1567        BLASTing and the title often contains none-ASCII
1568        characters.  Keep the pointer and replace.
1569        */
1570     descr = bsp->descr;
1571     bsp->descr = NULL;
1572 
1573     blnet->bsp = bsp;
1574     blnet->parameters = BlastOptionsToParameters(options);
1575     if (options_allocated) {
1576         options = BLASTOptionDelete(options);
1577     }
1578 
1579     blnet->callback = callback;
1580     blnet->bl3hptr = bl3hp;
1581     blnet->blast_matrix = blast_matrix;
1582 
1583     bphp = SeedBioseq(blnet, error_returns, ret_status, vnp_out);
1584 
1585     if (other_returns) {
1586         *other_returns = NULL;
1587         mask = BlastGetMaskedLoc(blnet);
1588         if (mask)
1589             ValNodeLink(other_returns, mask);
1590         dbinfo = BlastGetDbInfo(blnet);
1591         txdbinfo = NetDbinfo2TxDbinfo(dbinfo);
1592         ValNodeAddPointer (other_returns, TXDBINFO, txdbinfo);
1593         dbinfo = BlastDbinfoFree(dbinfo);
1594         params_buffer = BlastGetParameterBuffer(blnet);
1595         ValNodeAddPointer(other_returns, TXPARAMETERS, params_buffer);
1596         ka_blk = BlastGetKaParams(blnet, FALSE);
1597         if (ka_blk)
1598             ValNodeAddPointer (other_returns, TXKABLK_NOGAP, ka_blk);
1599         ka_blk = BlastGetKaParams(blnet, TRUE);
1600         if (ka_blk)
1601             ValNodeAddPointer (other_returns, TXKABLK_GAP, ka_blk);
1602         net_matrix = NetBlastGetMatrix(blnet);
1603         matrix = BlastNetMatrixToBlastMatrix(net_matrix);
1604         net_matrix = BlastMatrixFree(net_matrix);
1605         if (matrix)
1606             ValNodeAddPointer (other_returns, TXMATRIX, matrix);
1607     }
1608 
1609     blnet = BlastNet3BlockDestruct(blnet);
1610 
1611     bsp->descr = descr;
1612 
1613     return bphp;
1614 }
1615 
1616 /* -------------------------------------------------------------- */
1617 
1618 NLM_EXTERN CharPtr LIBCALL
Blast3GetMotd(BlastNet3Hptr bl3hptr)1619 Blast3GetMotd(BlastNet3Hptr bl3hptr)
1620 
1621 {
1622 	BlastResponsePtr response=NULL;
1623 	BlastRequestPtr request=NULL;
1624 	CharPtr string;
1625 
1626         request = ValNodeNew(NULL);
1627         request->choice = BlastRequest_motd;
1628         SubmitRequest(bl3hptr, request, &response, NULL, TRUE);
1629         BlastRequestFree (request);
1630 	if (response == NULL || response->choice != BlastResponse_motd)
1631 		return NULL;
1632 
1633 	string = StringSave((CharPtr) response->data.ptrvalue);
1634 
1635 	BlastResponseFree(response);
1636 
1637 	return string;
1638 }
1639 
1640 NLM_EXTERN BlastDbinfoPtr LIBCALL
Blast3GetDbinfo(BlastNet3Hptr bl3hptr)1641 Blast3GetDbinfo(BlastNet3Hptr bl3hptr)
1642 
1643 {
1644 	BlastResponsePtr response=NULL;
1645 	BlastRequestPtr request=NULL;
1646 	BlastDbinfoPtr dbinfo;
1647 
1648         request = ValNodeNew(NULL);
1649         request->choice = BlastRequest_db_info;
1650         SubmitRequest(bl3hptr, request, &response, NULL, TRUE);
1651         BlastRequestFree (request);
1652 	if (response == NULL || response->choice != BlastResponse_db_info)
1653            return (BlastDbinfoPtr) BlastResponseFree(response);
1654 
1655 	dbinfo = (BlastDbinfoPtr) response->data.ptrvalue;
1656         MemFree(response);
1657 
1658 	return dbinfo;
1659 }
1660 
1661 NLM_EXTERN Boolean
SubmitRequest(BlastNet3Hptr bl3hptr,BlastRequestPtr blreqp,BlastResponsePtr PNTR response,NetProgressCallback callback,Boolean reestablish)1662 SubmitRequest(BlastNet3Hptr bl3hptr, BlastRequestPtr blreqp, BlastResponsePtr PNTR response, NetProgressCallback callback, Boolean reestablish)
1663 
1664 {
1665     Boolean status;
1666     Int2 index;
1667 
1668     for(index=0; index<BLAST_SERVER_RETRIES; index++)
1669     {
1670 
1671 	status = RealSubmitRequest(bl3hptr, blreqp, response, callback);
1672 
1673         if (status == TRUE)
1674             break;
1675 
1676 	if (reestablish)
1677 		ReestablishNetBlast(bl3hptr);
1678     }
1679 
1680     return status;
1681 
1682 }
1683 
1684 /*
1685 	Status returned indicates a (potential) error.  if not done, this is an error.
1686 */
1687 #define PRINT_DEBUG_ASN 0
1688 #if PRINT_DEBUG_ASN
1689 static	tmpi = 0;
1690 #endif
1691 
1692 static Boolean
RealSubmitRequest(BlastNet3Hptr bl3hptr,BlastRequestPtr blreqp,BlastResponsePtr PNTR response,NetProgressCallback callback)1693 RealSubmitRequest(BlastNet3Hptr bl3hptr, BlastRequestPtr blreqp, BlastResponsePtr PNTR response, NetProgressCallback callback)
1694 
1695 {
1696 	AsnIoPtr asnin, asnout;
1697 	Boolean cancel, done;
1698 	BlastResponsePtr bllist, blresp, head;
1699 #if PRINT_DEBUG_ASN
1700         AsnIoPtr asnout_test;
1701 	Char buf[1024];
1702 #endif
1703 
1704 	if (bl3hptr == NULL)
1705 		return FALSE;
1706 
1707 	if (response == NULL)
1708 		return FALSE;
1709 
1710 	asnout = bl3hptr->svcp->waip;
1711 	asnin = bl3hptr->svcp->raip;
1712 
1713 #if PRINT_DEBUG_ASN
1714         sprintf(buf, "request.%d.out", ++tmpi);
1715         asnout_test = AsnIoOpen(buf, "w");
1716 	BlastRequestAsnWrite(blreqp, asnout_test, NULL);
1717 #endif
1718 
1719 	done = BlastRequestAsnWrite(blreqp, asnout, NULL);
1720 	if (done == FALSE)
1721 		return FALSE;
1722 
1723 #if PRINT_DEBUG_ASN
1724         AsnIoReset(asnout_test);
1725         AsnIoClose(asnout_test);
1726 #endif
1727 	AsnIoReset(asnout);
1728 
1729 	head = NULL;
1730 	done = FALSE;
1731 	while (!done && (blresp = BlastResponseAsnRead(asnin, NULL)) != NULL)
1732 	{
1733 		switch (blresp->choice)
1734 		{
1735 		     case BlastResponse_done:
1736 			done = TRUE;
1737 		     case BlastResponse_queued:
1738 		     case BlastResponse_start:
1739 		     case BlastResponse_progress:
1740 			if (callback)
1741 			{
1742 				if (callback(blresp, &cancel) != TRUE)
1743 				{
1744 					done = TRUE;
1745 				}
1746 			}
1747 			blresp = BlastResponseFree(blresp);
1748 			break;
1749 
1750 		     case BlastResponse_init:
1751 		     case BlastResponse_motd:
1752 		     case BlastResponse_fini:
1753 			done = TRUE;
1754 
1755 		     default:
1756 			if (head == NULL)
1757 			{
1758 				head = blresp;
1759 				bllist = blresp;
1760 			}
1761 			else
1762 			{
1763 				bllist->next = blresp;
1764 				bllist = bllist->next;
1765 			}
1766 			break;
1767 		}
1768 	}
1769 	*response = head;
1770 	return done;
1771 }
1772 
1773 
BlastNetFetchCleanup(TNlmTls tls,VoidPtr ptr)1774 static void BlastNetFetchCleanup (TNlmTls tls, VoidPtr ptr)
1775 {
1776     BlastNetFetchStructPtr bnfsp = (BlastNetFetchStructPtr) ptr;
1777 
1778     if (bnfsp) {
1779         bnfsp->dbname = (CharPtr) MemFree(bnfsp->dbname);
1780         MemFree(bnfsp);
1781     }
1782     return;
1783 }
1784 
1785 /*
1786 	Checks the chain of BlastNetFetchStructPtr's for one
1787 	which belongs to the calling thread. If none is found,
1788 	NULL isreturned; otherwise the BlastNetFetchStructPtr is
1789 	returned.
1790 */
1791 static BlastNetFetchStructPtr
BlastNetFindFetchStruct(BlastNet3Hptr bl3hp,CharPtr dbname,Boolean is_na)1792 BlastNetFindFetchStruct(BlastNet3Hptr bl3hp, CharPtr dbname, Boolean is_na)
1793 
1794 {
1795 	BlastNetFetchStructPtr	bnfsp = NULL;
1796 
1797 	if (NlmTlsGetValue(blastnetfetch_tls, (VoidPtr *)(&bnfsp)))
1798 	{
1799 		if (bnfsp == NULL)
1800 		{
1801 			bnfsp = (BlastNetFetchStructPtr) MemNew(sizeof(BlastNetFetchStruct));
1802 			bnfsp->dbname = StringSave(dbname);
1803 			bnfsp->is_prot = (is_na == TRUE) ? FALSE : TRUE;
1804 			bnfsp->bl3hp = bl3hp;
1805 			bnfsp->BlastNetFetchState = BLASTNET_INIT;
1806 			NlmTlsSetValue(&blastnetfetch_tls, bnfsp,
1807 				BlastNetFetchCleanup);
1808 		}
1809 	}
1810 
1811 	return bnfsp;
1812 }
1813 
BlastNetInit(BlastNetFetchStructPtr bnfsp)1814 static Boolean BlastNetInit(BlastNetFetchStructPtr bnfsp)
1815 
1816 {
1817 	return TRUE;
1818 
1819 }
1820 
1821 
1822 /**********************************************************************
1823 
1824 	Fetches the Bioseq, based on the ordinal number of the
1825 	sequence in the database.
1826 
1827 ************************************************************************/
1828 
BlastNetBioseqFetchFunc(Pointer data)1829 static Int2 LIBCALLBACK BlastNetBioseqFetchFunc(Pointer data)
1830 {
1831 	Boolean status;
1832 	Char buffer[64];
1833 	OMProcControlPtr ompcp;
1834         ObjMgrProcPtr ompp;
1835 	OMUserDataPtr omdp;
1836 	SeqIdPtr sip, best_id;
1837 	BlastNetFetchStructPtr blfsp;
1838 	SeqEntryPtr sep;
1839 	BioseqPtr bsp, core_bsp;
1840 
1841 	ompcp = (OMProcControlPtr)data;
1842         ompp = ompcp->proc;
1843 
1844 	blfsp = BlastNetFindFetchStruct(NULL, NULL, FALSE);
1845 
1846 	if (blfsp->BlastNetFetchState == BLASTNET_INIT)
1847 	{
1848 		status = BlastNetInit(blfsp);
1849 		if (status == FALSE)
1850 			return OM_MSG_RET_OK;
1851 		blfsp->BlastNetFetchState = BLASTNET_READY;
1852 	}
1853 
1854 	sip = (SeqIdPtr) (ompcp->input_data);
1855 
1856 	best_id = SeqIdFindBest(sip, SEQID_GI);
1857 
1858 	if (best_id == NULL)
1859 	{
1860 		core_bsp = BioseqFindCore(sip);
1861 		if (core_bsp)
1862 			best_id = SeqIdFindBest(core_bsp->id, SEQID_GI);
1863 	}
1864 
1865 	if (best_id == NULL)
1866 		return OM_MSG_RET_OK;
1867 
1868 
1869 	/* A BioseqPtr is returned by this function. */
1870 	bsp = PrivateBlastGetBioseq(blfsp->bl3hp, blfsp->dbname, best_id, blfsp->is_prot);
1871         if (bsp == NULL)
1872         {
1873                 SeqIdWrite(best_id, buffer, PRINTID_FASTA_LONG, sizeof(buffer));
1874                 ErrPost(CTX_UNKNOWN, 1, "Unable to retrieve %s", buffer);
1875                 return OM_MSG_RET_ERROR;
1876         }
1877 	sep = SeqEntryNew();
1878 	sep->choice = 1;
1879 	sep->data.ptrvalue = bsp;
1880 	SeqMgrSeqEntry(SM_BIOSEQ, (Pointer)bsp, sep);
1881 	ompcp->output_data = (Pointer)bsp;
1882 	ompcp->output_entityID = ObjMgrGetEntityIDForChoice(sep);
1883 	omdp = ObjMgrAddUserData(ompcp->output_entityID, ompp->procid, OMPROC_FETCH, 0);
1884 
1885 	return OM_MSG_RET_DONE;
1886 }
1887 
1888 /*
1889 	Compare BlastNetFetchStructPtr structures with some traits.  TRUE if identical, otherwise
1890 	FALSE.
1891 */
1892 static Boolean
BlastNetFetchCompare(BlastNetFetchStructPtr blfsp1,BlastNet3Hptr bl3hp,CharPtr dbname,Boolean is_na)1893 BlastNetFetchCompare (BlastNetFetchStructPtr blfsp1, BlastNet3Hptr bl3hp, CharPtr dbname, Boolean is_na)
1894 
1895 {
1896 	if (blfsp1 == NULL)
1897 		return FALSE;
1898 
1899 	if (StringCmp(blfsp1->dbname, dbname) != 0)
1900 		return FALSE;
1901 	if (blfsp1->is_prot == is_na)
1902 		return FALSE;
1903 	if (blfsp1->bl3hp != bl3hp)
1904 		return FALSE;
1905 
1906 	return TRUE;
1907 }
1908 
1909 /*********************************************************************
1910 
1911 	Enables the fetching.  Initializes needed structures and calls
1912 	BlastNetInit.
1913 
1914 **********************************************************************/
1915 
1916 NLM_EXTERN Boolean LIBCALL
BlastNetBioseqFetchEnable(BlastNet3Hptr bl3hp,CharPtr dbname,Boolean is_na,Boolean now)1917 BlastNetBioseqFetchEnable(BlastNet3Hptr bl3hp, CharPtr dbname, Boolean is_na, Boolean now)
1918 
1919 {
1920         Boolean result;
1921         BlastNetFetchStructPtr blfsp = NULL;
1922         ObjMgrPtr omp;
1923         ObjMgrProcPtr ompp;
1924 
1925               /* check if already enabled ***/
1926 
1927         omp = ObjMgrGet();
1928         ompp = ObjMgrProcFind(omp, 0, "BlastNetBioseqFetch", OMPROC_FETCH);
1929         if (ompp != NULL)   /* already initialized */
1930 	{
1931 		blfsp = BlastNetFindFetchStruct(bl3hp, dbname, is_na);
1932 			if (BlastNetFetchCompare(blfsp, bl3hp, dbname, is_na) == FALSE)
1933 			{
1934 				blfsp->dbname = (CharPtr) MemFree(blfsp->dbname);
1935 				blfsp->dbname = StringSave(dbname);
1936 				blfsp->is_prot = (is_na == TRUE) ? FALSE : TRUE;
1937 				blfsp->bl3hp = bl3hp;
1938 
1939 			}
1940 	}
1941 	else
1942 	{
1943 		blfsp = BlastNetFindFetchStruct(bl3hp, dbname, is_na);
1944 
1945 		ObjMgrProcLoad(OMPROC_FETCH, "BlastNetBioseqFetch",
1946 			"BlastNetBioseqFetch", OBJ_SEQID, 0,OBJ_BIOSEQ,0,
1947                         (Pointer)blfsp, BlastNetBioseqFetchFunc, PROC_PRIORITY_DEFAULT);
1948 
1949 		blfsp->BlastNetFetchState = BLASTNET_INIT;
1950 	}
1951 
1952 	blfsp->ctr++;    /* count number of enables */
1953 
1954 	if (blfsp->BlastNetFetchState == BLASTNET_READY)
1955 	{
1956 			  return TRUE;
1957 	}
1958 
1959         if (now)
1960         {
1961 		result = BlastNetInit(blfsp);
1962                 if (! result)
1963                 {
1964                         return result;
1965                 }
1966 		blfsp->BlastNetFetchState = BLASTNET_READY;
1967         }
1968         else
1969 	{
1970 		blfsp->BlastNetFetchState = BLASTNET_INIT;
1971 	}
1972 
1973         return TRUE;
1974 }
1975 
1976 /*****************************************************************************
1977 *
1978 *		BlastNetBioseqFetchDisable()
1979 *
1980 *	Calls readdb_destruct if necessary to deallocate resources.
1981 *
1982 *****************************************************************************/
BlastNetBioseqFetchDisable(BlastNet3Hptr bl3hp,CharPtr dbname,Boolean is_na)1983 NLM_EXTERN void LIBCALL BlastNetBioseqFetchDisable(BlastNet3Hptr bl3hp, CharPtr dbname, Boolean is_na)
1984 {
1985         ObjMgrPtr omp;
1986         ObjMgrProcPtr ompp;
1987         BlastNetFetchStructPtr blfsp;
1988 
1989         omp = ObjMgrGet();
1990         ompp = ObjMgrProcFind(omp, 0, "BlastNetBioseqFetch", OMPROC_FETCH);
1991         if (ompp == NULL)   /* not initialized */
1992                 return;
1993 
1994 	blfsp = BlastNetFindFetchStruct(bl3hp, dbname, is_na);
1995 	if (! blfsp->ctr)   /* no enables active */
1996 		return;
1997 
1998 	blfsp->ctr--;
1999 	if (blfsp->ctr)   /* connection still pending */
2000 			  return;
2001 
2002         if (blfsp->BlastNetFetchState == BLASTNET_READY)
2003 	{
2004 		blfsp->BlastNetFetchState = BLASTNET_DISABLE;  /* not active */
2005 	}
2006 
2007         return;
2008 }
2009 
2010 /*
2011 	Runs a BLAST request and returns a SeqAlignPtr for formatting.
2012 	Note that the network connection must be established beforehand
2013 	(i.e., BlastNet3BlockPtr blnet should be initialized).
2014 */
2015 NLM_EXTERN SeqAlignPtr LIBCALL
BlastBioseqNet(BlastNet3Hptr bl3hp,BioseqPtr bsp,CharPtr program,CharPtr database,BLAST_OptionsBlkPtr options,ValNodePtr * other_returns,ValNodePtr * error_returns,NetProgressCallback callback)2016 BlastBioseqNet(BlastNet3Hptr bl3hp, BioseqPtr bsp, CharPtr program, CharPtr database, BLAST_OptionsBlkPtr options, ValNodePtr *other_returns, ValNodePtr *error_returns, NetProgressCallback callback)
2017 
2018 {
2019 	Boolean status;
2020 
2021 	return BlastBioseqNetCore(bl3hp, bsp, program, database, options, other_returns, error_returns, callback, NULL, &status);
2022 }
2023 
2024 NLM_EXTERN SeqAlignPtr LIBCALL
BlastSeqLocNet(BlastNet3Hptr bl3hp,SeqLocPtr slp,CharPtr program,CharPtr database,BLAST_OptionsBlkPtr options,ValNodePtr * other_returns,ValNodePtr * error_returns,NetProgressCallback callback)2025 BlastSeqLocNet(BlastNet3Hptr bl3hp, SeqLocPtr slp, CharPtr program, CharPtr database, BLAST_OptionsBlkPtr options, ValNodePtr *other_returns, ValNodePtr *error_returns, NetProgressCallback callback)
2026 
2027 {
2028 	Boolean status;
2029 
2030 	return BlastSeqLocNetCore(bl3hp, slp, program, database, options, other_returns, error_returns, callback, NULL, &status);
2031 }
2032 
2033 NLM_EXTERN SeqAlignPtr LIBCALL
MegaBlastSeqLocNetCore(BlastNet3Hptr bl3hp,SeqLocPtr slp,CharPtr program,CharPtr database,BLAST_OptionsBlkPtr options,ValNodePtr * other_returns,ValNodePtr * error_returns,NetProgressCallback callback,Boolean PNTR ret_status)2034 MegaBlastSeqLocNetCore(BlastNet3Hptr bl3hp, SeqLocPtr slp, CharPtr program, CharPtr database, BLAST_OptionsBlkPtr options, ValNodePtr *other_returns, ValNodePtr *error_returns, NetProgressCallback callback, Boolean PNTR ret_status)
2035 {
2036 	BlastKABlkPtr ka_blk;
2037 	BlastDbinfoPtr dbinfo;
2038 	BlastNet3BlockPtr blnet;
2039 	Boolean options_allocated = FALSE;
2040 	CharPtr params_buffer;
2041 	BlastMatrixPtr net_matrix;
2042 	BLAST_MatrixPtr matrix;
2043 	Int2 status;
2044 	SeqAlignPtr seqalign = NULL;
2045 	TxDfDbInfoPtr txdbinfo;
2046 	ValNodePtr mask;
2047 	SeqEntryPtr sep;
2048 	BioseqPtr bsp;
2049 	Uint2 entityID = 0;
2050 
2051 	if (bl3hp == NULL || slp == NULL || program == NULL || database == NULL)
2052 		return NULL;
2053 
2054 	if (error_returns)
2055 		*error_returns = NULL;
2056 
2057 	if (other_returns)
2058 		*other_returns = NULL;
2059 
2060 	/* If no options, use default. */
2061 	if (options == NULL)
2062 	{
2063 		options = BLASTOptionNew(program, FALSE);
2064 		options_allocated = TRUE;
2065 	}
2066 
2067 	status = BLASTOptionValidateEx(options, program, error_returns);
2068 	if (status != 0)
2069 	{	/* error messages in other_returns? */
2070 		return NULL;
2071 	}
2072 
2073 	blnet = BlastNet3BlockNew(program, database);
2074 
2075 	blnet->bsp_set = BioseqSetNew();
2076 	sep = NULL;
2077 	for (; slp; slp = slp->next) {
2078 	   bsp = BioseqLockById(SeqLocId(slp));
2079 	   ValNodeAddPointer(&sep, 1, bsp);
2080 	   SeqMgrSeqEntry(OBJ_BIOSEQ, (Pointer)bsp, sep);
2081 	   BioseqUnlock(bsp);
2082 	}
2083 
2084 	((BioseqSetPtr)blnet->bsp_set)->seq_set = sep;
2085 	entityID = ObjMgrRegister(OBJ_SEQENTRY, (Pointer)sep);
2086 	blnet->bsp = (BioseqPtr)sep->data.ptrvalue;
2087 	blnet->parameters = BlastOptionsToParameters(options);
2088         if (options_allocated)
2089         {
2090                 options = BLASTOptionDelete(options);
2091         }
2092 
2093 	blnet->callback = callback;
2094 	blnet->bl3hptr = bl3hp;
2095 
2096 	seqalign = BlastBioseq(blnet, error_returns, ret_status, other_returns);
2097 
2098         /* BlastBioseq saves the MegaBLAST endpoint alignments in error_returns
2099            since there is nowhere else to save them */
2100 
2101 
2102 	if (other_returns)
2103 	{
2104 		mask = BlastGetMaskedLoc(blnet);
2105 		if (mask)
2106 			ValNodeLink(other_returns, mask);
2107 		dbinfo = BlastGetDbInfo(blnet);
2108 		txdbinfo = NetDbinfo2TxDbinfo(dbinfo);
2109 		ValNodeAddPointer (other_returns, TXDBINFO, txdbinfo);
2110 		dbinfo = BlastDbinfoFree(dbinfo);
2111 		params_buffer = BlastGetParameterBuffer(blnet);
2112 		ValNodeAddPointer(other_returns, TXPARAMETERS, params_buffer);
2113 		ka_blk = BlastGetKaParams(blnet, FALSE);
2114 		if (ka_blk)
2115 			ValNodeAddPointer (other_returns, TXKABLK_NOGAP, ka_blk);
2116 		ka_blk = BlastGetKaParams(blnet, TRUE);
2117 		if (ka_blk)
2118 			ValNodeAddPointer (other_returns, TXKABLK_GAP, ka_blk);
2119 		net_matrix = NetBlastGetMatrix(blnet);
2120 		matrix = BlastNetMatrixToBlastMatrix(net_matrix);
2121 		net_matrix = BlastMatrixFree(net_matrix);
2122 		if (matrix)
2123 		   ValNodeAddPointer (other_returns, TXMATRIX, matrix);
2124 	}
2125 
2126 	blnet = BlastNet3BlockDestruct(blnet);
2127 
2128 	return seqalign;
2129 }
2130 
2131 NLM_EXTERN SeqAlignPtr LIBCALL
BlastBioseqNetCore(BlastNet3Hptr bl3hp,BioseqPtr bsp,CharPtr program,CharPtr database,BLAST_OptionsBlkPtr options,ValNodePtr * other_returns,ValNodePtr * error_returns,NetProgressCallback callback,BLAST_MatrixPtr blast_matrix,Boolean PNTR ret_status)2132 BlastBioseqNetCore(BlastNet3Hptr bl3hp, BioseqPtr bsp, CharPtr program, CharPtr database, BLAST_OptionsBlkPtr options, ValNodePtr *other_returns, ValNodePtr *error_returns, NetProgressCallback callback, BLAST_MatrixPtr blast_matrix, Boolean PNTR ret_status)
2133 
2134 {
2135 	BlastKABlkPtr ka_blk;
2136 	BlastDbinfoPtr dbinfo;
2137 	BlastMatrixPtr net_matrix;
2138 	BLAST_MatrixPtr matrix;
2139 	BlastNet3BlockPtr blnet;
2140 	Boolean options_allocated = FALSE;
2141 	CharPtr params_buffer=NULL;
2142 	Int2 status;
2143 	SeqAlignPtr seqalign = NULL;
2144 	TxDfDbInfoPtr txdbinfo;
2145 	ValNodePtr descr, mask;
2146 
2147 	if (bl3hp == NULL || bsp == NULL || program == NULL || database == NULL)
2148 		return NULL;
2149 
2150 	if (error_returns)
2151 		*error_returns = NULL;
2152 
2153 	if (other_returns)
2154 		*other_returns = NULL;
2155 
2156 	/* If no options, use default. */
2157 	if (options == NULL)
2158 	{
2159 		options = BLASTOptionNew(program, FALSE);
2160 		options_allocated = TRUE;
2161 	}
2162 
2163 	status = BLASTOptionValidateEx(options, program, error_returns);
2164 	if (status != 0)
2165 	{	/* error messages in other_returns? */
2166 		return NULL;
2167 	}
2168 
2169 	blnet = BlastNet3BlockNew(program, database);
2170 	/*
2171 	Remove the Seq-descr as this is not needed for
2172 	BLASTing and the title often contains none-ASCII
2173 	characters.  Keep the pointer and replace.
2174 	*/
2175 	descr = bsp->descr;
2176 	bsp->descr = NULL;
2177 
2178 	blnet->bsp = bsp;
2179 	blnet->parameters = BlastOptionsToParameters(options);
2180         if (options_allocated)
2181         {
2182                 options = BLASTOptionDelete(options);
2183         }
2184 
2185 	blnet->callback = callback;
2186 	blnet->bl3hptr = bl3hp;
2187 	blnet->blast_matrix = blast_matrix;
2188 
2189 	seqalign = BlastBioseq(blnet, error_returns, ret_status, NULL);
2190 	dbinfo = BlastGetDbInfo(blnet);
2191 	net_matrix = NetBlastGetMatrix(blnet);
2192 	params_buffer = BlastGetParameterBuffer(blnet);
2193 	if (other_returns)
2194 	{
2195 		*other_returns = NULL;
2196 		mask = BlastGetMaskedLoc(blnet);
2197 		if (mask)
2198 			ValNodeLink(other_returns, mask);
2199 		txdbinfo = NetDbinfo2TxDbinfo(dbinfo);
2200 		ValNodeAddPointer (other_returns, TXDBINFO, txdbinfo);
2201 		ValNodeAddPointer(other_returns, TXPARAMETERS, params_buffer);
2202 		params_buffer = NULL; /* Prevents freeing below. */
2203 		ka_blk = BlastGetKaParams(blnet, FALSE);
2204 		if (ka_blk)
2205 			ValNodeAddPointer (other_returns, TXKABLK_NOGAP, ka_blk);
2206 		ka_blk = BlastGetKaParams(blnet, TRUE);
2207 		if (ka_blk)
2208 			ValNodeAddPointer (other_returns, TXKABLK_GAP, ka_blk);
2209 		matrix = BlastNetMatrixToBlastMatrix(net_matrix);
2210 		if (matrix)
2211 			ValNodeAddPointer (other_returns, TXMATRIX, matrix);
2212 	}
2213 	/* The next three lines prevent memory leaks when other_returns is NULL. */
2214 	params_buffer = MemFree(params_buffer);
2215 	dbinfo = BlastDbinfoFree(dbinfo);
2216 	net_matrix = BlastMatrixFree(net_matrix);
2217 
2218 	blnet = BlastNet3BlockDestruct(blnet);
2219 
2220 	bsp->descr = descr;
2221 
2222 	return seqalign;
2223 }
2224 
2225 NLM_EXTERN BlastPartsPtr LIBCALL
BlastBioseqNetReturnParts(BlastNet3Hptr bl3hp,BioseqPtr bsp,CharPtr program,CharPtr database,BLAST_OptionsBlkPtr options,ValNodePtr * other_returns,ValNodePtr * error_returns,NetProgressCallback callback,BLAST_MatrixPtr blast_matrix,Boolean PNTR ret_status)2226 BlastBioseqNetReturnParts(BlastNet3Hptr bl3hp, BioseqPtr bsp, CharPtr program, CharPtr database, BLAST_OptionsBlkPtr options, ValNodePtr *other_returns, ValNodePtr *error_returns, NetProgressCallback callback, BLAST_MatrixPtr blast_matrix, Boolean PNTR ret_status)
2227 
2228 {
2229 	BlastKABlkPtr ka_blk;
2230 	BlastDbinfoPtr dbinfo;
2231 	BlastMatrixPtr net_matrix;
2232 	BLAST_MatrixPtr matrix;
2233 	BlastNet3BlockPtr blnet;
2234 	BlastPartsPtr blast_parts;
2235 	Boolean options_allocated = FALSE;
2236 	CharPtr params_buffer;
2237 	Int2 status;
2238 	TxDfDbInfoPtr txdbinfo;
2239 	ValNodePtr descr, mask;
2240 
2241 	if (bl3hp == NULL || bsp == NULL || program == NULL || database == NULL)
2242 		return NULL;
2243 
2244 	if (error_returns)
2245 		*error_returns = NULL;
2246 
2247 	if (other_returns)
2248 		*other_returns = NULL;
2249 
2250 	/* If no options, use default. */
2251 	if (options == NULL)
2252 	{
2253 		options = BLASTOptionNew(program, FALSE);
2254 		options_allocated = TRUE;
2255 	}
2256 
2257 	status = BLASTOptionValidateEx(options, program, error_returns);
2258 	if (status != 0)
2259 	{	/* error messages in other_returns? */
2260 		return NULL;
2261 	}
2262 
2263 	blnet = BlastNet3BlockNew(program, database);
2264 	/*
2265 	Remove the Seq-descr as this is not needed for
2266 	BLASTing and the title often contains none-ASCII
2267 	characters.  Keep the pointer and replace.
2268 	*/
2269 	descr = bsp->descr;
2270 	bsp->descr = NULL;
2271 
2272 	blnet->bsp = bsp;
2273 	blnet->parameters = BlastOptionsToParameters(options);
2274         if (options_allocated)
2275         {
2276                 options = BLASTOptionDelete(options);
2277         }
2278 
2279 	blnet->callback = callback;
2280 	blnet->bl3hptr = bl3hp;
2281 	blnet->blast_matrix = blast_matrix;
2282 
2283 	blast_parts = BlastBioseqByParts(blnet, error_returns, ret_status);
2284 	if (other_returns)
2285 	{
2286 		*other_returns = NULL;
2287 		mask = BlastGetMaskedLoc(blnet);
2288 		if (mask)
2289 			ValNodeLink(other_returns, mask);
2290 		dbinfo = BlastGetDbInfo(blnet);
2291 		txdbinfo = NetDbinfo2TxDbinfo(dbinfo);
2292 		ValNodeAddPointer (other_returns, TXDBINFO, txdbinfo);
2293 		dbinfo = BlastDbinfoFree(dbinfo);
2294 		params_buffer = BlastGetParameterBuffer(blnet);
2295 		ValNodeAddPointer(other_returns, TXPARAMETERS, params_buffer);
2296 		ka_blk = BlastGetKaParams(blnet, FALSE);
2297 		if (ka_blk)
2298 			ValNodeAddPointer (other_returns, TXKABLK_NOGAP, ka_blk);
2299 		ka_blk = BlastGetKaParams(blnet, TRUE);
2300 		if (ka_blk)
2301 			ValNodeAddPointer (other_returns, TXKABLK_GAP, ka_blk);
2302 		net_matrix = NetBlastGetMatrix(blnet);
2303 		matrix = BlastNetMatrixToBlastMatrix(net_matrix);
2304 		net_matrix = BlastMatrixFree(net_matrix);
2305 		if (matrix)
2306 			ValNodeAddPointer (other_returns, TXMATRIX, matrix);
2307 	}
2308 
2309 	blnet = BlastNet3BlockDestruct(blnet);
2310 
2311 	bsp->descr = descr;
2312 
2313 	return blast_parts;
2314 }
2315 
2316 NLM_EXTERN SeqAlignPtr LIBCALL
BlastSeqLocNetCore(BlastNet3Hptr bl3hp,SeqLocPtr slp,CharPtr program,CharPtr database,BLAST_OptionsBlkPtr options,ValNodePtr * other_returns,ValNodePtr * error_returns,NetProgressCallback callback,BLAST_MatrixPtr blast_matrix,Boolean PNTR status)2317 BlastSeqLocNetCore(BlastNet3Hptr bl3hp, SeqLocPtr slp, CharPtr program, CharPtr database, BLAST_OptionsBlkPtr options, ValNodePtr *other_returns, ValNodePtr *error_returns, NetProgressCallback callback, BLAST_MatrixPtr blast_matrix, Boolean PNTR status)
2318 
2319 {
2320 	SeqAlignPtr	seqalign = NULL;
2321 	ValNodePtr	vnp;
2322 
2323 	SeqPortPtr	spp;
2324 	Bioseq		bs;
2325 	BioseqPtr	bsp = &bs;
2326 	Int4		the_len, res_index;
2327 	Int2		residue;
2328 	ByteStorePtr	bp;
2329 	SeqLocPtr	whole_slp;
2330 	ValNodePtr	mask_loc;
2331 
2332 	/* get Bioseq by SeqLoc */
2333 
2334 
2335 	the_len = SeqLocLen(slp);
2336 	bp = BSNew((Uint4)the_len);
2337 
2338 	if (ISA_na(SeqLocMol(slp)))
2339 	    spp = SeqPortNewByLoc (slp, Seq_code_iupacna);
2340 	else
2341 	    spp = SeqPortNewByLoc (slp, Seq_code_iupacaa);
2342 
2343 	MemSet((Pointer)bsp, 0, sizeof(Bioseq));
2344 	bsp->length = (Int4)the_len;
2345 	bsp->repr = Seq_repr_raw;
2346 	bsp->mol = (Uint1) SeqLocMol(slp);
2347 	bsp->id = SeqLocId(slp);
2348 
2349 	if (ISA_na(bsp->mol))
2350 	    bsp->seq_data_type = Seq_code_iupacna;
2351 	else
2352 	    bsp->seq_data_type = Seq_code_iupacaa;
2353 
2354 	SeqPortSeek(spp, 0, SEEK_SET);
2355 	BSSeek(bp, 0, SEEK_SET);
2356 	for (res_index = 0; res_index < the_len; res_index++)
2357 	{
2358 	    residue = SeqPortGetResidue(spp);
2359 	    BSPutByte(bp, residue);
2360 	}
2361 	bsp->seq_data = (SeqDataPtr) bp;
2362 
2363 	SeqPortFree(spp);
2364 
2365 	/* perform search */
2366 
2367 	seqalign = BlastBioseqNetCore(bl3hp, bsp, program, database, options,
2368 		other_returns, error_returns, callback, NULL, status);
2369 
2370 	/* offset the alignment */
2371 
2372 	AdjustOffSetsInSeqAlign(seqalign, slp, NULL);
2373 
2374 	if (other_returns) {
2375 	    mask_loc = NULL;
2376 	    for (vnp=*other_returns; vnp; vnp = vnp->next)
2377 	    {
2378 		switch (vnp->choice) {
2379 		    case SEQLOC_MASKING_NOTSET:
2380 		    case SEQLOC_MASKING_PLUS1:
2381 		    case SEQLOC_MASKING_PLUS2:
2382 		    case SEQLOC_MASKING_PLUS3:
2383 		    case SEQLOC_MASKING_MINUS1:
2384 		    case SEQLOC_MASKING_MINUS2:
2385 		    case SEQLOC_MASKING_MINUS3:
2386 			ValNodeAddPointer(&mask_loc, vnp->choice, vnp->data.ptrvalue);
2387 			break;
2388 		    default:
2389 			break;
2390 		}
2391 	    }
2392 
2393 	    /* adjust offset in mask_loc */
2394 
2395 	    if (mask_loc && slp) {
2396 		SeqLocPtr	maskslp;
2397 		SeqIntPtr	masksip;
2398 		Int4	offset;
2399 		ValNodePtr	vnp;
2400 
2401 		whole_slp = NULL;
2402 
2403 		ValNodeAddPointer(&whole_slp, SEQLOC_WHOLE, SeqIdDup(SeqIdFindBest(bsp->id, SEQID_GI)));
2404 
2405 		offset = GetOffsetInLoc(slp, whole_slp, SEQLOC_START);
2406 
2407 		for (vnp = mask_loc; vnp; vnp = vnp->next) {
2408 
2409 		    for (maskslp = (SeqLocPtr) vnp->data.ptrvalue; maskslp; maskslp = maskslp->next) {
2410 			masksip = (SeqIntPtr) maskslp->data.ptrvalue;
2411 
2412 			masksip->from += offset;
2413 			masksip->to += offset;
2414 		    }
2415 		}
2416 	    }
2417 	}
2418 
2419 	return seqalign;
2420 }
2421 
2422 #if 0
2423 FILE *global_fp;
2424 #endif
2425 
2426 static  Boolean LIBCALLBACK
callback(BlastResponsePtr brp,Boolean PNTR cancel)2427 callback (BlastResponsePtr brp, Boolean PNTR cancel)
2428 
2429 {
2430 
2431 #if 0
2432         fprintf(global_fp, ".");
2433         fflush(global_fp);
2434 #endif
2435 	return TRUE;
2436 
2437 }
2438 
2439 static Boolean
TraditionalBlastReportEngine(SeqLocPtr slp,BioseqPtr bsp,BLAST_OptionsBlkPtr options,BlastNet3Hptr bl3hp,CharPtr program,CharPtr database,Boolean html,FILE * outfp,Boolean verbose,Uint4 print_options,Uint4 align_options,Int4 number_of_descriptions,Int4 number_of_alignments,Int4Ptr number_of_hits,Uint4 overview)2440 TraditionalBlastReportEngine(SeqLocPtr slp, BioseqPtr bsp, BLAST_OptionsBlkPtr options, BlastNet3Hptr bl3hp, CharPtr program, CharPtr database, Boolean html, FILE *outfp, Boolean verbose, Uint4 print_options, Uint4 align_options, Int4 number_of_descriptions, Int4 number_of_alignments, Int4Ptr number_of_hits, Uint4 overview)
2441 
2442 {
2443     BlastDbinfoPtr dbinfo;
2444     BlastKABlkPtr ka_params=NULL, ka_params_gap=NULL;
2445     BlastPruneSapStructPtr prune;
2446     BLAST_MatrixPtr matrix;
2447     Int4Ptr PNTR txmatrix;
2448     Boolean query_is_na, db_is_na;
2449     Boolean status;
2450     CharPtr params_buffer=NULL;
2451     Int4 number_of_hits_private=0, length;
2452     SeqAlignPtr seqalign = NULL, sap, next_seqalign;
2453     SeqAnnotPtr seqannot=NULL;
2454     TxDfDbInfoPtr tx_dbinfo=NULL, tx_dbinfo_head;
2455     ValNodePtr mask_loc, mask_loc_start, other_returns, error_returns, vnp, vnp1=NULL;
2456     Uint1 align_type;
2457     Uint1 f_order[FEATDEF_ANY], g_order[FEATDEF_ANY];
2458 
2459     SeqLocPtr tmp_slp;
2460     DenseSegPtr dsp, next_dsp;
2461     MegaBlastResultsPtr mb_results = NULL;
2462 
2463     MemSet((Pointer)(g_order), 0, (size_t)(FEATDEF_ANY* sizeof(Uint1)));
2464     MemSet((Pointer)(f_order), 0, (size_t)(FEATDEF_ANY* sizeof(Uint1)));
2465 
2466     if (bsp == NULL && slp == NULL)
2467         return FALSE;
2468 
2469     if (bl3hp == NULL || program == NULL || database == NULL || outfp == NULL)
2470         return FALSE;
2471 
2472     align_type = BlastGetTypes(program, &query_is_na, &db_is_na);
2473 #if 0
2474     global_fp = outfp;
2475 #endif
2476 
2477     init_buff_ex(85);
2478     dbinfo = BlastRequestDbInfo(bl3hp, database, !db_is_na);
2479     if (dbinfo)
2480         PrintDbInformationBasic(database, !db_is_na, 70, dbinfo->definition, dbinfo->number_seqs, dbinfo->total_length, outfp, html);
2481     dbinfo = BlastDbinfoFree(dbinfo);
2482     free_buff();
2483 
2484     fprintf(outfp, "Searching");
2485 
2486     if (bsp) {
2487         seqalign = BlastBioseqNetCore(bl3hp, bsp, program, database, options,
2488 				      &other_returns, &error_returns, callback,
2489 				      NULL, &status);
2490     } else if (options->is_megablast_search)
2491         seqalign = MegaBlastSeqLocNetCore(bl3hp, slp, program, database, options, &other_returns, &error_returns, callback, &status);
2492     else
2493         seqalign = BlastSeqLocNetCore(bl3hp, slp, program, database, options, &other_returns, &error_returns, callback, NULL, &status);
2494 
2495     fprintf(outfp, " done\n");
2496 
2497     if (overview) {
2498         fprintf(outfp, "\n\n");
2499         if (bsp)
2500             length= bsp->length;
2501         else
2502             length= SeqLocLen(slp);
2503 
2504         VSMakeSeqLoc(&seqalign, &vnp1, length, NULL);
2505         VSPrintOverviewFromSeqLocs(vnp1, length, outfp);
2506     }
2507 
2508     BlastErrorPrintExtra(error_returns, TRUE, outfp);
2509 
2510     mask_loc = NULL;
2511     matrix = NULL;
2512     txmatrix = NULL;
2513     for (vnp=other_returns; vnp; vnp = vnp->next) {
2514         switch (vnp->choice) {
2515         case TXDBINFO:
2516             tx_dbinfo = (TxDfDbInfoPtr) vnp->data.ptrvalue;
2517             break;
2518         case TXKABLK_NOGAP:
2519             ka_params = (BlastKABlkPtr) vnp->data.ptrvalue;
2520             break;
2521         case TXKABLK_GAP:
2522             ka_params_gap = (BlastKABlkPtr) vnp->data.ptrvalue;
2523             break;
2524         case TXPARAMETERS:
2525             params_buffer = (CharPtr) vnp->data.ptrvalue;
2526             break;
2527         case TXMATRIX:
2528             /* This function should not use matrix ??? */
2529            matrix = (BLAST_MatrixPtr) vnp->data.ptrvalue;
2530            if (matrix)
2531               txmatrix = BlastMatrixToTxMatrix(matrix);
2532             /*BLAST_MatrixDestruct(matrix);*/
2533             break;
2534         case SEQLOC_MASKING_NOTSET:
2535         case SEQLOC_MASKING_PLUS1:
2536         case SEQLOC_MASKING_PLUS2:
2537         case SEQLOC_MASKING_PLUS3:
2538         case SEQLOC_MASKING_MINUS1:
2539         case SEQLOC_MASKING_MINUS2:
2540         case SEQLOC_MASKING_MINUS3:
2541 	   if (!options->is_megablast_search)
2542 	      ValNodeAddPointer(&mask_loc, vnp->choice, vnp->data.ptrvalue);
2543             break;
2544         case BlastResponse_mbalign:
2545            mb_results = (MegaBlastResultsPtr) vnp->data.ptrvalue;
2546            break;
2547         default:
2548             break;
2549         }
2550     }
2551 
2552     NlmMutexLockEx(&formating_mutex);
2553 
2554     ReadDBBioseqFetchEnable ("blastcl3", database, db_is_na, TRUE);
2555 
2556     if (mb_results) {
2557        MegaBlastHitPtr mb_hit;
2558        /* Results come as alignment endpoints only from Mega BLAST */
2559        for (mb_hit=mb_results->mbhits; mb_hit; mb_hit = mb_hit->next) {
2560           fprintf(outfp, "%s\t%s\t%d\t%d\t%d\t%d\t%d\n", mb_hit->id1,
2561                   mb_hit->id2, mb_hit->query_offset, mb_hit->subject_offset,
2562                   mb_hit->query_end, mb_hit->subject_end, mb_hit->score);
2563        }
2564        MegaBlastResultsFree(mb_results);
2565     }
2566 
2567 
2568     tmp_slp = slp;
2569 
2570     while (seqalign) {
2571        if (!options->is_megablast_search)
2572           next_seqalign = NULL;
2573        else {
2574           sap = seqalign;
2575           while (sap != NULL) {
2576              if (sap->next != NULL) {
2577                 dsp = (DenseSegPtr) (sap->segs);
2578                 next_dsp = (DenseSegPtr) (sap->next->segs);
2579 
2580                 if (SeqIdComp(dsp->ids, next_dsp->ids) != SIC_YES) {
2581                    next_seqalign = sap->next;
2582                    sap->next = NULL;
2583                 }
2584              } else
2585                 next_seqalign = NULL;
2586              sap = sap->next;
2587           }
2588 
2589           dsp = (DenseSegPtr) (seqalign->segs);
2590           while (tmp_slp && SeqIdComp(dsp->ids, SeqLocId(tmp_slp)) != SIC_YES)
2591              tmp_slp = tmp_slp->next;
2592           if (tmp_slp == NULL) /* Should never happen */
2593              break;
2594           bsp = BioseqLockById(SeqLocId(tmp_slp));
2595           init_buff_ex(85);
2596           AcknowledgeBlastQuery(bsp, 70, outfp, FALSE, html);
2597           free_buff();
2598           BioseqUnlock(bsp);
2599        }
2600 
2601        seqannot = SeqAnnotNew();
2602        seqannot->type = 2;
2603        AddAlignInfoToSeqAnnot(seqannot, align_type);
2604        seqannot->data = seqalign;
2605        prune = BlastPruneHitsFromSeqAlign(seqalign, number_of_descriptions, NULL);
2606        ObjMgrSetHold();
2607        init_buff_ex(85);
2608        PrintDefLinesFromSeqAlign(prune->sap, 80, outfp, print_options, FIRST_PASS, NULL);
2609        free_buff();
2610 
2611        prune = BlastPruneHitsFromSeqAlign(seqalign, number_of_alignments, prune);
2612        seqannot->data = prune->sap;
2613        if (align_options & TXALIGN_MASTER)
2614           ShowTextAlignFromAnnot(seqannot, 60, outfp, f_order, g_order, align_options, txmatrix, mask_loc, NULL);
2615        else
2616           ShowTextAlignFromAnnot(seqannot, 60, outfp, f_order, g_order, align_options, txmatrix, mask_loc, FormatScoreFunc);
2617        seqannot->data = seqalign;
2618        number_of_hits_private = prune->original_number;
2619        prune = BlastPruneSapStructDestruct(prune);
2620        ObjMgrClearHold();
2621        ObjMgrFreeCache(0);
2622 
2623        if (options->is_megablast_search)
2624           tmp_slp = tmp_slp->next;
2625 
2626        if (seqannot)
2627           seqannot = SeqAnnotFree(seqannot);
2628 
2629        seqalign = next_seqalign;
2630     }
2631     mask_loc_start = mask_loc;
2632     while (mask_loc) {
2633         SeqLocSetFree((SeqLocPtr) mask_loc->data.ptrvalue);
2634         mask_loc = mask_loc->next;
2635     }
2636     ValNodeFree(mask_loc_start);
2637 
2638     BLAST_MatrixDestruct(matrix);
2639     if (txmatrix)
2640        txmatrix = TxMatrixDestruct(txmatrix);
2641 
2642     if (verbose) {
2643        init_buff_ex(85);
2644        tx_dbinfo_head = tx_dbinfo;
2645        while (tx_dbinfo) {
2646 	  PrintDbReport(tx_dbinfo, 70, outfp);
2647 	  tx_dbinfo = tx_dbinfo->next;
2648        }
2649        tx_dbinfo_head = TxDfDbInfoDestruct(tx_dbinfo_head);
2650 
2651        if (ka_params) {
2652 	  PrintKAParameters(ka_params->lambda, ka_params->k, ka_params->h, 70, outfp, FALSE);
2653 	  MemFree(ka_params);
2654        }
2655 
2656        if (ka_params_gap) {
2657 	  PrintKAParameters(ka_params_gap->lambda, ka_params_gap->k, ka_params_gap->h, 70, outfp, TRUE);
2658 	  MemFree(ka_params_gap);
2659        }
2660        PrintTildeSepLines(params_buffer, 70, outfp);
2661        MemFree(params_buffer);
2662        free_buff();
2663     }
2664 
2665     ReadDBBioseqFetchDisable();
2666     other_returns = ValNodeFree(other_returns);
2667 
2668     NlmMutexUnlock(formating_mutex);
2669 
2670     if (number_of_hits)
2671        *number_of_hits = number_of_hits_private;
2672     return status;
2673 }
2674 /*
2675   Formats a 'traditional' BLAST report.
2676 */
2677 
2678 NLM_EXTERN Boolean LIBCALL
TraditionalBlastReport(BioseqPtr bsp,BLAST_OptionsBlkPtr options,BlastNet3Hptr bl3hp,CharPtr program,CharPtr database,Boolean html,FILE * outfp,Boolean verbose,Uint4 print_options,Uint4 align_options,Int4 number_of_descriptions,Int4 number_of_alignments,Int4Ptr number_of_hits)2679 TraditionalBlastReport(BioseqPtr bsp, BLAST_OptionsBlkPtr options, BlastNet3Hptr bl3hp, CharPtr program, CharPtr database, Boolean html, FILE *outfp, Boolean verbose, Uint4 print_options, Uint4 align_options, Int4 number_of_descriptions, Int4 number_of_alignments, Int4Ptr number_of_hits)
2680 
2681 {
2682 	return TraditionalBlastReportEngine(NULL, bsp, options, bl3hp, program, database, html, outfp, verbose, print_options, align_options, number_of_descriptions, number_of_alignments, number_of_hits, BLAST_OVERVIEW_NONE);
2683 }
2684 
2685 NLM_EXTERN Boolean LIBCALL
TraditionalBlastReportExtra(BioseqPtr bsp,BLAST_OptionsBlkPtr options,BlastNet3Hptr bl3hp,CharPtr program,CharPtr database,Boolean html,FILE * outfp,Boolean verbose,Uint4 print_options,Uint4 align_options,Int4 number_of_descriptions,Int4 number_of_alignments,Int4Ptr number_of_hits,Uint4 overview)2686 TraditionalBlastReportExtra(BioseqPtr bsp, BLAST_OptionsBlkPtr options, BlastNet3Hptr bl3hp, CharPtr program, CharPtr database, Boolean html, FILE *outfp, Boolean verbose, Uint4 print_options, Uint4 align_options, Int4 number_of_descriptions, Int4 number_of_alignments, Int4Ptr number_of_hits, Uint4 overview)
2687 
2688 {
2689 	return TraditionalBlastReportEngine(NULL, bsp, options, bl3hp, program, database, html, outfp, verbose, print_options, align_options, number_of_descriptions, number_of_alignments, number_of_hits, overview);
2690 }
2691 
2692 
2693 NLM_EXTERN Boolean LIBCALL
TraditionalBlastReportLoc(SeqLocPtr slp,BLAST_OptionsBlkPtr options,BlastNet3Hptr bl3hp,CharPtr program,CharPtr database,Boolean html,FILE * outfp,Boolean verbose,Uint4 print_options,Uint4 align_options,Int4 number_of_descriptions,Int4 number_of_alignments,Int4Ptr number_of_hits)2694 TraditionalBlastReportLoc(SeqLocPtr slp, BLAST_OptionsBlkPtr options, BlastNet3Hptr bl3hp, CharPtr program, CharPtr database, Boolean html, FILE *outfp, Boolean verbose, Uint4 print_options, Uint4 align_options, Int4 number_of_descriptions, Int4 number_of_alignments, Int4Ptr number_of_hits)
2695 
2696 {
2697 	return TraditionalBlastReportEngine(slp, NULL, options, bl3hp, program, database, html, outfp, verbose, print_options, align_options, number_of_descriptions, number_of_alignments, number_of_hits, BLAST_OVERVIEW_NONE);
2698 }
2699 
2700 NLM_EXTERN Boolean LIBCALL
TraditionalBlastReportLocExtra(SeqLocPtr slp,BLAST_OptionsBlkPtr options,BlastNet3Hptr bl3hp,CharPtr program,CharPtr database,Boolean html,FILE * outfp,Boolean verbose,Uint4 print_options,Uint4 align_options,Int4 number_of_descriptions,Int4 number_of_alignments,Int4Ptr number_of_hits,Uint4 overview)2701 TraditionalBlastReportLocExtra(SeqLocPtr slp, BLAST_OptionsBlkPtr options, BlastNet3Hptr bl3hp, CharPtr program, CharPtr database, Boolean html, FILE *outfp, Boolean verbose, Uint4 print_options, Uint4 align_options, Int4 number_of_descriptions, Int4 number_of_alignments, Int4Ptr number_of_hits, Uint4 overview)
2702 
2703 {
2704 	return TraditionalBlastReportEngine(slp, NULL, options, bl3hp, program, database, html, outfp, verbose, print_options, align_options, number_of_descriptions, number_of_alignments, number_of_hits, overview);
2705 }
2706 
2707 /* Fills in other options based upon "other_options" string in BlastParametersPtr. */
2708 
2709 static void
s_parseOtherOptions(char * other_options,BLAST_OptionsBlkPtr options)2710 s_parseOtherOptions(char* other_options, BLAST_OptionsBlkPtr options)
2711 {
2712 
2713     char* opt_str = "t";
2714     char* *values;
2715     Int4 index;
2716 
2717     ASSERT(options);
2718 
2719     if (other_options == NULL)
2720         return;
2721 
2722     if(!BlastParseInputString(other_options, opt_str, &values, NULL))
2723             return;
2724 
2725     index = BlastGetLetterIndex(opt_str, 't');
2726 
2727     if(values[index] != NULL) {
2728           options->tweak_parameters = atoi(values[index]);
2729     }
2730 
2731     return;
2732 }
2733 
2734 
2735 /*
2736         Converst the BlastParametersPtr (used by network service) to
2737         BLAST_OptionsBlkPtr (used by blast).
2738 */
2739 #ifndef SPLIT_BLAST
2740 NLM_EXTERN BLAST_OptionsBlkPtr
parametersToOptions(BlastParametersPtr parameters,CharPtr program,ValNodePtr PNTR error_return)2741 parametersToOptions (BlastParametersPtr parameters, CharPtr program, ValNodePtr PNTR error_return)
2742 
2743 {
2744         BLAST_OptionsBlkPtr options;
2745         Int2 status;
2746 
2747         if (program == NULL)
2748                 return NULL;
2749 
2750         if (parameters == NULL) {
2751             options = BLASTOptionNew(program, TRUE);
2752         } else {
2753                 options = BLASTOptionNew(program, (Boolean) parameters->gapped_alignment);
2754                 options->threshold_second = parameters->second_threshold;
2755                 if (parameters->Cutoff_cutoff)
2756                 {
2757                         if (parameters->Cutoff_cutoff->choice == Cutoff_cutoff_evalue)
2758                                 options->expect_value = parameters->Cutoff_cutoff->data.realvalue;
2759                         else if (parameters->Cutoff_cutoff->choice == Cutoff_cutoff_score)
2760                                 options->cutoff_s = parameters->Cutoff_cutoff->data.intvalue;
2761                 }
2762                 if (parameters->Cutoff2_cutoff2)
2763                 {
2764                         if (parameters->Cutoff2_cutoff2->choice == Cutoff2_cutoff2_evalue)
2765                                 options->e2 = parameters->Cutoff2_cutoff2->data.realvalue;
2766                         else if (parameters->Cutoff2_cutoff2->choice == Cutoff2_cutoff2_score)
2767                                 options->cutoff_s2 = parameters->Cutoff2_cutoff2->data.intvalue;
2768                 }
2769                 /* compensates for client not providing this.  Remove this at some point? */
2770                 if (parameters->hitlist_size != 0)
2771                         options->hitlist_size = parameters->hitlist_size;
2772                 options->penalty = parameters->nucl_penalty;
2773                 options->reward = parameters->nucl_reward;
2774                 options->gap_open = parameters->gap_open;
2775                 options->gap_extend = parameters->gap_extend;
2776                 /* compensates for client not providing this.  Remove this at some point? */
2777                 if (parameters->genetic_code != 0)
2778                         options->genetic_code = parameters->genetic_code;
2779                 /* compensates for client not providing this.  Remove this at some point? */
2780                 if (parameters->db_genetic_code != 0)
2781                         options->db_genetic_code = parameters->db_genetic_code;
2782 
2783                 options->filter = parameters->low_complexity_filtering;
2784                 options->ethresh = parameters->ethresh;
2785                 options->maxNumPasses = parameters->max_num_passes;
2786                 options->pseudoCountConst = parameters->pseudo_count_const;
2787 
2788 		if (parameters->gifile)
2789 		{
2790                 	options->gifile = StringSave(parameters->gifile);
2791 		}
2792                 options->gilist = parameters->gilist;
2793 		if (parameters->matrix)
2794 		{
2795 			options->matrix = (CharPtr) MemFree(options->matrix);
2796                 	options->matrix = StringSave(parameters->matrix);
2797 		}
2798 		if (parameters->filter_string)
2799 		{
2800                		options->filter_string = (CharPtr) MemFree(options->filter_string);
2801                		options->filter_string = StringSave(parameters->filter_string);
2802 		}
2803                 if (parameters->entrez_query)
2804                     options->entrez_query = StringSave(parameters->entrez_query);
2805                 /* compensates for client not providing this.  Remove this at some point? */
2806 		if (parameters->word_size)
2807                     options->wordsize = parameters->word_size;
2808 		if (parameters->db_length)
2809                     options->db_length = parameters->db_length;
2810 		if (parameters->searchsp_eff)
2811                     options->searchsp_eff = parameters->searchsp_eff;
2812 		if (parameters->hsp_range_max)
2813                     options->hsp_range_max = parameters->hsp_range_max;
2814 		if (parameters->block_width || parameters->is_megablast)
2815                    /* In case of megablast, block_width should be 0 by default
2816                       instead of 20 returned from BLASTOptionNew */
2817                     options->block_width = parameters->block_width;
2818 		if (parameters->perform_culling)
2819                     options->perform_culling = parameters->perform_culling;
2820 		if (parameters->strand_option)
2821                     options->strand_option = parameters->strand_option;
2822 
2823                 if(parameters->phi_pattern) {
2824                     options->phi_pattern = StringSave(parameters->phi_pattern);
2825                     options->isPatternSearch = TRUE;
2826                 }
2827         	options->use_real_db_size = parameters->use_real_db_size;
2828 #if 0
2829                 if(parameters->db_dir_prefix) {
2830                     options->db_dir_prefix = StringSave(parameters->db_dir_prefix);
2831 		}
2832 #endif
2833         	options->use_best_align = parameters->use_best_align;
2834 
2835                 if(parameters->required_start != 0)
2836                     options->required_start = parameters->required_start;
2837                 if(parameters->required_end != 0)
2838                     options->required_end = parameters->required_end;
2839 
2840         	options->is_rps_blast = parameters->is_rps_blast;
2841                 /* this value may be overwritten by the call to s_parseOtherOptions
2842                   if different information is contained there. */
2843                 options->tweak_parameters = parameters->tweak_parameters;
2844 
2845                 options->smith_waterman = parameters->smith_waterman;
2846 		options->is_megablast_search = parameters->is_megablast;
2847                 options->query_lcase_mask =
2848                    (SeqLocPtr) parameters->query_lcase_mask;
2849                 if (parameters->endpoint_results)
2850                    options->no_traceback = 1;
2851                 options->perc_identity = (FloatLo) parameters->percent_identity;
2852                 options->first_db_seq = parameters->first_db_seq;
2853                 options->final_db_seq = parameters->final_db_seq;
2854                 options->window_size = parameters->window_size;
2855                 if (options->window_size == 0 && StringCmp(program, "blastn"))
2856                     options->window_size = 40;
2857                 options->mb_template_length = parameters->mb_template_length;
2858                 options->mb_disc_type = parameters->mb_disc_type;
2859                 if (options->mb_template_length > 0 &&
2860                     (options->gap_open > 0 || options->gap_extend > 0)) {
2861                    options->mb_use_dyn_prog = TRUE;
2862                 }
2863 
2864                 /* Parses out tweak_parameters. */
2865                 s_parseOtherOptions(parameters->other_options, options);
2866         }
2867 
2868 	if ((status = BLASTOptionValidateEx(options, program, error_return))) {
2869             return NULL;
2870 	}
2871 
2872         return options;
2873 }
2874 /* This function is interface to the Entrez2 engine. It may be used
2875    to get list of gis corresponding to the Entrez Boolean string or
2876    just number of such hits in the Entrez database */
2877 
BLASTGetUidsFromQuery(CharPtr query,Int4Ptr PNTR uids,Boolean is_na,Boolean count_only,BlastError ** blast_err)2878 NLM_EXTERN Int4 BLASTGetUidsFromQuery(CharPtr       query,
2879 				      Int4Ptr PNTR  uids,
2880                                       Boolean       is_na,
2881 				      Boolean       count_only,
2882 				      BlastError ** blast_err)
2883 {
2884     Entrez2ReplyPtr e2ry;
2885     Entrez2RequestPtr  e2rq;
2886     E2ReplyPtr e2rp;
2887     Int4 count = 0;
2888     Entrez2BooleanReplyPtr e2br;
2889     Entrez2IdListPtr e2idlist;
2890 
2891     if(uids != NULL)
2892         *uids = NULL;
2893 
2894     EntrezSetProgramName ("BLAST API");
2895     /* EntrezSetServer ("www.ncbi.nlm.nih.gov", 80,
2896                      "/entrez/utils/entrez2server.fcgi"); */
2897 
2898     e2rq = EntrezCreateBooleanRequest (!count_only, FALSE,
2899                                        is_na? "Nucleotide" : "Protein",
2900                                        query, 0, 0, NULL, 0, 0);
2901 
2902     e2ry = EntrezSynchronousQuery (e2rq);
2903 
2904     if (e2ry == NULL) {
2905 	if ( blast_err ) {
2906 	    *blast_err = BlastErrorNew();
2907 
2908 	    (*blast_err)->level = Blast_error_level_error;
2909 	    (*blast_err)->msg   = StrSave("NULL returned from EntrezSynchronousQuery()");
2910 	} else {
2911 	    ErrPostEx(SEV_ERROR, 0, 0,
2912 		      "NULL returned from EntrezSynchronousQuery()");
2913 	}
2914 
2915         return -1;
2916     }
2917 
2918     if((e2rp = e2ry->reply) == NULL) {
2919 	if ( blast_err ) {
2920 	    *blast_err = BlastErrorNew();
2921 
2922 	    (*blast_err)->level = Blast_error_level_error;
2923 	    (*blast_err)->msg   = StrSave("Invalid ASN.1: E2ReplyPtr==NULL");
2924 	} else {
2925 	    ErrPostEx(SEV_ERROR, 0, 0, "Invalid ASN.1: E2ReplyPtr==NULL");
2926 	}
2927         return -1;
2928     }
2929 
2930     switch(e2rp->choice) {
2931     case E2Reply_error:
2932 	if ( blast_err ) {
2933 	    const char * msg1 = "Error in request: ";
2934 	    const char * msg2 = (CharPtr) e2rp->data.ptrvalue;
2935 	    char       * msg3 = 0;
2936 
2937 	    int msglen1 = strlen(msg1);
2938 	    int msglen2 = strlen(msg2);
2939 
2940 	    msg3 = MemNew(msglen1 + msglen2 + 1);
2941 
2942 	    if ( msg3 ) {
2943 		strcpy(msg3, msg1);
2944 		strcat(msg3, msg2);
2945 
2946 		*blast_err = BlastErrorNew();
2947 
2948 		(*blast_err)->level = Blast_error_level_error;
2949 		(*blast_err)->msg   = msg3;
2950 	    }
2951 	} else {
2952 	    ErrPostEx(SEV_ERROR, 0, 0, "Error in request: %s", (CharPtr) e2rp->data.ptrvalue);
2953 	}
2954         count = -1;
2955         break;
2956     case E2Reply_eval_boolean:
2957         e2br = (Entrez2BooleanReplyPtr) e2rp->data.ptrvalue;
2958         count = e2br->count;
2959         if((e2idlist = e2br->uids) != NULL) {
2960             count = e2idlist->num;
2961             if(uids != NULL) {
2962                 *uids = (Int4Ptr) MemNew(sizeof(Int4)*count);
2963                 BSSeek((ByteStorePtr) e2idlist->uids, 0, SEEK_SET);
2964                 BSRead((ByteStorePtr) e2idlist->uids, *uids, sizeof(Int4)*count);
2965             }
2966         }
2967         break;
2968     default:
2969 	if ( blast_err ) {
2970 	    const char * msg1 = "Invalid reply type from the server: ";
2971 	    const char * msg2 = (CharPtr) e2rp->data.ptrvalue;
2972 	    char       * msg3 = 0;
2973 
2974 	    int msglen1 = strlen(msg1);
2975 	    int msglen2 = strlen(msg2);
2976 
2977 	    msg3 = MemNew(msglen1 + msglen2 + 1);
2978 
2979 	    if ( msg3 ) {
2980 		strcpy(msg3, msg1);
2981 		strcat(msg3, msg2);
2982 
2983 		*blast_err = BlastErrorNew();
2984 
2985 		(*blast_err)->level = Blast_error_level_error;
2986 		(*blast_err)->msg   = msg3;
2987 	    }
2988 	} else {
2989 	    ErrPostEx(SEV_ERROR, 0, 0, "Invalid reply type from the server: %d", e2rp->choice);
2990 	}
2991         count = -1;
2992         break;
2993     }
2994 
2995     Entrez2ReplyFree(e2ry);
2996     Entrez2RequestFree(e2rq);
2997 
2998     return count;
2999 }
3000 #endif
3001 
3002