void service_log(uint32_t handle, const char *fmt, ...) { if (g.log == 0) { fprintf(stderr, "[%u] ", handle); va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } else { struct message m; int size; va_list ap; va_start(ap, fmt); size = vsnprintf(0, 0, fmt, ap); va_end(ap); m.data = service_alloc(0, size+1); va_start(ap, fmt); vsnprintf((char *)m.data, size+1, fmt, ap); va_end(ap); m.size = size+1; m.session = 0; m.proto = 0; m.source = handle; if (-1 == service_send(g.log, &m)) service_alloc(m.data, 0); } }
uint32_t service_create(struct module *module, const char *param) { struct service *s = service_alloc(0, sizeof *s); s->module = *module; s->session = 0; s->logfile = 0; s->handle = service_regist(s); s->queue = queue_create(s->handle); service_total_inc(); s = service_grab(s->handle); s->ud = module->create(s->handle, param); if (!s->ud) { service_log(s->handle, "FAILED %s\n", param); uint32_t handle = s->handle; while (!(s = (struct service *)index_release(g.index, handle))) {} queue_try_release(s->queue); queue_release(s->queue, queue_message_dtor, (void *)(uintptr_t)handle); service_alloc(s, 0); service_total_dec(); return 0; } service_log(s->handle, "CREATE %s\n", param); worker_queue_push(s->queue); if (service_release(s->handle)) return 0; return s->handle; }
struct env * env_create(const char *file) { struct env *env = (struct env *)service_alloc(0, sizeof *env); spinlock_init(&env->lock); env->L = luaL_newstate(); if (file && LUA_OK != luaL_dofile(env->L, file)) { fprintf(stderr, "env init failed, %s\n", lua_tostring(env->L, -1)); lua_close(env->L); spinlock_unit(&env->lock); service_alloc(env, 0); return 0; } return env; }
int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, SERVICE_CREATION_T *setup, VCHI_SERVICE_HANDLE_T *handle) { VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; struct shim_service *service = service_alloc(instance, setup); *handle = (VCHI_SERVICE_HANDLE_T)service; if (service) { VCHIQ_SERVICE_PARAMS_T params; VCHIQ_STATUS_T status; memset(¶ms, 0, sizeof(params)); params.fourcc = setup->service_id; params.callback = shim_callback; params.userdata = service; params.version = setup->version.version; params.version_min = setup->version.version_min; status = vchiq_add_service(instance, ¶ms, &service->handle); if (status != VCHIQ_SUCCESS) { service_free(service); service = NULL; *handle = NULL; } } return (service != NULL) ? 0 : -1; }
struct queue *service_dispatch(struct monitor *monitor, struct queue *q) { if (!q) { q = worker_queue_pop(); if (!q) return 0; } uint32_t handle = queue_handle(q); struct service *s = service_grab(handle); if (!s) { queue_release(q, queue_message_dtor, (void *)(uintptr_t)handle); return worker_queue_pop(); } struct message m; if (!queue_pop(q, &m)) { service_release(handle); return worker_queue_pop(); } int overload = queue_overload(q); if (overload) service_log(handle, "service may overload, message queue length = %d\n", overload); monitor_trigger(monitor, m.source, handle); if (s->logfile) log_output(s->logfile, &m); s->module.dispatch(s->handle, s->ud, &m); service_alloc(m.data, 0); monitor_trigger(monitor, 0, 0); struct queue *next = worker_queue_pop(); if (next) { worker_queue_push(q); q = next; } service_release(handle); return q; }
static int service_socket_poll(void) { struct socket_message sm; if (!socket_poll(&sm)) return 0; struct message m; int size = sizeof sm; m.source = 0; m.session = 0; m.data = service_alloc(0, size); m.size = size; m.proto = SERVICE_PROTO_SOCKET; memcpy(m.data, &sm, size); uint32_t handle = (uint32_t)(uintptr_t)sm.ud; if (-1 == service_send(handle, &m)) service_alloc(m.data, 0); return 1; }
static void queue_message_dtor(struct message *m, void *ud) { service_alloc(m->data, 0); struct message em; em.source = (uint32_t)(uintptr_t)ud; em.session = 0; em.data = 0; em.size = 0; service_send(m->source, &em); }
int service_release(uint32_t handle) { struct service *s = (struct service *)index_release(g.index, handle); if (!s) return 0; s->module.release(s->handle, s->ud); queue_try_release(s->queue); if (s->logfile) fclose(s->logfile); service_alloc(s, 0); service_total_dec(); service_log(handle, "RELEASE\n"); return 1; }
int service_start(const char *name, int sock, service_limit_func_t *limitfunc, service_command_func_t *commandfunc, int argc, char *argv[]) { struct service *service; struct service_connection *sconn, *sconntmp; fd_set fds; int maxfd, nfds, serrno; assert(argc == 2); pjdlog_init(PJDLOG_MODE_STD); pjdlog_debug_set(atoi(argv[1])); service = service_alloc(name, limitfunc, commandfunc); if (service == NULL) return (errno); if (service_connection_add(service, sock, NULL) == NULL) { serrno = errno; service_free(service); return (serrno); } for (;;) { FD_ZERO(&fds); maxfd = -1; for (sconn = service_connection_first(service); sconn != NULL; sconn = service_connection_next(sconn)) { maxfd = fd_add(&fds, maxfd, service_connection_get_sock(sconn)); } PJDLOG_ASSERT(maxfd >= 0); PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); nfds = select(maxfd + 1, &fds, NULL, NULL, NULL); if (nfds < 0) { if (errno != EINTR) pjdlog_errno(LOG_ERR, "select() failed"); continue; } else if (nfds == 0) { /* Timeout. */ PJDLOG_ABORT("select() timeout"); continue; } for (sconn = service_connection_first(service); sconn != NULL; sconn = sconntmp) { /* * Prepare for connection to be removed from the list * on failure. */ sconntmp = service_connection_next(sconn); if (FD_ISSET(service_connection_get_sock(sconn), &fds)) service_message(service, sconn); } if (service_connection_first(service) == NULL) { /* * No connections left, exiting. */ break; } } return (0); }
/** * Process a configuration context update and turn it into the set of object * we need. * * @param context The configuration data */ static int process_config_update(CONFIG_CONTEXT *context) { CONFIG_CONTEXT *obj; SERVICE *service; SERVER *server; /** * Process the data and create the services and servers defined * in the data. */ obj = context; while (obj) { char *type = config_get_value(obj->parameters, "type"); if (type == NULL) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Configuration object %s has no type.", obj->object))); } else if (!strcmp(type, "service")) { char *router = config_get_value(obj->parameters, "router"); if (router) { if ((service = service_find(obj->object)) != NULL) { char *user; char *auth; char *enable_root_user; enable_root_user = config_get_value(obj->parameters, "enable_root_user"); user = config_get_value(obj->parameters, "user"); auth = config_get_value(obj->parameters, "passwd"); if (user && auth) { service_update(service, router, user, auth); if (enable_root_user) serviceEnableRootUser(service, atoi(enable_root_user)); } obj->element = service; } else { char *user; char *auth; char *enable_root_user; enable_root_user = config_get_value(obj->parameters, "enable_root_user"); user = config_get_value(obj->parameters, "user"); auth = config_get_value(obj->parameters, "passwd"); obj->element = service_alloc(obj->object, router); if (obj->element && user && auth) { serviceSetUser(obj->element, user, auth); if (enable_root_user) serviceEnableRootUser(service, atoi(enable_root_user)); } } } else { obj->element = NULL; LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : No router defined for service " "'%s'.", obj->object))); } } else if (!strcmp(type, "server")) { char *address; char *port; char *protocol; char *monuser; char *monpw; address = config_get_value(obj->parameters, "address"); port = config_get_value(obj->parameters, "port"); protocol = config_get_value(obj->parameters, "protocol"); monuser = config_get_value(obj->parameters, "monitoruser"); monpw = config_get_value(obj->parameters, "monitorpw"); if (address && port && protocol) { if ((server = server_find(address, atoi(port))) != NULL) { server_update(server, protocol, monuser, monpw); obj->element = server; } else { obj->element = server_alloc(address, protocol, atoi(port)); if (obj->element && monuser && monpw) { serverAddMonUser(obj->element, monuser, monpw); } } } else { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Server '%s' is missing a " "required " "configuration parameter. A server must " "have address, port and protocol " "defined.", obj->object))); } } obj = obj->next; } /* * Now we have the services we can add the servers to the services * add the protocols to the services */ obj = context; while (obj) { char *type = config_get_value(obj->parameters, "type"); if (type == NULL) ; else if (!strcmp(type, "service")) { char *servers; char *roptions; servers = config_get_value(obj->parameters, "servers"); roptions = config_get_value(obj->parameters, "router_options"); if (servers && obj->element) { char *s = strtok(servers, ","); while (s) { CONFIG_CONTEXT *obj1 = context; while (obj1) { if (strcmp(s, obj1->object) == 0 && obj->element && obj1->element) { if (!serviceHasBackend(obj->element, obj1->element)) { serviceAddBackend( obj->element, obj1->element); } } obj1 = obj1->next; } s = strtok(NULL, ","); } } if (roptions && obj->element) { char *s = strtok(roptions, ","); serviceClearRouterOptions(obj->element); while (s) { serviceAddRouterOption(obj->element, s); s = strtok(NULL, ","); } } } else if (!strcmp(type, "listener")) { char *service; char *port; char *protocol; char *address; service = config_get_value(obj->parameters, "service"); address = config_get_value(obj->parameters, "address"); port = config_get_value(obj->parameters, "port"); protocol = config_get_value(obj->parameters, "protocol"); if (service && port && protocol) { CONFIG_CONTEXT *ptr = context; while (ptr && strcmp(ptr->object, service) != 0) ptr = ptr->next; if (ptr && ptr->element && serviceHasProtocol(ptr->element, protocol, atoi(port)) == 0) { serviceAddProtocol(ptr->element, protocol, address, atoi(port)); serviceStartProtocol(ptr->element, protocol, atoi(port)); } } } else if (strcmp(type, "server") != 0 && strcmp(type, "monitor") != 0) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Configuration object %s has an invalid " "type specified.", obj->object))); } obj = obj->next; } return 1; }
/** * Process a configuration context and turn it into the set of object * we need. * * @param context The configuration data * @return A zero result indicates a fatal error */ static int process_config_context(CONFIG_CONTEXT *context) { CONFIG_CONTEXT *obj; int error_count = 0; /** * Process the data and create the services and servers defined * in the data. */ obj = context; while (obj) { char *type = config_get_value(obj->parameters, "type"); if (type == NULL) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Configuration object '%s' has no type.", obj->object))); error_count++; } else if (!strcmp(type, "service")) { char *router = config_get_value(obj->parameters, "router"); if (router) { obj->element = service_alloc(obj->object, router); char *user = config_get_value(obj->parameters, "user"); char *auth = config_get_value(obj->parameters, "passwd"); char *enable_root_user = config_get_value(obj->parameters, "enable_root_user"); if (enable_root_user) serviceEnableRootUser(obj->element, atoi(enable_root_user)); if (!auth) auth = config_get_value(obj->parameters, "auth"); if (obj->element && user && auth) { serviceSetUser(obj->element, user, auth); } else if (user && auth == NULL) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Service '%s' has a " "user defined but no " "corresponding password.", obj->object))); } } else { obj->element = NULL; LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : No router defined for service " "'%s'\n", obj->object))); error_count++; } } else if (!strcmp(type, "server")) { char *address; char *port; char *protocol; char *monuser; char *monpw; address = config_get_value(obj->parameters, "address"); port = config_get_value(obj->parameters, "port"); protocol = config_get_value(obj->parameters, "protocol"); monuser = config_get_value(obj->parameters, "monitoruser"); monpw = config_get_value(obj->parameters, "monitorpw"); if (address && port && protocol) { obj->element = server_alloc(address, protocol, atoi(port)); } else { obj->element = NULL; LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Server '%s' is missing a " "required configuration parameter. A " "server must " "have address, port and protocol " "defined.", obj->object))); error_count++; } if (obj->element && monuser && monpw) serverAddMonUser(obj->element, monuser, monpw); else if (monuser && monpw == NULL) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Server '%s' has a monitoruser" "defined but no corresponding password.", obj->object))); } } obj = obj->next; } /* * Now we have the services we can add the servers to the services * add the protocols to the services */ obj = context; while (obj) { char *type = config_get_value(obj->parameters, "type"); if (type == NULL) ; else if (!strcmp(type, "service")) { char *servers; char *roptions; servers = config_get_value(obj->parameters, "servers"); roptions = config_get_value(obj->parameters, "router_options"); if (servers && obj->element) { char *s = strtok(servers, ","); while (s) { CONFIG_CONTEXT *obj1 = context; while (obj1) { if (strcmp(s, obj1->object) == 0 && obj->element && obj1->element) { serviceAddBackend( obj->element, obj1->element); } obj1 = obj1->next; } s = strtok(NULL, ","); } } else if (servers == NULL) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : The service '%s' is missing a " "definition of the servers that provide " "the service.", obj->object))); } if (roptions && obj->element) { char *s = strtok(roptions, ","); while (s) { serviceAddRouterOption(obj->element, s); s = strtok(NULL, ","); } } } else if (!strcmp(type, "listener")) { char *service; char *address; char *port; char *protocol; service = config_get_value(obj->parameters, "service"); port = config_get_value(obj->parameters, "port"); address = config_get_value(obj->parameters, "address"); protocol = config_get_value(obj->parameters, "protocol"); if (service && port && protocol) { CONFIG_CONTEXT *ptr = context; while (ptr && strcmp(ptr->object, service) != 0) ptr = ptr->next; if (ptr && ptr->element) { serviceAddProtocol(ptr->element, protocol, address, atoi(port)); } else { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Listener '%s', " "service '%s' not found. " "Listener will not execute.", obj->object, service))); error_count++; } } else { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Listener '%s' is misisng a " "required " "parameter. A Listener must have a " "service, port and protocol defined.", obj->object))); error_count++; } } else if (!strcmp(type, "monitor")) { char *module; char *servers; char *user; char *passwd; module = config_get_value(obj->parameters, "module"); servers = config_get_value(obj->parameters, "servers"); user = config_get_value(obj->parameters, "user"); passwd = config_get_value(obj->parameters, "passwd"); if (module) { obj->element = monitor_alloc(obj->object, module); if (servers && obj->element) { char *s = strtok(servers, ","); while (s) { CONFIG_CONTEXT *obj1 = context; while (obj1) { if (strcmp(s, obj1->object) == 0 && obj->element && obj1->element) { monitorAddServer( obj->element, obj1->element); } obj1 = obj1->next; } s = strtok(NULL, ","); } } if (obj->element && user && passwd) { monitorAddUser(obj->element, user, passwd); } else if (obj->element && user) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error: " "Monitor '%s' defines a " "username with no password.", obj->object))); error_count++; } } else { obj->element = NULL; LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Monitor '%s' is missing a " "require module parameter.", obj->object))); error_count++; } } else if (strcmp(type, "server") != 0) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Configuration object '%s' has an " "invalid type specified.", obj->object))); error_count++; } obj = obj->next; } if (error_count) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : %d errors where encountered processing the " "configuration file '%s'.", error_count, config_file))); return 0; } return 1; }
void env_release(struct env *env) { lua_close(env->L); spinlock_unit(&env->lock); service_alloc(env, 0); }