1
/* $Id: hspfilter_queue.c,v 1.1 2009/06/01 13:54:56 maning Exp $
2
* ===========================================================================
5
* National Center for Biotechnology Information
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.
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
22
* Please cite the author in any work or product based on this material.
24
* ===========================================================================
30
/** @file hspfilter_queue.c
31
* Default implementation of the BlastHSPWriter interface to save hits from
32
* a BLAST search, and subsequently return them in sorted order.
35
#ifndef SKIP_DOXYGEN_PROCESSING
36
static char const rcsid[] =
37
"$Id: hspfilter_queue.c,v 1.1 2009/06/01 13:54:56 maning Exp $";
38
#endif /* SKIP_DOXYGEN_PROCESSING */
42
#include <algo/blast/core/blast_hspstream.h>
43
#include <algo/blast/api/hspfilter_queue.h>
44
//#include <algo/blast/core/blast_util.h>
46
/** Data structure used by the writer */
47
typedef struct BlastHSPQueueData {
48
ListNode * start; /**< First element of the queue */
49
ListNode * end; /**< First element of the queue */
50
Boolean writeDone; /**< Has writing to this stream been finished? */
51
TNlmMutex lock; /**< reading/writing lock */
52
TNlmSemaphore sema; /**< Semaphore for reading */
55
/*************************************************************/
56
/** The following are implementations for BlastHSPWriter ADT */
58
/** Perform pre-run stage-specific initialization
59
* @param data The internal data structure [in][out]
60
* @param results The HSP results to operate on [in]
63
s_BlastHSPQueueInit(void* data, BlastHSPResults* results)
65
BlastHSPQueueData * q_data = data;
69
/** Perform post-run clean-ups
70
* @param data The buffered data structure [in]
71
* @param results The HSP results to propagate [in][out]
74
s_BlastHSPQueueFinal(void* data, BlastHSPResults* results)
76
BlastHSPQueueData * q_data = data;
78
NlmMutexLockEx(&q_data->lock);
79
q_data->writeDone = TRUE;
80
NlmSemaPost(q_data->sema);
81
NlmMutexUnlock(q_data->lock);
86
/** Perform writing task
87
* ownership of the HSP list and sets the dereferenced pointer to NULL.
88
* @param data To store results to [in][out]
89
* @param hsp_list Pointer to the HSP list to save in the queue. [in]
92
s_BlastHSPQueueRun(void* data, BlastHSPList* hsp_list)
94
BlastHSPQueueData * q_data = data;
99
if (hsp_list->hspcnt == 0) {
100
Blast_HSPListFree(hsp_list);
104
if (q_data->writeDone)
107
NlmMutexLockEx(&q_data->lock);
108
q_data->end = ListNodeAddPointer(&q_data->end, 0, (void *)hsp_list);
110
q_data->start = q_data->end;
112
NlmSemaPost(q_data->sema);
113
NlmMutexUnlock(q_data->lock);
119
* @param writer The writer to free [in]
124
s_BlastHSPQueueFree(BlastHSPWriter* writer)
127
BlastHSPQueueData *q_data = writer->data;
129
NlmSemaDestroy(q_data->sema);
130
NlmMutexDestroy(q_data->lock);
132
for(p = q_data->start; p; p = p->next) {
133
p->ptr = (void *) Blast_HSPListFree((BlastHSPList*) p->ptr);
135
q_data->start = ListNodeFree(q_data->start);
141
/** create the writer
142
* @param params Pointer to the hit paramters [in]
143
* @param query_info BlastQueryInfo (not used) [in]
148
s_BlastHSPQueueNew(void* params, BlastQueryInfo* query_info)
150
BlastHSPWriter * writer = NULL;
151
BlastHSPQueueData * data = NULL;
153
/* allocate space for writer */
154
writer = malloc(sizeof(BlastHSPWriter));
156
/* fill up the function pointers */
157
writer->InitFnPtr = &s_BlastHSPQueueInit;
158
writer->FinalFnPtr = &s_BlastHSPQueueFinal;
159
writer->FreeFnPtr = &s_BlastHSPQueueFree;
160
writer->RunFnPtr = &s_BlastHSPQueueRun;
162
/* allocate for data structure */
163
writer->data = calloc(1,sizeof(BlastHSPQueueData));
165
data->sema = NlmSemaInit(0);
170
/*************************************************************/
171
/** The following are exported functions to be used by APP */
174
BlastHSPQueueParamsNew()
180
BlastHSPQueueParamsFree(BlastHSPQueueParams* opts)
186
BlastHSPQueueInfoNew(BlastHSPQueueParams* params) {
187
BlastHSPWriterInfo * writer_info =
188
malloc(sizeof(BlastHSPWriterInfo));
189
writer_info->NewFnPtr = &s_BlastHSPQueueNew;
190
writer_info->params = params;
194
/************************************************************/
195
/** The follwoing is added to support queue implementation */
197
int BlastHSPQueueRead(void* data, BlastHSPList** hsp_list_out)
199
BlastHSPQueueData* q_data = (BlastHSPQueueData*) data;
200
int status = kBlastHSPStream_Error;
203
NlmMutexLockEx(&q_data->lock);
205
if (!q_data->writeDone) {
206
while (!q_data->writeDone && !q_data->start) {
207
/* Decrement the semaphore count to 0, then wait for it to be
208
* incremented. Note that mutex must be locked whenever the
209
* contents of the stream are checked, but it must be unlocked
210
* for the semaphore wait. */
211
NlmMutexUnlock(q_data->lock);
212
NlmSemaWait(q_data->sema);
213
NlmMutexLockEx(&q_data->lock);
217
if (!q_data->start) {
218
/* Nothing in the queue, but no more writing to the queue is expected. */
219
*hsp_list_out = NULL;
220
status = kBlastHSPStream_Eof;
222
ListNode* start_node = q_data->start;
224
*hsp_list_out = (BlastHSPList*) start_node->ptr;
226
q_data->start = start_node->next;
227
start_node->next = NULL;
228
ListNodeFree(start_node);
231
status = kBlastHSPStream_Success;
234
NlmMutexUnlock(q_data->lock);