예제 #1
0
int main(int argc, char * argv[]) {
    bool pass = true;

    {
        int nums[] = { 1, 3, 2, 1, 2 };
        ListNode * list = ll_create(nums, sizeof(nums) / sizeof(int));
        ListNode * node = list->next;
        delete_middle_node(node);
        ll_print(list);
        ll_delete(list);
    }

    {
        int nums[] = { 1, 3, 2, 1, 2 };
        ListNode * list = ll_create(nums, sizeof(nums) / sizeof(int));
        ListNode * node = list->next->next;
        delete_middle_node(node);
        ll_print(list);
        ll_delete(list);
    }

    {
        int nums[] = { 1, 3, 2, 1, 2 };
        ListNode * list = ll_create(nums, sizeof(nums) / sizeof(int));
        ListNode * node = list->next->next->next;
        delete_middle_node(node);
        ll_print(list);
        ll_delete(list);
    }

    return (pass ? 0 : -1);
}
예제 #2
0
int32_t coolapi_open_device (int32_t demux_index, int32_t demux_id)
{
	dmx_t * dmx;

	coolapi_open();

	dmx = find_demux(0, demux_index);
	if(!dmx) {
		cs_log("no free demux found");
		return 0;
	}

	if (!ll_cool_filter)
		ll_cool_filter = ll_create("ll_cool_filter");

	if (!ll_cool_chanhandle)
		ll_cool_chanhandle = ll_create("ll_cool_chanhandle");

	dmx->demux_index = demux_index;
	dmx->demux_id = demux_id;
	dmx->pid = -1;

	dmx->device = dmx_device[demux_index];
	dmx->opened = 1;

	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
	pthread_mutex_init(&dmx->mutex, &attr);

	return dmx->fd;
}
예제 #3
0
int32_t coolapi_open_device(int32_t demux_index, int32_t demux_id)
{
	dmx_t *dmx;

	SAFE_MUTEX_LOCK(&demux_lock);

	dmx = find_demux(0, demux_index);
	if(!dmx)
	{
		SAFE_MUTEX_UNLOCK(&demux_lock);
		cs_log("no free demux found");
		return 0;
	}

	if(!ll_cool_filter)
		{ ll_cool_filter = ll_create("ll_cool_filter"); }

	if(!ll_cool_chanhandle)
		{ ll_cool_chanhandle = ll_create("ll_cool_chanhandle"); }

	dmx->demux_id = demux_id;
	dmx->pid = -1;

	//dmx->device = dmx_handles[demux_index].handle;
	dmx->opened = 1;

	pthread_mutexattr_t attr;
	SAFE_MUTEXATTR_INIT(&attr);
	SAFE_MUTEXATTR_SETTYPE(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
	SAFE_MUTEX_INIT(&dmx->mutex, &attr);

	SAFE_MUTEX_UNLOCK(&demux_lock);

	return dmx->fd;
}
예제 #4
0
int main(int argc, char *argv[]) {

  Database *db; 
  LinkedList *ll;

  db = db_create("project_seven");              //CREATE DATABASE project_seven;
  tbl_delete(db, "animals");                    //DROP TABLE IF EXISTS animals;
  func_delete(db, "num_animals");               //DROP FUNCTION IF EXISTS num_animals;
  
  tbl_create(db, "animals");                    //CREATE TABLE animals

  /* Capabilities of this function changed to
     make implementation easier. The purpose of this function is to 
     demonstrate memory management */
  func_create(db, "num_animals", num_animals);  //CREATE FUNCTION num_animals()


  /*Creates rows in table*/
  ll = ll_create();
  ll_append(ll, "Cow");
  tbl_insert(db, "animals", ll);                //INSERT INTO animals (animal) VALUES ("Cow");
  
  ll = ll_create();
  ll_append(ll, "Dog");
  tbl_insert(db, "animals", ll);                //INSERT INTO animals (animal) VALUES ("Dog");


  /*Printing tables, and rows created*/
  db_print(db);                                 //SHOW TABLES;
  tbl_print(db, "animals");                     //SELECT * FROM animals;


  /*Deallocating memory*/
  tbl_clear(db, "animals");                     //DELETE FROM animals;
  tbl_print(db, "animals");                     //SELECT * FROM animals;


  /*Allocating so that we can deallocate again*/
  ll = ll_create();
  ll_append(ll, "Pig");
  tbl_insert(db, "animals", ll);                //INSERT INTO animals (animal) VALUES ("Pig");
  
  ll = ll_create();
  ll_append(ll, "Cat");
  tbl_insert(db, "animals", ll);                //INSERT INTO animals (animal) VALUES ("Cat");
  
  tbl_print(db, "animals");                     //SELECT * FROM animals;

  /*Deallocating memory*/
  tbl_clear(db, "animals");                     //TRUNCATE TABLE animals;
  tbl_print(db, "animals");                     //SELECT * FROM animals;

  tbl_delete(db, "animals");                    //DROP TABLE IF EXISTS animals;
  func_delete(db, "num_animals");               //DROP FUNCTION IF EXISTS num_animals;
  db_print(db);                                 //SHOW TABLES;

  db_delete(db);                                //DROP DATABASE IF EXISTS project_seven;
 
  return 0;
}
예제 #5
0
파일: graph.c 프로젝트: Shihira/laboratory
graph* g_create_(size_t szelem, graph_type gt)
{
    graph* g = (graph*)malloc(sizeof(graph));
    if(!g) toss(MemoryFault);
    g->elem_size = szelem;
    g->nodes = ll_create(gnode);
    g->edges = ll_create(gedge);
    g->gtype = gt;

    return g;
}
예제 #6
0
void init_gbox_cards(void)
{
        gbox_cards = ll_create("gbox.cards");
        gbox_backup_cards = ll_create("gbox.backup.cards");
        cs_lock_create(__func__, &gbox_cards_lock, "gbox_cards_lock", 5000);
        cs_writelock(__func__, &gbox_cards_lock);        
        checkcode[0] = 0x15;
        checkcode[1] = 0x30;
        checkcode[2] = 0x02;
        checkcode[3] = 0x04;
        checkcode[4] = 0x19;
        checkcode[5] = 0x19;
        checkcode[6] = 0x66;
        cs_writeunlock(__func__, &gbox_cards_lock);        
}
예제 #7
0
static void account_au_fn(const char *token, char *value, void *setting, FILE *f) {
	struct s_auth *account = setting;
	if (value) {
		// set default values for usage during runtime from Webif
		account->autoau = 0;
		if (!account->aureader_list)
			account->aureader_list = ll_create("aureader_list");
		if (streq(value, "1"))
			account->autoau = 1;
		strtolower(value);
		ll_clear(account->aureader_list);
		LL_ITER itr = ll_iter_create(configured_readers);
		struct s_reader *rdr;
		char *pch, *saveptr1 = NULL;
		for (pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1)) {
			ll_iter_reset(&itr);
			while ((rdr = ll_iter_next(&itr))) {
				if (streq(rdr->label, pch) || account->autoau) {
					ll_append(account->aureader_list, rdr);
				}
			}
		}
		return;
	}
	if (account->autoau == 1) {
		fprintf_conf(f, token, "%d\n", account->autoau);
	} else if (account->aureader_list) {
		value = mk_t_aureader(account);
		if (strlen(value) > 0)
			fprintf_conf(f, token, "%s\n", value);
		free_mk_t(value);
	} else if (cfg.http_full_cfg) {
		fprintf_conf(f, token, "%s\n", "");
	}
}
예제 #8
0
파일: topic.c 프로젝트: dellswor/Cache
int top_create(char *name, char *schema) {
    Topic *st;
    int ncells;
    char bf[1024];

    if (tshm_containsKey(topicTable, name))	/* topic already defined */
        return 0;
    st = (Topic *)malloc(sizeof(Topic));
    if (st != NULL) {
        void *dummy;
        strcpy(bf, schema);
        pthread_mutex_init(&(st->lock), NULL);
        st->schema = unpack(bf, &ncells);
        if (st->schema != NULL) {
            st->ncells = ncells;
            st->regAUs = ll_create();
            if (st->regAUs != NULL) {
                if (tshm_put(topicTable, name, st, &dummy))
                    return 1;
                ll_destroy(st->regAUs, NULL);
            }
            free((void *)(st->schema));
        }
        free((void *)st);
    }
    return 0;
}
예제 #9
0
void module_ghttp(struct s_module *ph)
{
	ph->ptab.nports = 0;
	// ph->ptab.ports[0].s_port = cfg.ghttp_port;
	ph->desc = "ghttp";
	ph->type = MOD_CONN_TCP;
	// ph->listenertype = LIS_GHTTP;
	ph->large_ecm_support = 1;
	ph->recv = ghttp_recv;
	ph->c_init = ghttp_client_init;
	ph->c_recv_chk = ghttp_recv_chk;
	ph->c_send_ecm = ghttp_send_ecm;
	ph->cleanup = ghttp_cleanup;
#ifdef HAVE_DVBAPI
	ph->c_capmt = ghttp_capmt_notify;
#endif
	ph->num = R_GHTTP;
	ghttp_ignored_contexts = ll_create("ignored contexts");
#ifdef WITH_SSL
	SSL_load_error_strings();
	SSL_library_init();
	ghttp_ssl_context = SSL_CTX_new(SSLv23_client_method());
	if(ghttp_ssl_context == NULL) { ERR_print_errors_fp(stderr); }
#endif
}
예제 #10
0
int module_install()
{
	printk(1, "[ext2]: Registering filesystem\n");
	fslist = ll_create(0);
	register_sbt("ext2", 2, (int (*)(dev_t,u64,char*))ext2_mount);
	return 0;
}
예제 #11
0
int32_t cs_init_log(void)
{
	if(logStarted == 0)
	{
		pthread_mutex_init(&log_mutex, NULL);

		cs_pthread_cond_init(&log_thread_sleep_cond_mutex, &log_thread_sleep_cond);

#if defined(WEBIF) || defined(MODULE_MONITOR)
		cs_lock_create(&loghistory_lock, "loghistory_lock", 5000);
#endif

		log_list = ll_create(LOG_LIST);
		pthread_attr_t attr;
		pthread_attr_init(&attr);
		pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
		int32_t ret = pthread_create(&log_thread, &attr, (void *)&log_list_thread, NULL);
		if(ret)
		{
			fprintf(stderr, "ERROR: Can't create logging thread (errno=%d %s)", ret, strerror(ret));
			pthread_attr_destroy(&attr);
			cs_exit(1);
		}
		pthread_attr_destroy(&attr);
	}
	int32_t rc = 0;
	if(!cfg.disablelog) { rc = cs_open_logfiles(); }
	logStarted = 1;
	return rc;
}
예제 #12
0
int32_t cs_init_log(void)
{	
	if(logStarted == 0)
	{
		init_syslog_socket();
		SAFE_MUTEX_INIT_NOLOG(&log_mutex, NULL);

		cs_pthread_cond_init_nolog(__func__, &log_thread_sleep_cond_mutex, &log_thread_sleep_cond);

#if defined(WEBIF) || defined(MODULE_MONITOR)
		cs_lock_create_nolog(__func__, &loghistory_lock, "loghistory_lock", 5000);
#endif

		log_list = ll_create(LOG_LIST);

		int32_t ret = start_thread_nolog("logging", (void *)&log_list_thread, NULL, &log_thread, 0, 1);
		if(ret)
		{
			cs_exit(1);
		}
		
		logStarted = 1;
	}
	int32_t rc = 0;
	if(!cfg.disablelog) { rc = cs_open_logfiles(); }
	logStarted = 1;
	
	if(cfg.initial_debuglevel > 0) 
	{ 
		cs_dblevel = cfg.initial_debuglevel;
		cs_log("debug_level=%d", cs_dblevel);
	}
	
	return rc;
}
예제 #13
0
exp_t *
exp_list(exp_t *list, exp_t *exp)
{
	ll_t *ll;

	if (list->ex_type != EX_LIST)
	{
		ll = ll_create();
		if (ll == NULL)
		{
			log_die(EX_SOFTWARE, "exp_list: ll_create failed");
		}

		if (LL_INSERT(ll, list) == -1)
		{
			log_die(EX_SOFTWARE, "exp_list: LL_INSERT failed");
		}

		list = exp_create(EX_LIST, ll);
	}
	else
	{
		ll = list->ex_data;
	}

	if (LL_INSERT(ll, exp) == -1)
	{
		log_die(EX_SOFTWARE, "exp_list: LL_INSERT failed");
	}

	return list;
}
예제 #14
0
int main(void)
{
	struct llist *list = ll_create(1.7);

	ll_add(&list, 2.8);

	ll_print(list);

}
예제 #15
0
cache_t *get_empty_cache(int (*sync)(struct ce_t *), char *name)
{
	cache_t *c = (void *)kmalloc(sizeof(cache_t));
	c->sync = sync;
	c->syncing=0;
	c->dirty=0;
	c->rwl = rwlock_create(0);
	c->count=0;
	c->slow=1000;
	c->hash = chash_create(100000);
	strncpy(c->name, name, 32);
	ll_create(&c->dirty_ll);
	ll_create(&c->primary_ll);
	ll_insert(cache_list, c);
	
	printk(0, "[cache]: Allocated new cache '%s'\n", name);
	return c;
}
예제 #16
0
void ll_add(struct llist **list, double data)
{
	struct llist *new_node = ll_create(data);

	if(new_node) {
		new_node->tail = *list;
		(*list)->head = new_node;
		*list = new_node;
	}
}
예제 #17
0
파일: rocs_cron.c 프로젝트: TecDroiD/rocs
int add_cronjob(p_cronjob job) {
	job->timestamp += get_timestamp() + 1;
	
	log_message(INFO,"Adding job for timestamp %d, cronlist %d", job->timestamp, cronlist);
	p_linkedlist item = ll_create(job, sizeof(t_cronjob));
	log_message(DEBUG, ".");
	
	cronlist = ll_add(cronlist,item, LL_BACK, 0);
	log_message(DEBUG, "..");
}
예제 #18
0
파일: rocs_cron.c 프로젝트: TecDroiD/rocs
/**
 * remove all jobs matching the name..
 */ 
