/services/fconf/fconf_service.c
C | 328 lines | 246 code | 53 blank | 29 comment | 63 complexity | 4a202b22bb7370f7ad3bf8d536dbf9e8 MD5 | raw file
1/* 2 * File: fconf_service.c 3 * Author: Li XianJing <xianjimli@hotmail.com> 4 * Brief: FConf Service. 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-08-01 Li XianJing <xianjimli@hotmail.com> created 29 * 30 */ 31 32#include "fconf.h" 33#include "fconf_xml.h" 34#include "fconf_share.h" 35#include "ftk_globals.h" 36#include "ftk_main_loop.h" 37#include "fconf_service.h" 38#include "ftk_source_timer.h" 39 40typedef struct _PrivInfo 41{ 42 FConf* impl; 43 int client_id; 44 int peer_id; /*the port in client side*/ 45 FBusParcel* parcel; 46 FtkSource* timer_save; 47}PrivInfo; 48 49static Ret fconf_marshal_lock(FBusService* thiz, FBusParcel* req_resp) 50{ 51 Ret ret = RET_FAIL; 52 DECL_PRIV(thiz, priv); 53 return_val_if_fail(priv != NULL && priv->impl != NULL && req_resp != NULL, RET_FAIL); 54 55 if((ret = fconf_lock(priv->impl)) == RET_OK) 56 { 57 fbus_parcel_reset(req_resp); 58 fbus_parcel_write_int(req_resp, ret); 59 } 60 61 return ret; 62} 63 64static Ret fconf_marshal_unlock(FBusService* thiz, FBusParcel* req_resp) 65{ 66 Ret ret = RET_FAIL; 67 DECL_PRIV(thiz, priv); 68 return_val_if_fail(priv != NULL && priv->impl != NULL && req_resp != NULL, RET_FAIL); 69 70 if((ret = fconf_unlock(priv->impl)) == RET_OK) 71 { 72 fbus_parcel_reset(req_resp); 73 fbus_parcel_write_int(req_resp, ret); 74 } 75 76 return ret; 77} 78 79static Ret fconf_marshal_remove(FBusService* thiz, FBusParcel* req_resp) 80{ 81 const char* xpath = {0}; 82 83 Ret ret = RET_FAIL; 84 DECL_PRIV(thiz, priv); 85 return_val_if_fail(priv != NULL && priv->impl != NULL && req_resp != NULL, RET_FAIL); 86 87 xpath = fbus_parcel_get_string(req_resp); 88 89 if((ret = fconf_remove(priv->impl, xpath)) == RET_OK) 90 { 91 fbus_parcel_reset(req_resp); 92 fbus_parcel_write_int(req_resp, ret); 93 } 94 95 return ret; 96} 97 98static Ret fconf_marshal_set(FBusService* thiz, FBusParcel* req_resp) 99{ 100 const char* xpath = {0}; 101 const char* value = {0}; 102 103 Ret ret = RET_FAIL; 104 DECL_PRIV(thiz, priv); 105 return_val_if_fail(priv != NULL && priv->impl != NULL && req_resp != NULL, RET_FAIL); 106 107 xpath = fbus_parcel_get_string(req_resp); 108 value = fbus_parcel_get_string(req_resp); 109 110 if((ret = fconf_set(priv->impl, xpath, value)) == RET_OK) 111 { 112 fbus_parcel_reset(req_resp); 113 fbus_parcel_write_int(req_resp, ret); 114 } 115 116 return ret; 117} 118 119static Ret fconf_marshal_get(FBusService* thiz, FBusParcel* req_resp) 120{ 121 const char* xpath = {0}; 122 char* value = {0}; 123 124 Ret ret = RET_FAIL; 125 DECL_PRIV(thiz, priv); 126 return_val_if_fail(priv != NULL && priv->impl != NULL && req_resp != NULL, RET_FAIL); 127 128 xpath = fbus_parcel_get_string(req_resp); 129 130 if((ret = fconf_get(priv->impl, xpath, &value)) == RET_OK) 131 { 132 fbus_parcel_reset(req_resp); 133 fbus_parcel_write_int(req_resp, ret); 134 if(ret == RET_OK) 135 { 136 fbus_parcel_write_string(req_resp, value); 137 } 138 } 139 140 return ret; 141} 142 143static Ret fconf_marshal_get_child_count(FBusService* thiz, FBusParcel* req_resp) 144{ 145 const char* xpath = {0}; 146 int count = {0}; 147 148 Ret ret = RET_FAIL; 149 DECL_PRIV(thiz, priv); 150 return_val_if_fail(priv != NULL && priv->impl != NULL && req_resp != NULL, RET_FAIL); 151 152 xpath = fbus_parcel_get_string(req_resp); 153 154 if((ret = fconf_get_child_count(priv->impl, xpath, &count)) == RET_OK) 155 { 156 fbus_parcel_reset(req_resp); 157 fbus_parcel_write_int(req_resp, ret); 158 if(ret == RET_OK) 159 { 160 fbus_parcel_write_int(req_resp, count); 161 } 162 } 163 164 return ret; 165} 166 167static Ret fconf_marshal_get_child(FBusService* thiz, FBusParcel* req_resp) 168{ 169 const char* xpath = {0}; 170 int index = {0}; 171 char* child = {0}; 172 173 Ret ret = RET_FAIL; 174 DECL_PRIV(thiz, priv); 175 return_val_if_fail(priv != NULL && priv->impl != NULL && req_resp != NULL, RET_FAIL); 176 177 xpath = fbus_parcel_get_string(req_resp); 178 index = fbus_parcel_get_int(req_resp); 179 180 if((ret = fconf_get_child(priv->impl, xpath, index, &child)) == RET_OK) 181 { 182 fbus_parcel_reset(req_resp); 183 fbus_parcel_write_int(req_resp, ret); 184 if(ret == RET_OK) 185 { 186 fbus_parcel_write_string(req_resp, child); 187 } 188 } 189 190 return ret; 191} 192 193static const char* fconf_service_get_name(FBusService* thiz) 194{ 195 return FBUS_SERVICE_FCONF; 196} 197 198static Ret fconf_service_on_client_connect(FBusService* thiz, int client_id) 199{ 200 return RET_OK; 201} 202 203static Ret fconf_service_on_client_disconnect(FBusService* thiz, int client_id) 204{ 205 return RET_OK; 206} 207 208static Ret fconf_service_handle_request(FBusService* thiz, int client_id, FBusParcel* req_resp) 209{ 210 DECL_PRIV(thiz, priv); 211 int req_code = fbus_parcel_get_int(req_resp); 212 213 priv->client_id = client_id; 214 switch(req_code) 215 { 216 case FCONF_LOCK: 217 { 218 fconf_marshal_lock(thiz, req_resp); 219 break; 220 } 221 case FCONF_UNLOCK: 222 { 223 fconf_marshal_unlock(thiz, req_resp); 224 break; 225 } 226 case FCONF_REMOVE: 227 { 228 fconf_marshal_remove(thiz, req_resp); 229 break; 230 } 231 case FCONF_SET: 232 { 233 fconf_marshal_set(thiz, req_resp); 234 break; 235 } 236 case FCONF_GET: 237 { 238 fconf_marshal_get(thiz, req_resp); 239 break; 240 } 241 case FCONF_GET_CHILD_COUNT: 242 { 243 fconf_marshal_get_child_count(thiz, req_resp); 244 break; 245 } 246 case FCONF_GET_CHILD: 247 { 248 fconf_marshal_get_child(thiz, req_resp); 249 break; 250 } 251 default:break; 252 } 253 254 if(fconf_xml_is_dirty(priv->impl) && priv->timer_save->ref < 2) 255 { 256 ftk_logd("%s: timer save %d\n", __func__, priv->timer_save->ref); 257 ftk_source_ref(priv->timer_save); 258 ftk_main_loop_add_source(ftk_default_main_loop(), priv->timer_save); 259 } 260 261 return RET_OK; 262} 263 264static void fconf_service_destroy(FBusService* thiz) 265{ 266 if(thiz != NULL) 267 { 268 DECL_PRIV(thiz, priv); 269 ftk_source_disable(priv->timer_save); 270 ftk_source_unref(priv->timer_save); 271 fbus_parcel_destroy(priv->parcel); 272 fconf_destroy(priv->impl); 273 FTK_FREE(thiz); 274 } 275 return; 276} 277 278static Ret on_changed(void* ctx, int change_by_self, FConfChangeType type, const char* xpath, const char* value) 279{ 280 FBusService* thiz = ctx; 281 DECL_PRIV(thiz, priv); 282 283 fbus_parcel_reset(priv->parcel); 284 fbus_parcel_write_int(priv->parcel, type); 285 fbus_parcel_write_string(priv->parcel, xpath); 286 287 if(value != NULL) 288 { 289 fbus_parcel_write_string(priv->parcel, value); 290 } 291 fbus_service_notify_all(thiz, priv->client_id, priv->parcel); 292 ftk_logd("%s: client_id=%d %d %d %s %s\n", __func__, priv->client_id, change_by_self, type, xpath, value); 293 294 return RET_OK; 295} 296 297static Ret timer_save_func(void* ctx) 298{ 299 FBusService* thiz = ctx; 300 DECL_PRIV(thiz, priv); 301 302 fconf_xml_save(priv->impl); 303 304 return RET_REMOVE; 305} 306 307FBusService* fconf_service_create(void) 308{ 309 FBusService* thiz = FTK_ZALLOC(sizeof(FBusService)+sizeof(PrivInfo)); 310 if(thiz != NULL) 311 { 312 DECL_PRIV(thiz, priv); 313 priv->parcel = fbus_parcel_create(1024); 314 priv->timer_save = ftk_source_timer_create(10000, timer_save_func, thiz); 315 priv->impl = fconf_xml_create(DATA_DIR"/config"); 316 thiz->get_name = fconf_service_get_name; 317 thiz->on_client_connect = fconf_service_on_client_connect; 318 thiz->on_client_disconnect = fconf_service_on_client_disconnect; 319 thiz->handle_request = fconf_service_handle_request; 320 thiz->destroy = fconf_service_destroy; 321 fbus_service_register(thiz); 322 fconf_reg_changed_notify(priv->impl, on_changed, thiz); 323 } 324 325 return thiz; 326} 327 328