APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, apr_pool_t *pool) { apr_thread_cond_t *new_cond; sem_id rv; int i; new_cond = (apr_thread_cond_t *)apr_palloc(pool, sizeof(apr_thread_cond_t)); if (new_cond == NULL) return APR_ENOMEM; if ((rv = create_sem(1, "apr conditional lock")) < B_OK) return rv; new_cond->lock = rv; new_cond->pool = pool; APR_RING_INIT(&new_cond->alist, waiter_t, link); APR_RING_INIT(&new_cond->flist, waiter_t, link); for (i=0;i < 10 ;i++) { struct waiter_t *nw = make_waiter(pool); APR_RING_INSERT_TAIL(&new_cond->flist, nw, waiter_t, link); } apr_pool_cleanup_register(new_cond->pool, (void *)new_cond, thread_cond_cleanup, apr_pool_cleanup_null); *cond = new_cond; return APR_SUCCESS; }
static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t size, apr_pool_t *p, apr_uint32_t flags) { apr_status_t rv; int fd; #ifdef HAVE_EPOLL_CREATE1 fd = epoll_create1(EPOLL_CLOEXEC); #else fd = epoll_create(size); #endif if (fd < 0) { pollset->p = NULL; return apr_get_netos_error(); } #ifndef HAVE_EPOLL_CREATE1 { int flags; if ((flags = fcntl(fd, F_GETFD)) == -1) return errno; flags |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, flags) == -1) return errno; } #endif pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if ((flags & APR_POLLSET_THREADSAFE) && !(flags & APR_POLLSET_NOCOPY) && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { pollset->p = NULL; return rv; } #else if (flags & APR_POLLSET_THREADSAFE) { pollset->p = NULL; return APR_ENOTIMPL; } #endif pollset->p->epoll_fd = fd; pollset->p->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); if (!(flags & APR_POLLSET_NOCOPY)) { APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); } return APR_SUCCESS; }
APU_DECLARE(apr_status_t) apr_reslist_create(apr_reslist_t **reslist, int min, int smax, int hmax, apr_interval_time_t ttl, apr_reslist_constructor con, apr_reslist_destructor de, void *params, apr_pool_t *pool) { apr_status_t rv; apr_reslist_t *rl; /* Do some sanity checks so we don't thrash around in the * maintenance routine later. */ if (min > smax || min > hmax || smax > hmax || ttl < 0) { return APR_EINVAL; } rl = apr_pcalloc(pool, sizeof(*rl)); rl->pool = pool; rl->min = min; rl->smax = smax; rl->hmax = hmax; rl->ttl = ttl; rl->constructor = con; rl->destructor = de; rl->params = params; APR_RING_INIT(&rl->avail_list, apr_res_t, link); APR_RING_INIT(&rl->free_list, apr_res_t, link); rv = apr_thread_mutex_create(&rl->listlock, APR_THREAD_MUTEX_DEFAULT, pool); if (rv != APR_SUCCESS) { return rv; } rv = apr_thread_cond_create(&rl->avail, pool); if (rv != APR_SUCCESS) { return rv; } rv = reslist_maint(rl); if (rv != APR_SUCCESS) { return rv; } apr_pool_cleanup_register(rl->pool, rl, reslist_cleanup, apr_pool_cleanup_null); *reslist = rl; return APR_SUCCESS; }
static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t size, apr_pool_t *p, apr_uint32_t flags) { apr_status_t rv = APR_SUCCESS; pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { pollset->p = NULL; return rv; } #else if (flags & APR_POLLSET_THREADSAFE) { pollset->p = NULL; return APR_ENOTIMPL; } #endif pollset->p->waiting = 0; pollset->p->port_set = apr_palloc(p, size * sizeof(port_event_t)); pollset->p->port_fd = port_create(); if (pollset->p->port_fd < 0) { pollset->p = NULL; return apr_get_netos_error(); } { int flags; if ((flags = fcntl(pollset->p->port_fd, F_GETFD)) == -1) return errno; flags |= FD_CLOEXEC; if (fcntl(pollset->p->port_fd, F_SETFD, flags) == -1) return errno; } pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); return rv; }
/** Create timer queue */ APT_DECLARE(apt_timer_queue_t*) apt_timer_queue_create(apr_pool_t *pool) { apt_timer_queue_t *timer_queue = apr_palloc(pool,sizeof(apt_timer_queue_t)); APR_RING_INIT(&timer_queue->head, apt_timer_t, link); timer_queue->elapsed_time = 0; return timer_queue; }
apt_bool_t mpf_buffer_restart(mpf_buffer_t *buffer) { apr_thread_mutex_lock(buffer->guard); APR_RING_INIT(&buffer->head, mpf_chunk_t, link); apr_thread_mutex_unlock(buffer->guard); return TRUE; }
APT_DECLARE(apt_obj_list_t*) apt_list_create(apr_pool_t *pool) { apt_obj_list_t *list = apr_palloc(pool, sizeof(apt_obj_list_t)); list->pool = pool; APR_RING_INIT(&list->head, apt_list_elem_t, link); return list; }
/** * Initialize the fd_queue_t. */ apr_status_t ap_queue_init(fd_queue_t * queue, int queue_capacity, apr_pool_t * a) { int i; apr_status_t rv; if ((rv = apr_thread_mutex_create(&queue->one_big_mutex, APR_THREAD_MUTEX_DEFAULT, a)) != APR_SUCCESS) { return rv; } if ((rv = apr_thread_cond_create(&queue->not_empty, a)) != APR_SUCCESS) { return rv; } APR_RING_INIT(&queue->timers, timer_event_t, link); queue->data = apr_palloc(a, queue_capacity * sizeof(fd_queue_elem_t)); queue->bounds = queue_capacity; queue->nelts = 0; queue->in = 0; queue->out = 0; /* Set all the sockets in the queue to NULL */ for (i = 0; i < queue_capacity; ++i) queue->data[i].sd = NULL; apr_pool_cleanup_register(a, queue, ap_queue_destroy, apr_pool_cleanup_null); return APR_SUCCESS; }
APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, apr_uint32_t size, apr_pool_t *p, apr_uint32_t flags) { apr_status_t rv = APR_SUCCESS; *pollset = apr_palloc(p, sizeof(**pollset)); #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, APR_THREAD_MUTEX_DEFAULT, p) != APR_SUCCESS))) { *pollset = NULL; return rv; } #else if (flags & APR_POLLSET_THREADSAFE) { *pollset = NULL; return APR_ENOTIMPL; } #endif (*pollset)->nelts = 0; (*pollset)->nalloc = size; (*pollset)->flags = flags; (*pollset)->pool = p; (*pollset)->port_set = apr_palloc(p, size * sizeof(port_event_t)); (*pollset)->port_fd = port_create(); if ((*pollset)->port_fd < 0) { return APR_ENOMEM; } apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, apr_pool_cleanup_null); (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); APR_RING_INIT(&(*pollset)->add_ring, pfd_elem_t, link); APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); return rv; }
/** Create timer manager */ MPF_DECLARE(mpf_timer_manager_t*) mpf_timer_manager_create(mpf_scheduler_t *scheduler, apr_pool_t *pool) { mpf_timer_manager_t *timer_manager = apr_palloc(pool,sizeof(mpf_timer_manager_t)); APR_RING_INIT(&timer_manager->head, mpf_timer_t, link); timer_manager->elapsed_time = 0; timer_manager->resolution = 100; /* 100 ms */ mpf_scheduler_timer_clock_set(scheduler,timer_manager->resolution,mpf_scheduler_proc,timer_manager); return timer_manager; }
mpf_buffer_t* mpf_buffer_create(apr_pool_t *pool) { mpf_buffer_t *buffer = apr_palloc(pool,sizeof(mpf_buffer_t)); buffer->pool = pool; buffer->cur_chunk = NULL; buffer->remaining_chunk_size = 0; APR_RING_INIT(&buffer->head, mpf_chunk_t, link); apr_thread_mutex_create(&buffer->guard,APR_THREAD_MUTEX_UNNESTED,pool); return buffer; }
h2_task_queue *h2_tq_create(long id, apr_pool_t *pool) { h2_task_queue *q = apr_pcalloc(pool, sizeof(h2_task_queue)); if (q) { q->id = id; APR_RING_ELEM_INIT(q, link); APR_RING_INIT(&q->tasks, h2_task, link); } return q; }
kdfilter *kdfilter_new(apr_pool_t *pool) { kdfilter *self; apr_pool_t *obj_pool; const char *name = NULL; int spam_enabled, virus_enabled, from_enabled; apr_pool_create(&obj_pool, pool); self = apr_pcalloc(obj_pool, sizeof(kdfilter)); APR_RING_INIT(&self->filter_drv_list, filter_driver, link); /* Register cleanup function. */ apr_pool_cleanup_register(obj_pool, self, kdfilter_delete, kdfilter_delete); /* Add the default filters. */ do { /* Check if we enable the spam filter. */ spam_enabled = options_get_bool("filter_spam.enabled"); virus_enabled = options_get_bool("filter_virus.enabled"); from_enabled = options_get_bool("filter_spam.enabled"); if (from_enabled && kdfilter_add(self, &filter_from) < 0) { name = filter_from.filter_name; break; } if (spam_enabled && kdfilter_add(self, &filter_spam) < 0) { name = filter_spam.filter_name; break; } if (virus_enabled && kdfilter_add(self, &filter_virus) < 0) { name = filter_virus.filter_name; break; } if (kdfilter_add(self, &filter_forward) < 0) { name = filter_forward.filter_name; break; } self->pool = obj_pool; return self; } while (0); KERROR_PUSH(_filter_, 0, "filter %s failed initialization", name); apr_pool_destroy(obj_pool); return NULL; }
APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p, apr_bucket_alloc_t *list) { apr_bucket_brigade *b; b = apr_palloc(p, sizeof(*b)); b->p = p; b->bucket_alloc = list; APR_RING_INIT(&b->list, apr_bucket, link); apr_pool_cleanup_register(b->p, b, brigade_cleanup, apr_pool_cleanup_null); return b; }
/** Create RTSP client */ RTSP_DECLARE(rtsp_client_t*) rtsp_client_create( const char *id, apr_size_t max_connection_count, apr_size_t request_timeout, void *obj, const rtsp_client_vtable_t *handler, apr_pool_t *pool) { apt_task_t *task; apt_task_vtable_t *vtable; apt_task_msg_pool_t *msg_pool; rtsp_client_t *client; apt_log(RTSP_LOG_MARK,APT_PRIO_NOTICE,"Create RTSP Client [%s] [%"APR_SIZE_T_FMT"]", id, max_connection_count); client = apr_palloc(pool,sizeof(rtsp_client_t)); client->pool = pool; client->obj = obj; client->vtable = handler; msg_pool = apt_task_msg_pool_create_dynamic(sizeof(task_msg_data_t),pool); client->task = apt_poller_task_create( max_connection_count, rtsp_client_poller_signal_process, client, msg_pool, pool); if(!client->task) { return NULL; } task = apt_poller_task_base_get(client->task); if(task) { apt_task_name_set(task,id); } vtable = apt_poller_task_vtable_get(client->task); if(vtable) { vtable->process_msg = rtsp_client_task_msg_process; } APR_RING_INIT(&client->connection_list, rtsp_client_connection_t, link); client->request_timeout = (apr_uint32_t)request_timeout; return client; }
/** Create connection agent. */ MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_client_connection_agent_create( const char *id, apr_size_t max_connection_count, apt_bool_t offer_new_connection, apr_pool_t *pool) { apt_task_t *task; apt_task_vtable_t *vtable; apt_task_msg_pool_t *msg_pool; mrcp_connection_agent_t *agent; apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv2 Agent [%s] [%"APR_SIZE_T_FMT"]", id, max_connection_count); agent = apr_palloc(pool,sizeof(mrcp_connection_agent_t)); agent->pool = pool; agent->request_timeout = 0; agent->offer_new_connection = offer_new_connection; agent->rx_buffer_size = MRCP_STREAM_BUFFER_SIZE; agent->tx_buffer_size = MRCP_STREAM_BUFFER_SIZE; msg_pool = apt_task_msg_pool_create_dynamic(sizeof(connection_task_msg_t),pool); agent->task = apt_poller_task_create( max_connection_count, mrcp_client_poller_signal_process, agent, msg_pool, pool); if(!agent->task) { return NULL; } task = apt_poller_task_base_get(agent->task); if(task) { apt_task_name_set(task,id); } vtable = apt_poller_task_vtable_get(agent->task); if(vtable) { vtable->process_msg = mrcp_client_agent_msg_process; } APR_RING_INIT(&agent->connection_list, mrcp_connection_t, link); return agent; }
static apr_status_t thread_pool_construct(apr_thread_pool_t * me, apr_size_t init_threads, apr_size_t max_threads) { apr_status_t rv; int i; me->thd_max = max_threads; me->idle_max = init_threads; me->threshold = init_threads / 2; rv = apr_thread_mutex_create(&me->lock, APR_THREAD_MUTEX_NESTED, me->pool); if (APR_SUCCESS != rv) { return rv; } rv = apr_thread_cond_create(&me->cond, me->pool); if (APR_SUCCESS != rv) { apr_thread_mutex_destroy(me->lock); return rv; } me->tasks = apr_palloc(me->pool, sizeof(*me->tasks)); if (!me->tasks) { goto CATCH_ENOMEM; } APR_RING_INIT(me->tasks, apr_thread_pool_task, link); me->scheduled_tasks = apr_palloc(me->pool, sizeof(*me->scheduled_tasks)); if (!me->scheduled_tasks) { goto CATCH_ENOMEM; } APR_RING_INIT(me->scheduled_tasks, apr_thread_pool_task, link); me->recycled_tasks = apr_palloc(me->pool, sizeof(*me->recycled_tasks)); if (!me->recycled_tasks) { goto CATCH_ENOMEM; } APR_RING_INIT(me->recycled_tasks, apr_thread_pool_task, link); me->busy_thds = apr_palloc(me->pool, sizeof(*me->busy_thds)); if (!me->busy_thds) { goto CATCH_ENOMEM; } APR_RING_INIT(me->busy_thds, apr_thread_list_elt, link); me->idle_thds = apr_palloc(me->pool, sizeof(*me->idle_thds)); if (!me->idle_thds) { goto CATCH_ENOMEM; } APR_RING_INIT(me->idle_thds, apr_thread_list_elt, link); me->recycled_thds = apr_palloc(me->pool, sizeof(*me->recycled_thds)); if (!me->recycled_thds) { goto CATCH_ENOMEM; } APR_RING_INIT(me->recycled_thds, apr_thread_list_elt, link); me->thd_cnt = me->idle_cnt = me->task_cnt = me->scheduled_task_cnt = 0; me->tasks_run = me->tasks_high = me->thd_high = me->thd_timed_out = 0; me->spawning_cnt = 0; me->idle_wait = 0; me->terminated = 0; for (i = 0; i < TASK_PRIORITY_SEGS; i++) { me->task_idx[i] = NULL; } goto FINAL_EXIT; CATCH_ENOMEM: rv = APR_ENOMEM; apr_thread_mutex_destroy(me->lock); apr_thread_cond_destroy(me->cond); FINAL_EXIT: return rv; }
/* * main */ int main(int argc, const char * const argv[]) { apr_off_t max; apr_time_t current, repeat, delay, previous; apr_status_t status; apr_pool_t *pool, *instance; apr_getopt_t *o; apr_finfo_t info; int retries, isdaemon, limit_found, intelligent, dowork; char opt; const char *arg; char *proxypath, *path; interrupted = 0; repeat = 0; isdaemon = 0; dryrun = 0; limit_found = 0; max = 0; verbose = 0; realclean = 0; benice = 0; deldirs = 0; intelligent = 0; previous = 0; /* avoid compiler warning */ proxypath = NULL; if (apr_app_initialize(&argc, &argv, NULL) != APR_SUCCESS) { return 1; } atexit(apr_terminate); if (argc) { shortname = apr_filepath_name_get(argv[0]); } if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { return 1; } apr_pool_abort_set(oom, pool); apr_file_open_stderr(&errfile, pool); apr_signal(SIGINT, setterm); apr_signal(SIGTERM, setterm); apr_getopt_init(&o, pool, argc, argv); while (1) { status = apr_getopt(o, "iDnvrtd:l:L:p:", &opt, &arg); if (status == APR_EOF) { break; } else if (status != APR_SUCCESS) { usage(); } else { switch (opt) { case 'i': if (intelligent) { usage(); } intelligent = 1; break; case 'D': if (dryrun) { usage(); } dryrun = 1; break; case 'n': if (benice) { usage(); } benice = 1; break; case 't': if (deldirs) { usage(); } deldirs = 1; break; case 'v': if (verbose) { usage(); } verbose = 1; break; case 'r': if (realclean) { usage(); } realclean = 1; deldirs = 1; break; case 'd': if (isdaemon) { usage(); } isdaemon = 1; repeat = apr_atoi64(arg); repeat *= SECS_PER_MIN; repeat *= APR_USEC_PER_SEC; break; case 'l': if (limit_found) { usage(); } limit_found = 1; do { apr_status_t rv; char *end; rv = apr_strtoff(&max, arg, &end, 10); if (rv == APR_SUCCESS) { if ((*end == 'K' || *end == 'k') && !end[1]) { max *= KBYTE; } else if ((*end == 'M' || *end == 'm') && !end[1]) { max *= MBYTE; } else if ((*end == 'G' || *end == 'g') && !end[1]) { max *= GBYTE; } else if (*end && /* neither empty nor [Bb] */ ((*end != 'B' && *end != 'b') || end[1])) { rv = APR_EGENERAL; } } if (rv != APR_SUCCESS) { apr_file_printf(errfile, "Invalid limit: %s" APR_EOL_STR APR_EOL_STR, arg); usage(); } } while(0); break; case 'p': if (proxypath) { usage(); } proxypath = apr_pstrdup(pool, arg); if (apr_filepath_set(proxypath, pool) != APR_SUCCESS) { usage(); } break; } /* switch */ } /* else */ } /* while */ if (o->ind != argc) { usage(); } if (isdaemon && (repeat <= 0 || verbose || realclean || dryrun)) { usage(); } if (!isdaemon && intelligent) { usage(); } if (!proxypath || max <= 0) { usage(); } if (apr_filepath_get(&path, 0, pool) != APR_SUCCESS) { usage(); } baselen = strlen(path); #ifndef DEBUG if (isdaemon) { apr_file_close(errfile); apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); } #endif do { apr_pool_create(&instance, pool); now = apr_time_now(); APR_RING_INIT(&root, _entry, link); delcount = 0; unsolicited = 0; dowork = 0; switch (intelligent) { case 0: dowork = 1; break; case 1: retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, path, APR_FINFO_MTIME, instance); } while (status != APR_SUCCESS && !interrupted && --retries); if (status == APR_SUCCESS) { previous = info.mtime; intelligent = 2; } dowork = 1; break; case 2: retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, path, APR_FINFO_MTIME, instance); } while (status != APR_SUCCESS && !interrupted && --retries); if (status == APR_SUCCESS) { if (previous != info.mtime) { dowork = 1; } previous = info.mtime; break; } intelligent = 1; dowork = 1; break; } if (dowork && !interrupted) { if (!process_dir(path, instance) && !interrupted) { purge(path, instance, max); } else if (!isdaemon && !interrupted) { apr_file_printf(errfile, "An error occurred, cache cleaning " "aborted." APR_EOL_STR); return 1; } if (intelligent && !interrupted) { retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, path, APR_FINFO_MTIME, instance); } while (status != APR_SUCCESS && !interrupted && --retries); if (status == APR_SUCCESS) { previous = info.mtime; intelligent = 2; } else { intelligent = 1; } } } apr_pool_destroy(instance); current = apr_time_now(); if (current < now) { delay = repeat; } else if (current - now >= repeat) { delay = repeat; } else { delay = now + repeat - current; } /* we can't sleep the whole delay time here apiece as this is racy * with respect to interrupt delivery - think about what happens * if we have tested for an interrupt, then get scheduled * before the apr_sleep() call and while waiting for the cpu * we do get an interrupt */ if (isdaemon) { while (delay && !interrupted) { if (delay > APR_USEC_PER_SEC) { apr_sleep(APR_USEC_PER_SEC); delay -= APR_USEC_PER_SEC; } else { apr_sleep(delay); delay = 0; } } } } while (isdaemon && !interrupted); if (!isdaemon && interrupted) { apr_file_printf(errfile, "Cache cleaning aborted due to user " "request." APR_EOL_STR); return 1; } return 0; }
/* * walk the cache directory tree */ static int process_dir(char *path, apr_pool_t *pool) { apr_dir_t *dir; apr_pool_t *p; apr_hash_t *h; apr_hash_index_t *i; apr_file_t *fd; apr_status_t status; apr_finfo_t info; apr_size_t len; apr_time_t current, deviation; char *nextpath, *base, *ext, *orig_basename; APR_RING_ENTRY(_direntry) anchor; DIRENTRY *d, *t, *n; ENTRY *e; int skip, retries; disk_cache_info_t disk_info; APR_RING_INIT(&anchor, _direntry, link); apr_pool_create(&p, pool); h = apr_hash_make(p); fd = NULL; skip = 0; deviation = MAXDEVIATION * APR_USEC_PER_SEC; if (apr_dir_open(&dir, path, p) != APR_SUCCESS) { return 1; } while (apr_dir_read(&info, 0, dir) == APR_SUCCESS && !interrupted) { if (!strcmp(info.name, ".") || !strcmp(info.name, "..")) { continue; } d = apr_pcalloc(p, sizeof(DIRENTRY)); d->basename = apr_pstrcat(p, path, "/", info.name, NULL); APR_RING_INSERT_TAIL(&anchor, d, _direntry, link); } apr_dir_close(dir); if (interrupted) { return 1; } skip = baselen + 1; for (d = APR_RING_FIRST(&anchor); !interrupted && d != APR_RING_SENTINEL(&anchor, _direntry, link); d=n) { n = APR_RING_NEXT(d, link); base = strrchr(d->basename, '/'); if (!base++) { base = d->basename; } ext = strchr(base, '.'); /* there may be temporary files which may be gone before * processing, always skip these if not in realclean mode */ if (!ext && !realclean) { if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN) && strlen(base) == AP_TEMPFILE_NAMELEN) { continue; } } /* this may look strange but apr_stat() may return errno which * is system dependent and there may be transient failures, * so just blindly retry for a short while */ retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, d->basename, DIRINFO, p); } while (status != APR_SUCCESS && !interrupted && --retries); /* what may happen here is that apache did create a file which * we did detect but then does delete the file before we can * get file information, so if we don't get any file information * we will ignore the file in this case */ if (status != APR_SUCCESS) { if (!realclean && !interrupted) { continue; } return 1; } if (info.filetype == APR_DIR) { /* Make a copy of the basename, as process_dir modifies it */ orig_basename = apr_pstrdup(pool, d->basename); if (process_dir(d->basename, pool)) { return 1; } /* If asked to delete dirs, do so now. We don't care if it fails. * If it fails, it likely means there was something else there. */ if (deldirs && !dryrun) { apr_dir_remove(orig_basename, pool); } continue; } if (info.filetype != APR_REG) { continue; } if (!ext) { if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN) && strlen(base) == AP_TEMPFILE_NAMELEN) { d->basename += skip; d->type = TEMP; d->dsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); } continue; } if (!strcasecmp(ext, CACHE_HEADER_SUFFIX)) { *ext = '\0'; d->basename += skip; /* if a user manually creates a '.header' file */ if (d->basename[0] == '\0') { continue; } t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING); if (t) { d = t; } d->type |= HEADER; d->htime = info.mtime; d->hsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); continue; } if (!strcasecmp(ext, CACHE_DATA_SUFFIX)) { *ext = '\0'; d->basename += skip; /* if a user manually creates a '.data' file */ if (d->basename[0] == '\0') { continue; } t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING); if (t) { d = t; } d->type |= DATA; d->dtime = info.mtime; d->dsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); } } if (interrupted) { return 1; } path[baselen] = '\0'; for (i = apr_hash_first(p, h); i && !interrupted; i = apr_hash_next(i)) { void *hvalue; apr_uint32_t format; apr_hash_this(i, NULL, NULL, &hvalue); d = hvalue; switch(d->type) { case HEADERDATA: nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == DISK_FORMAT_VERSION) { apr_off_t offset = 0; apr_file_seek(fd, APR_SET, &offset); len = sizeof(disk_cache_info_t); if (apr_file_read_full(fd, &disk_info, len, &len) == APR_SUCCESS) { apr_file_close(fd); e = apr_palloc(pool, sizeof(ENTRY)); APR_RING_INSERT_TAIL(&root, e, _entry, link); e->expire = disk_info.expire; e->response_time = disk_info.response_time; e->htime = d->htime; e->dtime = d->dtime; e->hsize = d->hsize; e->dsize = d->dsize; e->basename = apr_pstrdup(pool, d->basename); break; } else { apr_file_close(fd); } } else if (format == VARY_FORMAT_VERSION) { /* This must be a URL that added Vary headers later, * so kill the orphaned .data file */ apr_file_close(fd); apr_file_remove(apr_pstrcat(p, path, "/", d->basename, CACHE_DATA_SUFFIX, NULL), p); } } else { apr_file_close(fd); } } /* we have a somehow unreadable headers file which is associated * with a data file. this may be caused by apache currently * rewriting the headers file. thus we may delete the file set * either in realclean mode or if the headers file modification * timestamp is not within a specified positive or negative offset * to the current time. */ current = apr_time_now(); if (realclean || d->htime < current - deviation || d->htime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->hsize; unsolicited += d->dsize; } break; /* single data and header files may be deleted either in realclean * mode or if their modification timestamp is not within a * specified positive or negative offset to the current time. * this handling is necessary due to possible race conditions * between apache and this process */ case HEADER: current = apr_time_now(); nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == VARY_FORMAT_VERSION) { apr_time_t expires; len = sizeof(expires); apr_file_read_full(fd, &expires, len, &len); apr_file_close(fd); if (expires < current) { delete_entry(path, d->basename, p); } break; } } apr_file_close(fd); } if (realclean || d->htime < current - deviation || d->htime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->hsize; } break; case DATA: current = apr_time_now(); if (realclean || d->dtime < current - deviation || d->dtime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->dsize; } break; /* temp files may only be deleted in realclean mode which * is asserted above if a tempfile is in the hash array */ case TEMP: delete_file(path, d->basename, p); unsolicited += d->dsize; break; } } if (interrupted) { return 1; } apr_pool_destroy(p); if (benice) { apr_sleep(NICE_DELAY); } if (interrupted) { return 1; } return 0; }
/** * Initialize a bean that has already been allocated with the given * BMX Objectname. * @param bean The pre-allocated bean object to initialize. * @param objectname The BMX Objectname for this new bean. */ void bmx_bean_init(struct bmx_bean *bean, struct bmx_objectname *objectname) { bean->objectname = objectname; APR_RING_INIT(&(bean->bean_props), bmx_property, link); }
/* core's child-status hook * tracks number of remaining children per generation and * runs the end-generation hook when the last child of * a generation exits */ void ap_core_child_status(server_rec *s, pid_t pid, ap_generation_t gen, int slot, mpm_child_status status) { mpm_gen_info_t *cur; const char *status_msg = "unknown status"; if (!gen_head_init) { /* where to run this? */ gen_head_init = 1; geninfo = apr_pcalloc(s->process->pool, sizeof *geninfo); unused_geninfo = apr_pcalloc(s->process->pool, sizeof *unused_geninfo); APR_RING_INIT(geninfo, mpm_gen_info_t, link); APR_RING_INIT(unused_geninfo, mpm_gen_info_t, link); } cur = APR_RING_FIRST(geninfo); while (cur != APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link) && cur->gen != gen) { cur = APR_RING_NEXT(cur, link); } switch(status) { case MPM_CHILD_STARTED: status_msg = "started"; if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) { /* first child for this generation */ if (!APR_RING_EMPTY(unused_geninfo, mpm_gen_info_t, link)) { cur = APR_RING_FIRST(unused_geninfo); APR_RING_REMOVE(cur, link); cur->active = cur->done = 0; } else { cur = apr_pcalloc(s->process->pool, sizeof *cur); } cur->gen = gen; APR_RING_ELEM_INIT(cur, link); APR_RING_INSERT_HEAD(geninfo, cur, mpm_gen_info_t, link); } ap_random_parent_after_fork(); ++cur->active; break; case MPM_CHILD_EXITED: ap_update_global_status(); status_msg = "exited"; if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00546) "no record of generation %d of exiting child %" APR_PID_T_FMT, gen, pid); } else { --cur->active; if (!cur->active && cur->done) { /* no children, server has stopped/restarted */ end_gen(cur); } } break; case MPM_CHILD_LOST_SLOT: status_msg = "lost slot"; /* we don't track by slot, so it doesn't matter */ break; } ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, s, "mpm child %" APR_PID_T_FMT " (gen %d/slot %d) %s", pid, gen, slot, status_msg); }
/** Create connection agent */ MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_create( const char *id, const char *listen_ip, apr_port_t listen_port, apr_size_t max_connection_count, apt_bool_t force_new_connection, apr_pool_t *pool) { apt_task_t *task; apt_task_vtable_t *vtable; apt_task_msg_pool_t *msg_pool; mrcp_connection_agent_t *agent; if(!listen_ip) { return NULL; } apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv2 Agent [%s] %s:%hu [%"APR_SIZE_T_FMT"]", id,listen_ip,listen_port,max_connection_count); agent = apr_palloc(pool,sizeof(mrcp_connection_agent_t)); agent->pool = pool; agent->sockaddr = NULL; agent->listen_sock = NULL; agent->force_new_connection = force_new_connection; agent->rx_buffer_size = MRCP_STREAM_BUFFER_SIZE; agent->tx_buffer_size = MRCP_STREAM_BUFFER_SIZE; apr_sockaddr_info_get(&agent->sockaddr,listen_ip,APR_INET,listen_port,0,pool); if(!agent->sockaddr) { return NULL; } msg_pool = apt_task_msg_pool_create_dynamic(sizeof(connection_task_msg_t),pool); agent->task = apt_poller_task_create( max_connection_count + 1, mrcp_server_poller_signal_process, agent, msg_pool, pool); if(!agent->task) { return NULL; } task = apt_poller_task_base_get(agent->task); if(task) { apt_task_name_set(task,id); } vtable = apt_poller_task_vtable_get(agent->task); if(vtable) { vtable->destroy = mrcp_server_agent_on_destroy; vtable->process_msg = mrcp_server_agent_msg_process; } APR_RING_INIT(&agent->connection_list, mrcp_connection_t, link); agent->pending_channel_table = apr_hash_make(pool); if(mrcp_server_agent_listening_socket_create(agent) != TRUE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Listening Socket [%s] %s:%hu", id, listen_ip, listen_port); } return agent; }
static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t size, apr_pool_t *p, apr_uint32_t flags) { apr_status_t rv; pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { pollset->p = NULL; return rv; } #else if (flags & APR_POLLSET_THREADSAFE) { pollset->p = NULL; return APR_ENOTIMPL; } #endif /* POLLIN and POLLOUT are represented in different returned * events, so we need 2 entries per descriptor in the result set, * both for what is returned by kevent() and what is returned to * the caller of apr_pollset_poll() (since it doesn't spend the * CPU to coalesce separate APR_POLLIN and APR_POLLOUT events * for the same descriptor) */ pollset->p->setsize = 2 * size; pollset->p->ke_set = (struct kevent *) apr_palloc(p, pollset->p->setsize * sizeof(struct kevent)); memset(pollset->p->ke_set, 0, pollset->p->setsize * sizeof(struct kevent)); pollset->p->kqueue_fd = kqueue(); if (pollset->p->kqueue_fd == -1) { pollset->p = NULL; return apr_get_netos_error(); } { int flags; if ((flags = fcntl(pollset->p->kqueue_fd, F_GETFD)) == -1) return errno; flags |= FD_CLOEXEC; if (fcntl(pollset->p->kqueue_fd, F_SETFD, flags) == -1) return errno; } pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t)); APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); return APR_SUCCESS; }
MPF_DECLARE(mpf_context_factory_t*) mpf_context_factory_create(apr_pool_t *pool) { mpf_context_factory_t *factory = apr_palloc(pool, sizeof(mpf_context_factory_t)); APR_RING_INIT(&factory->head, mpf_context_t, link); return factory; }
/** Create RTSP server */ RTSP_DECLARE(rtsp_server_t*) rtsp_server_create( const char *id, const char *listen_ip, apr_port_t listen_port, apr_size_t max_connection_count, void *obj, const rtsp_server_vtable_t *handler, apr_pool_t *pool) { apt_task_t *task; apt_task_vtable_t *vtable; apt_task_msg_pool_t *msg_pool; rtsp_server_t *server; if(!listen_ip) { return NULL; } apt_log(RTSP_LOG_MARK,APT_PRIO_NOTICE,"Create RTSP Server [%s] %s:%hu [%"APR_SIZE_T_FMT"]", id, listen_ip, listen_port, max_connection_count); server = apr_palloc(pool,sizeof(rtsp_server_t)); server->pool = pool; server->obj = obj; server->vtable = handler; server->listen_sock = NULL; server->sockaddr = NULL; apr_sockaddr_info_get(&server->sockaddr,listen_ip,APR_INET,listen_port,0,pool); if(!server->sockaddr) { return NULL; } msg_pool = apt_task_msg_pool_create_dynamic(sizeof(task_msg_data_t),pool); server->task = apt_poller_task_create( max_connection_count + 1, rtsp_server_poller_signal_process, server, msg_pool, pool); if(!server->task) { return NULL; } task = apt_poller_task_base_get(server->task); if(task) { apt_task_name_set(task,id); } vtable = apt_poller_task_vtable_get(server->task); if(vtable) { vtable->destroy = rtsp_server_on_destroy; vtable->process_msg = rtsp_server_task_msg_process; } APR_RING_INIT(&server->connection_list, rtsp_server_connection_t, link); if(rtsp_server_listening_socket_create(server) != TRUE) { apt_log(RTSP_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Listening Socket [%s] %s:%hu", id, listen_ip, listen_port); } return server; }