1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2003-2012 Match Grun and the Claws Mail team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 /*
21  * Functions to define an address query (a request).
22  */
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <glib.h>
27 #include <pthread.h>
28 
29 #include "mgutils.h"
30 #include "addrquery.h"
31 #include "utils.h"
32 
33 /**
34  * Query list for tracking current queries.
35  */
36 static GList *_requestList_ = NULL;
37 
38 /**
39  * Mutex to protect list from multiple threads.
40  */
41 static pthread_mutex_t _requestListMutex_ = PTHREAD_MUTEX_INITIALIZER;
42 
43 /**
44  * Current query ID. This is incremented for each query request created.
45  */
46 static gint _currentQueryID_ = 0;
47 
48 /**
49  * Clear the query.
50  * \param req Request query object.
51  */
qryreq_clear(QueryRequest * req)52 static void qryreq_clear( QueryRequest *req ) {
53 	GList *node;
54 
55 	cm_return_if_fail( req != NULL );
56 	g_free( req->searchTerm );
57 	req->queryID = 0;
58 	req->searchType = ADDRSEARCH_NONE;
59 	req->searchTerm = NULL;
60 	req->callBackEnd = NULL;
61 	req->callBackEntry = NULL;
62 
63 	/* Empty the list */
64 	node = req->queryList;
65 	while( node ) {
66 		node->data = NULL;
67 		node = g_list_next( node );
68 	}
69 	g_list_free( req->queryList );
70 	req->queryList = NULL;
71 }
72 
73 /**
74  * Free query.
75  * \param req Request query object.
76  */
qryreq_free(QueryRequest * req)77 static void qryreq_free( QueryRequest *req ) {
78 	cm_return_if_fail( req != NULL );
79 	qryreq_clear( req );
80 	g_free( req );
81 }
82 
83 /**
84  * Specify search type.
85  * \param req   Request query object.
86  * \param value Type.
87  */
qryreq_set_search_type(QueryRequest * req,const AddrSearchType value)88 void qryreq_set_search_type( QueryRequest *req, const AddrSearchType value ) {
89 	cm_return_if_fail( req != NULL );
90 	req->searchType = value;
91 }
92 
93 /**
94  * Add address query object to request.
95  * \param req  Request query object.
96  * \param aqo  Address query object that performs the search.
97  */
qryreq_add_query(QueryRequest * req,AddrQueryObject * aqo)98 void qryreq_add_query( QueryRequest *req, AddrQueryObject *aqo ) {
99 	cm_return_if_fail( req != NULL );
100 	cm_return_if_fail( aqo != NULL );
101 	req->queryList = g_list_append( req->queryList, aqo );
102 }
103 
104 /**
105  * Add query to list.
106  *
107  * \param searchTerm    Search term. A private copy will be made.
108  * \param callBackEnd   Callback function that will be called when query
109  * 			terminates.
110  * \param callBackEntry Callback function that will be called after each
111  * 			address entry has been read.
112  * \return Initialize query request object.
113  */
qrymgr_add_request(const gchar * searchTerm,void * callBackEnd,void * callBackEntry)114 QueryRequest *qrymgr_add_request(
115 	const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
116 {
117 	QueryRequest *req;
118 
119 	req = g_new0( QueryRequest, 1 );
120 	req->searchTerm = g_strdup( searchTerm );
121 	req->callBackEnd = callBackEnd;
122 	req->callBackEntry = callBackEntry;
123 	req->timeStart = time( NULL );
124 	req->queryList = NULL;
125 
126 	/* Insert in head of list */
127 	pthread_mutex_lock( & _requestListMutex_ );
128 	req->queryID = ++_currentQueryID_;
129 	_requestList_ = g_list_prepend( _requestList_, req );
130 	pthread_mutex_unlock( & _requestListMutex_ );
131 
132 	return req;
133 }
134 
135 /**
136  * Find query in list.
137  * \param  queryID ID of query to find.
138  * \return Query object, or <i>NULL</i> if not found.
139  */
qrymgr_find_request(const gint queryID)140 QueryRequest *qrymgr_find_request( const gint queryID ) {
141 	QueryRequest *req;
142 	QueryRequest *q;
143 	GList *node;
144 
145 	pthread_mutex_lock( & _requestListMutex_ );
146 	req = NULL;
147 	node = _requestList_;
148 	while( node ) {
149 		q = node->data;
150 		if( q->queryID == queryID ) {
151 			req = q;
152 			break;
153 		}
154 		node = g_list_next( node );
155 	}
156 	pthread_mutex_unlock( & _requestListMutex_ );
157 
158 	return req;
159 }
160 
161 /**
162  * Delete specified query.
163  * \param  queryID ID of query to retire.
164  */
qrymgr_delete_request(const gint queryID)165 void qrymgr_delete_request( const gint queryID ) {
166 	QueryRequest *req;
167 	GList *node, *nf;
168 
169 	pthread_mutex_lock( & _requestListMutex_ );
170 
171 	/* Find node */
172 	nf = NULL;
173 	node = _requestList_;
174 	while( node ) {
175 		req = node->data;
176 		if( req->queryID == queryID ) {
177 			nf = node;
178 			qryreq_free( req );
179 			break;
180 		}
181 		node = g_list_next( node );
182 	}
183 
184 	/* Free link element and associated query */
185 	if( nf ) {
186 		_requestList_ = g_list_remove_link( _requestList_, nf );
187 		g_list_free_1( nf );
188 	}
189 
190 	pthread_mutex_unlock( & _requestListMutex_ );
191 }
192 
193 /**
194  * Initialize query manager.
195  */
qrymgr_initialize(void)196 void qrymgr_initialize( void ) {
197 	_requestList_ = NULL;
198 }
199 
200 /**
201  * Free all queries.
202  */
qrymgr_free_all_request(void)203 static void qrymgr_free_all_request( void ) {
204 	QueryRequest *req;
205 	GList *node;
206 
207 	pthread_mutex_lock( & _requestListMutex_ );
208 	node = _requestList_;
209 	while( node ) {
210 		req = node->data;
211 		qryreq_free( req );
212 		node->data = NULL;
213 		node = g_list_next( node );
214 	}
215 	g_list_free( _requestList_ );
216 	_requestList_ = NULL;
217 	pthread_mutex_unlock( & _requestListMutex_ );
218 }
219 
220 /**
221  * Teardown query manager.
222  */
qrymgr_teardown(void)223 void qrymgr_teardown( void ) {
224 	qrymgr_free_all_request();
225 }
226 
227 /*
228 * End of Source.
229 */
230 
231 
232