int del_cronjob(p_cronjob job){
	p_linkedlist item = ll_create(job, sizeof(t_cronjob));
	p_linkedlist remove	= ll_find(cronlist, item, jobequal);
	while(remove != 0) {
		cronlist = ll_remove(cronlist,remove);
		ll_destroy(remove);
		remove	= ll_find(cronlist, item, jobequal);
	} 

	ll_destroy(item);
}
예제 #19
0
driver_command_t *driver_command_create(select_group_t *group)
{
    driver_command_t *driver = (driver_command_t*) safe_malloc(sizeof(driver_command_t));

    driver->stream        = buffer_create(BO_BIG_ENDIAN);
    driver->group         = group;
    driver->is_shutdown   = FALSE;
    driver->outgoing_data = buffer_create(BO_LITTLE_ENDIAN);
    driver->tunnels       = ll_create(NULL);

    return driver;
}
예제 #20
0
void init_multitasking()
{
	printk(KERN_DEBUG, "[sched]: Starting multitasking system...\n");
	/* make the kernel task */
	task_t *task = task_create();
	task->pid = next_pid++;
	task->pd = (page_dir_t *)kernel_dir;
	task->stack_end=STACK_LOCATION;
	task->priority = 1;
	task->cpu = primary_cpu;
	task->thread = thread_data_create();
	/* alarm_mutex is aquired inside a kernel tick, so we may not schedule. */
	alarm_mutex = mutex_create(0, MT_NOSCHED);
	
	kill_queue = ll_create(0);
	primary_queue = tqueue_create(0, 0);
	primary_cpu->active_queue = tqueue_create(0, 0);

	tqueue_insert(primary_queue, (void *)task, task->listnode);
	tqueue_insert(primary_cpu->active_queue, (void *)task, task->activenode);
	
	primary_cpu->cur = task;
	primary_cpu->ktask = task;
	primary_cpu->numtasks=1;
	/* make this the "current_task" by assigning a specific location
	 * in the page directory as the pointer to the task. */
	arch_specific_set_current_task((addr_t *)kernel_dir, (addr_t)task);
	kernel_task = task;
	/* this is the final thing to allow the system to begin scheduling
	 * once interrupts are enabled */
	primary_cpu->flags |= CPU_TASK;
	
	add_atomic(&running_processes, 1);
#if CONFIG_MODULES
	add_kernel_symbol(delay);
	add_kernel_symbol(delay_sleep);
	add_kernel_symbol(schedule);
	add_kernel_symbol(run_scheduler);
	add_kernel_symbol(exit);
	add_kernel_symbol(sys_setsid);
	add_kernel_symbol(do_fork);
	add_kernel_symbol(kill_task);
	add_kernel_symbol(do_send_signal);
	add_kernel_symbol(dosyscall);
	add_kernel_symbol(task_pause);
	add_kernel_symbol(task_resume);
	add_kernel_symbol(got_signal);
 #if CONFIG_SMP
	add_kernel_symbol(get_cpu);
 #endif
	_add_kernel_symbol((addr_t)(task_t **)&kernel_task, "kernel_task");
#endif
}
예제 #21
0
int main () {
	printf("Tester for ll\n");
	ll * l1 = ll_create(2);
	printf("Head is %d\n",l1->head);
	ll_add(l1,"AAAAAAAAAAAAA",5,1);
	ll_add(l1,"AAAAAAAAAAAAA",5,1);
	ll_add(l1,"AAAAAAAAAAAAA",5,1);
	ll_add(l1,"AAAAAAAAAAAAA",5,1);
	ll_add(l1,"AAAAAAAAAAACCA",5,1);
	ll_add(l1,"AAAAAAAAAAACCA",5,1);
	ll_add(l1,"AAAAAAAAAAACCA",5,1);
	ll_add(l1,"AAAAAAAAAAACCA",5,1);
	ll_add(l1,"AAAAAAAAAAACCA",5,1);
	ll_add(l1,"AAAAAAAAAAACCA",5,1);
	ll_add(l1,"ACAAAAAAAAACCA",5,1);
	ll_add(l1,"ACAAAAAAAAACCA",5,1);
	ll_add(l1,"ACAAAAAAAAACCA",5,1);
	ll_add(l1,"ACAAAAAAAAACCA",5,1);
	ll_print(l1);
	int hw;
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	ll_max(l1,300,&hw,5);
	printf("There are %d max's\n",hw);
	ll_max(l1,3,&hw,5);
	printf("There are %d max's\n",hw);
	ll_max(l1,3,&hw,5);
	printf("There are %d max's\n",hw);
	ll_max(l1,3,&hw,5);
	printf("There are %d max's\n",hw);
	ll_max(l1,3,&hw,5);
	ll_max(l1,3,&hw,5);
	ll_max(l1,3,&hw,5);
	ll_max(l1,3,&hw,5);
	ll_max(l1,3,&hw,5);
	ll_max(l1,3,&hw,5);
	ll_max(l1,3,&hw,5);
	ll_max(l1,3,&hw,5);
	ll_print(l1);
	return 0;
}
예제 #22
0
파일: module-led.c 프로젝트: budiarno/NCam
static void arm_led_start_thread(void)
{
	arm_detect_led_type();
	if(!cfg.enableled || arm_led_type == LED_TYPE_UNKNOWN)
		{ return; }
	// call this after signal handling is done
	if(!arm_led_actions)
	{
		arm_led_actions = ll_create("arm_led_actions");
	}

	start_thread("arm led", arm_led_thread_main, NULL, &arm_led_thread, 1, 1);
}
예제 #23
0
bool stack_push(stack *s, double data){
    if(!s){
        return false;
    }   

    struct llist *new_head = ll_create(data);
    if(!new_head){
        return false;
    }
    new_head->next = s->head;
    s->head = new_head;
    return true;
}
예제 #24
0
PROBLEM* add_new_problem(const char* name, int number){
	static BOOL problems_initialized = FALSE;
	PROBLEM* prob;
	
	if(problems_initialized == FALSE){
		problems = ll_create(&problem_free);
		problems_initialized = TRUE;
	}
	
	prob = problem_initialize(name, number);
	ll_push_back(problems, prob);
	
	return prob;
}
예제 #25
0
int32_t cs_init_log(void)
{
	if(logStarted == 0){
#if defined(WEBIF) || defined(MODULE_MONITOR) 
		cs_lock_create(&loghistory_lock, 5, "loghistory_lock");
#endif

		log_list = ll_create(LOG_LIST);
		start_thread((void*)&log_list_thread, "log_list_thread");
	}
	int32_t rc = cs_open_logfiles();
	logStarted = 1;
	return rc;
}
예제 #26
0
obj* LinkedList() {
    obj* self = Object();
    self->dealloc = dealloc;

    list* list = ll_create();
    set_p(self, "value", &list, sizeof(struct llist_*));

    bind(self, "push back", push_back);
    bind(self, "push front", push_front);

    bind_o(self, "back", back);
    bind_o(self, "front", front);

    return self;
}
예제 #27
0
int32_t dvbapi_edit_channel_cache(int32_t demux_id, int32_t pidindex, uint8_t add)
{
	struct s_ecmpids *p = &demux[demux_id].ECMpids[pidindex];
	struct s_channel_cache *c;
	LL_ITER it;
	int32_t count = 0;

	if(!channel_cache)
		{ channel_cache = ll_create("channel cache"); }

	it = ll_iter_create(channel_cache);
	while((c = ll_iter_next(&it)))
	{
		if(demux[demux_id].program_number == c->srvid
				&& p->CAID == c->caid
				&& p->ECM_PID == c->pid
				&& (p->PROVID == c->prid || p->PROVID == 0))
		{
			if(add && p->CHID == c->chid)
			{
				return 0; //already added
			}
			ll_iter_remove_data(&it);
			count++;
		}
	}

	if(add)
	{
		if(!cs_malloc(&c, sizeof(struct s_channel_cache)))
			{ return count; }
		c->srvid = demux[demux_id].program_number;
		c->caid = p->CAID;
		c->pid = p->ECM_PID;
		c->prid = p->PROVID;
		c->chid = p->CHID;
		ll_append(channel_cache, c);
#ifdef WITH_DEBUG
		char buf[ECM_FMT_LEN];
		ecmfmt(c->caid, 0, c->prid, c->chid, c->pid, c->srvid, 0, 0, 0, 0, buf, ECM_FMT_LEN, 0, 0);
		cs_debug_mask(D_DVBAPI, "[DVBAPI] added to channel cache: %s", buf);
#endif
		count++;
	}

	return count;
}
예제 #28
0
void
module_init(int glob, ...)
{
	va_list ap;
	char *module_name;
	char *module_path;
	char buffer[BUFLEN];

	module_list = ll_create();
	if (module_list == NULL)
	{
		log_die(EX_SOFTWARE, "module_init: ll_create failed");
	}

	module_path = cf_module_path? cf_module_path: defs_module_path;

	// Search modules in the filesystem
	if (glob)
	{
		module_glob(module_path);
		return;
	}

	// Load modules supplied in va_list
	va_start(ap, glob);
	for (;;)
	{
		module_name = va_arg(ap, char *);
		if (module_name == NULL)
		{
			break;
		}

		if (strlen(module_path) + strlen(module_name) + 2 > sizeof buffer)
		{
			log_die(EX_SOFTWARE, "module_init: buffer exhausted");
		}

		strcpy(buffer, module_path);
		strcat(buffer, "/");
		strcat(buffer, module_name);

		module_load(buffer);
	}
	va_end(ap);

}
예제 #29
0
void
exp_init(void)
{
	exp_defs = sht_create(EXP_BUCKETS, NULL);
	if (exp_defs == NULL)
	{
		log_die(EX_SOFTWARE, "exp_init: sht_create failed");
	}

	exp_garbage = ll_create();
	if (exp_garbage == NULL)
	{
		log_die(EX_SOFTWARE, "exp_init: ll_create failed");
	}

	return;
}
예제 #30
0
int32_t cacheex_add_stats(struct s_client *cl, uint16_t caid, uint16_t srvid, uint32_t prid, uint8_t direction)
{
    if(!cfg.cacheex_enable_stats)
    {
        return -1;
    }

    // create list if doesn't exist
    if(!cl->ll_cacheex_stats)
    {
        cl->ll_cacheex_stats = ll_create("ll_cacheex_stats");
    }

    time_t now = time((time_t *)0);
    LL_ITER itr = ll_iter_create(cl->ll_cacheex_stats);
    S_CACHEEX_STAT_ENTRY *cacheex_stats_entry;

    // check for existing entry
    while((cacheex_stats_entry = ll_iter_next(&itr)))
    {
        if(cacheex_stats_entry->cache_srvid == srvid &&
                cacheex_stats_entry->cache_caid == caid &&
                cacheex_stats_entry->cache_prid == prid &&
                cacheex_stats_entry->cache_direction == direction)
        {
            // we already have this entry - just add count and time
            cacheex_stats_entry->cache_count++;
            cacheex_stats_entry->cache_last = now;
            return cacheex_stats_entry->cache_count;
        }
    }

    // if we land here we have to add a new entry
    if(cs_malloc(&cacheex_stats_entry, sizeof(S_CACHEEX_STAT_ENTRY)))
    {
        cacheex_stats_entry->cache_caid = caid;
        cacheex_stats_entry->cache_srvid = srvid;
        cacheex_stats_entry->cache_prid = prid;
        cacheex_stats_entry->cache_count = 1;
        cacheex_stats_entry->cache_last = now;
        cacheex_stats_entry->cache_direction = direction;
        ll_iter_insert(&itr, cacheex_stats_entry);
        return 1;
    }
    return 0;
}