PageRenderTime 35ms CodeModel.GetById 2ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/fbus/fbus_service_manager_daemon.c

http://ftk.googlecode.com/
C | 399 lines | 300 code | 70 blank | 29 comment | 43 complexity | 41251563313e95e0a7d663db683c1869 MD5 | raw file
  1/*
  2 * File:    fbus_service_manager_daemon.c
  3 * Author:  Li XianJing <xianjimli@hotmail.com>
  4 * Brief:   service manager daemon.
  5 *
  6 * Copyright (c) 2009 - 2010  Li XianJing <xianjimli@hotmail.com>
  7 *
  8 * Licensed under the Academic Free License version 2.1
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2 of the License, or
 13 * (at your option) any later version.
 14 *
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 */
 24
 25/*
 26 * History:
 27 * ================================================================
 28 * 2010-07-25 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_log.h"
 33#include <sys/wait.h>
 34#include <sys/types.h>
 35#include "ftk_globals.h"
 36#include "ftk_main_loop.h"
 37#include "fbus_service.h"
 38#include "ftk_source_timer.h"
 39#include "fbus_service_infos.h"
 40#include "fbus_service_manager.h"
 41
 42typedef struct _PrivInfo
 43{
 44	int quiting;
 45	FBusServiceInfos* service_infos;
 46}PrivInfo;
 47
 48static int process_start(const char* exec)
 49{
 50	int pid = fork();
 51
 52	if(pid == 0)
 53	{
 54		execl(exec, exec, NULL);
 55	}
 56
 57	return pid;
 58}
 59
 60static Ret process_stop(int pid)
 61{
 62	int ret = kill(pid, SIGTERM);
 63
 64	return ret == 0 ? RET_OK : RET_FAIL;
 65}
 66
 67static int process_wait_child(void)
 68{
 69	int status = 0;
 70
 71	return waitpid(-1, &status, WNOHANG);
 72}
 73
 74static const char* fbus_service_service_manager_get_name(FBusService* thiz)
 75{
 76	return FBUS_SERVICE_MANAGER_NAME;
 77}
 78
 79static Ret fbus_service_service_manager_handle_get_nr(FBusService* thiz, int* nr)
 80{
 81	DECL_PRIV(thiz, priv);
 82	*nr = fbus_service_infos_get_nr(priv->service_infos);
 83
 84	return RET_OK;
 85}
 86
 87static Ret fbus_service_service_manager_handle_get(FBusService* thiz, int i, FBusServiceInfo* info)
 88{
 89	DECL_PRIV(thiz, priv);
 90
 91	FBusServiceInfo* found = fbus_service_infos_get(priv->service_infos, i);
 92	return_val_if_fail(found != NULL, RET_FAIL);
 93
 94	memcpy(info, found, sizeof(FBusServiceInfo));
 95
 96	return RET_OK;
 97}
 98
 99static Ret fbus_service_service_manager_handle_stop(FBusService* thiz, const char* name)
100{
101	DECL_PRIV(thiz, priv);
102	FBusServiceInfo* info = fbus_service_infos_find(priv->service_infos, name);
103	return_val_if_fail(info != NULL, RET_NOT_FOUND);
104
105	if(info->status == FBUS_SERVICE_STARTED)
106	{
107		process_stop(info->pid);
108		info->status = FBUS_SERVICE_STOPING;
109	}
110
111	return RET_OK;
112}
113
114static Ret fbus_service_service_manager_handle_start(FBusService* thiz, const char* name)
115{
116	DECL_PRIV(thiz, priv);
117	FBusServiceInfo* info = fbus_service_infos_find(priv->service_infos, name);
118	return_val_if_fail(info != NULL, RET_NOT_FOUND);
119
120	if(info->status == FBUS_SERVICE_STOPED)
121	{
122		process_start(info->exec);
123		info->status = FBUS_SERVICE_STARTING;
124	}
125
126	return RET_OK;
127}
128
129static Ret fbus_service_service_manager_handle_query(FBusService* thiz, const char* name, FBusServiceInfo* info)
130{
131	DECL_PRIV(thiz, priv);
132	FBusServiceInfo* found = fbus_service_infos_find(priv->service_infos, name);
133	return_val_if_fail(found != NULL, RET_NOT_FOUND);
134
135	memcpy(info, found, sizeof(FBusServiceInfo));
136
137	return RET_OK;
138}
139
140static Ret fbus_service_service_manager_handle_register(FBusService* thiz, const char* name, 
141	FBusServiceInfo* info, const char* host, int pid)
142{
143	DECL_PRIV(thiz, priv);
144	FBusServiceInfo* found = fbus_service_infos_find(priv->service_infos, name);
145	return_val_if_fail(found != NULL, RET_NOT_FOUND);
146	return_val_if_fail(host != NULL, RET_FAIL);
147
148	found->pid = pid;
149	ftk_strncpy(found->host, host, sizeof(found->host)-1);
150
151	found->status = FBUS_SERVICE_STARTED;
152	memcpy(info, found, sizeof(FBusServiceInfo));
153
154	return RET_OK;
155}
156
157static Ret fbus_service_service_manager_handle_unregister(FBusService* thiz, const char* name,
158	const char* host, int pid)
159{
160	DECL_PRIV(thiz, priv);
161	FBusServiceInfo* found = fbus_service_infos_find(priv->service_infos, name);
162	return_val_if_fail(found != NULL, RET_NOT_FOUND);
163	return_val_if_fail(found->pid == pid && strcmp(found->host, host) == 0, RET_FAIL);
164	return_val_if_fail(host != NULL, RET_FAIL);
165
166	found->status = FBUS_SERVICE_STOPED;
167
168	return RET_OK;
169}
170
171static Ret fbus_service_service_manager_check_children(FBusService* thiz)
172{
173	int pid = 0;
174	DECL_PRIV(thiz, priv);
175
176	do
177	{
178		int i = 0;
179		int nr = 0;
180		
181		if((pid = process_wait_child()) <= 0) break;
182		
183		nr = fbus_service_infos_get_nr(priv->service_infos);
184		for(i = 0; i < nr; i++)
185		{
186			FBusServiceInfo* info = fbus_service_infos_get(priv->service_infos, i);
187			if(info->pid == pid)
188			{
189				info->status = FBUS_SERVICE_STOPED;
190				ftk_logd("%s: service %s %d stoped.\n", __func__, info->name, info->pid);
191
192				if(!priv->quiting)
193				{
194					if(info->start_type == FBUS_SERVICE_RUN_FOREVER)
195					{
196						process_start(info->exec);
197						info->status = FBUS_SERVICE_STARTING;
198						ftk_logd("%s: restart service %s\n", __func__, info->name);
199					}
200				}
201				break;
202			}
203		}
204	}while(pid > 0);
205
206	return RET_OK;
207}
208
209static Ret fbus_service_service_manager_handle_request(FBusService* thiz, int client_id, FBusParcel* req_resp)
210{
211	int pid = 0;
212	Ret ret = RET_OK;
213	int req_code = fbus_parcel_get_int(req_resp);
214
215	switch(req_code)
216	{
217		case FBUS_SERVICE_MANAGER_REQ_GET:
218		{
219			FBusServiceInfo info = {0};
220			int index = fbus_parcel_get_int(req_resp);
221			
222			ret = fbus_service_service_manager_handle_get(thiz, index, &info);
223			
224			fbus_parcel_reset(req_resp);
225			fbus_parcel_write_int(req_resp, ret);
226			if(ret == RET_OK)
227			{
228				fbus_parcel_write_data(req_resp, &info, sizeof(info));
229			}
230			break;
231		}
232		case FBUS_SERVICE_MANAGER_REQ_GET_NR:
233		{
234			int nr = 0;
235			
236			ret = fbus_service_service_manager_handle_get_nr(thiz, &nr);
237			
238			fbus_parcel_reset(req_resp);
239			fbus_parcel_write_int(req_resp, ret);
240			fbus_parcel_write_int(req_resp, nr);
241			break;
242		}
243		case FBUS_SERVICE_MANAGER_REQ_STOP:
244		{
245			const char* name = fbus_parcel_get_string(req_resp);
246			
247			ret = fbus_service_service_manager_handle_stop(thiz, name);
248			
249			fbus_parcel_reset(req_resp);
250			fbus_parcel_write_int(req_resp, ret);
251			break;
252		}
253		case FBUS_SERVICE_MANAGER_REQ_START:
254		{
255			const char* name = fbus_parcel_get_string(req_resp);
256			
257			ret = fbus_service_service_manager_handle_start(thiz, name);
258			
259			fbus_parcel_reset(req_resp);
260			fbus_parcel_write_int(req_resp, ret);
261			break;
262		}
263		case FBUS_SERVICE_MANAGER_REQ_QUERY:
264		{
265			FBusServiceInfo info = {0};
266			const char* name = fbus_parcel_get_string(req_resp);
267			
268			ret = fbus_service_service_manager_handle_query(thiz, name, &info);
269			
270			fbus_parcel_reset(req_resp);
271			fbus_parcel_write_int(req_resp, ret);
272			if(ret == RET_OK)
273			{
274				fbus_parcel_write_data(req_resp, &info, sizeof(info));
275			}
276			break;
277		}
278		case FBUS_SERVICE_MANAGER_REQ_REGISTER:
279		{
280			FBusServiceInfo info = {0};
281			const char* name = fbus_parcel_get_string(req_resp);
282			const char* host = fbus_parcel_get_string(req_resp);
283			pid = fbus_parcel_get_int(req_resp);
284
285			ret = fbus_service_service_manager_handle_register(thiz, name, &info, host, pid);
286
287			fbus_parcel_reset(req_resp);
288			fbus_parcel_write_int(req_resp, ret);
289			if(ret == RET_OK)
290			{
291				fbus_parcel_write_data(req_resp, &info, sizeof(info));
292			}
293			break;
294		}
295		case FBUS_SERVICE_MANAGER_REQ_UNREGISTER:
296		{
297			const char* name = fbus_parcel_get_string(req_resp);
298			const char* host = fbus_parcel_get_string(req_resp);
299			pid = fbus_parcel_get_int(req_resp);
300			
301			ret = fbus_service_service_manager_handle_unregister(thiz, name, host, pid);
302			
303			fbus_parcel_reset(req_resp);
304			fbus_parcel_write_int(req_resp, ret);
305			break;
306		}
307		default:
308		{
309			ftk_logd("%s: not supported: %d\n", __func__, req_code);
310			break;
311		}
312	}
313
314	fbus_service_service_manager_check_children(thiz);
315
316	return RET_OK;
317}
318
319static void fbus_service_service_manager_destroy(FBusService* thiz)
320{
321	if(thiz != NULL)
322	{
323		int i = 0;
324		int nr = 0;
325		DECL_PRIV(thiz, priv);
326
327		priv->quiting = 1;
328		nr = fbus_service_infos_get_nr(priv->service_infos);
329		for(i = 0; i < nr; i++)
330		{
331			FBusServiceInfo* info = fbus_service_infos_get(priv->service_infos, i);
332			if(info->status == FBUS_SERVICE_STARTED)
333			{
334				process_stop(info->pid);
335			}
336		}
337		fbus_service_service_manager_check_children(thiz);
338		fbus_service_infos_destroy(priv->service_infos);
339		FTK_FREE(thiz);
340	}
341
342	return;
343}
344
345static FBusService* fbus_service_service_manager_create(void)
346{
347	FBusService* thiz = FTK_ZALLOC(sizeof(FBusService) + sizeof(PrivInfo));
348
349	if(thiz != NULL)
350	{
351		int i = 0;
352		int nr = 0;
353		DECL_PRIV(thiz, priv);
354		FtkSource* timer = NULL;
355		char path[FTK_MAX_PATH + 1] = {0};
356
357		thiz->get_name = fbus_service_service_manager_get_name;
358		thiz->handle_request = fbus_service_service_manager_handle_request;
359		thiz->destroy = fbus_service_service_manager_destroy;
360
361		priv->service_infos = fbus_service_infos_create(16);
362		ftk_snprintf(path, sizeof(path)-1, DATA_DIR"/services");
363		fbus_service_infos_load_dir(priv->service_infos, path);
364	
365		fbus_service_register(thiz);
366		timer = ftk_source_timer_create(5000, (FtkTimer)fbus_service_service_manager_check_children, thiz);
367		ftk_main_loop_add_source(ftk_default_main_loop(), timer);
368
369		nr = fbus_service_infos_get_nr(priv->service_infos);
370		for(i = 0; i < nr; i++)
371		{
372			FBusServiceInfo* info = fbus_service_infos_get(priv->service_infos, i);
373			if(info->start_type == FBUS_SERVICE_START_ON_LOAD)
374			{
375				process_start(info->exec);
376				info->status = FBUS_SERVICE_STARTING;
377				ftk_logd("%s: launch %s:%s\n", __func__, info->name, info->exec);
378			}
379		}
380	}
381
382	return thiz;
383}
384
385int main(int argc, char* argv[])
386{
387	fbus_service_init(argc, argv);
388
389	if(fbus_service_service_manager_create() != NULL)
390	{
391		fbus_service_run();
392	}
393	else
394	{
395		ftk_loge("Create service manager failed.\n");
396	}
397
398	return 0;
399}