/*
 * Create and insert new contact
 * into urecord
 */
int insert_ucontact(urecord_t* _r, str* aor, str* _c, time_t _e, qvalue_t _q, str* _cid, 
					int _cs, unsigned int _flags, struct ucontact** _con, str* _ua, str* _recv,
					struct socket_info* sock, str* _inst, int sid)
{
	if (mem_insert_ucontact(_r, aor, _c, _e, _q, _cid, _cs, _flags, _con, _ua, _recv, sock, _inst, sid) < 0) {
		LOG(L_ERR, "insert_ucontact(): Error while inserting contact\n");
		return -1;
	}

	notify_watchers(_r, *_con, (_e > 0) ? PRES_ONLINE : PRES_OFFLINE);

	if (exists_ulcb_type(UL_CONTACT_INSERT)) {
		run_ul_callbacks( UL_CONTACT_INSERT, *_con);
	}

	save_reg_avps(*_con);
	
	if (db_mode == WRITE_THROUGH) {
		if (db_store_ucontact(*_con) < 0) {
			LOG(L_ERR, "insert_ucontact(): Error while inserting in database\n");
		}
		(*_con)->state = CS_SYNC;
	}

	return 0;
}
Exemple #2
0
void thread_impl_t::set_state( THREAD_STATE state )
{
	ULONG prev_state = ThreadState;

	if (prev_state == StateTerminated)
		return;

	ThreadState = state;
	switch (state)
	{
	case StateWait:
		runlist_remove();
		break;
	case StateRunning:
		runlist_add();
		break;
	case StateTerminated:
		notify_watchers();
		if (prev_state == StateRunning)
			runlist_remove();
		break;
	default:
		die("switch to unknown thread state\n");
	}

	// ready to complete some I/O?
	if (num_active_threads() == 0)
		check_completions();
}
Exemple #3
0
void event_impl_t::set( PULONG prev )
{
	*prev = state;
	state = 1;

	notify_watchers();
}
/*
 * This timer routine is used when
 * db_mode is set to NO_DB
 */
static inline int nodb_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int not = 0;

	ptr = _r->contacts;

	while(ptr) {
		if (ptr->expires < act_time) {
			if (ptr->replicate != 0) {
				LOG(L_NOTICE, "Keeping binding '%.*s','%.*s' for replication\n", 
				    ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s));

					/* keep it for replication, but it expired normaly
					 * and was the last contact, so notify */
				if (!ptr->next && ptr->state == CS_NEW) not=1;

				ptr = ptr->next;
			}
			else {
				LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
				    ptr->aor->len, ZSW(ptr->aor->s),
				    ptr->c.len, ZSW(ptr->c.s));

				t = ptr;
				ptr = ptr->next;

					/* it was the last contact and it was in normal
					 * state, so notify */
				if (!ptr && t->state == CS_NEW) not=1;

				mem_delete_ucontact(_r, t);
				_r->slot->d->expired++;

			}
			     /* Last contact expired, notify watchers */
			if (not) notify_watchers(_r, PRES_OFFLINE);
		} else {
				/* the contact was unregistered and is not marked 
				 * for replication so remove it, but the notify was
				 * done during unregister */
			if (ptr->state == CS_ZOMBIE_N && ptr->replicate == 0) {
				LOG(L_NOTICE, "removing spare zombie '%.*s','%.*s'\n",
				    ptr->aor->len, ZSW(ptr->aor->s),
				    ptr->c.len, ZSW(ptr->c.s));
				t = ptr;
				ptr = ptr->next;
				mem_delete_ucontact(_r, t);
			}
			else
				ptr = ptr->next;
		}
	}

	return 0;
}
Exemple #5
0
static void
apteryx__prune (Apteryx__Server_Service *service,
                const Apteryx__Prune *prune,
                Apteryx__OKResult_Closure closure, void *closure_data)
{
    Apteryx__OKResult result = APTERYX__OKRESULT__INIT;
    result.result = 0;
    GList *paths = NULL, *iter;
    (void) service;

    /* Check parameters */
    if (prune == NULL || prune->path == NULL)
    {
        ERROR ("PRUNE: Invalid parameters.\n");
        result.result = -EINVAL;
        closure (&result, closure_data);
        INC_COUNTER (counters.prune_invalid);
        return;
    }
    INC_COUNTER (counters.prune);

    DEBUG ("PRUNE: %s\n", prune->path);

    /* Proxy first */
    if (proxy_prune (prune->path))
    {
        /* Return result */
        closure (&result, closure_data);
        return;
    }

    /* Collect the list of deleted paths for notification */
    paths = g_list_prepend(paths, g_strdup(prune->path));
    _search_paths (&paths, prune->path);

    /* Prune from database */
    db_delete (prune->path, UINT64_MAX);

    /* Return result */
    closure (&result, closure_data);

    /* Call watchers for each pruned path */
    for (iter = paths; iter; iter = g_list_next (iter))
    {
        notify_watchers ((const char *)iter->data);
    }

    g_list_free_full (paths, g_free);
    return;
}
/*
 * This routine is used when db_mode is
 * set to WRITE_THROUGH
 */
static inline int wt_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int not = 0;
	
	ptr = _r->contacts;
	
	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
			}

			notify_watchers(_r, ptr, PRES_OFFLINE);

			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
			    ptr->uid->len, ZSW(ptr->uid->s),
			    ptr->c.len, ZSW(ptr->c.s));
			
			t = ptr;
			ptr = ptr->next;
			
			     /* it was the last contact and it was in normal
			      * state, so notify */
			if (!ptr && t->state == CS_SYNC) not=1;
		
			if (db_delete_ucontact(t) < 0) {
				LOG(L_ERR, "wt_timer(): Error while deleting contact from "
				    "database\n");
			}

			delete_reg_avps(t);			
			mem_delete_ucontact(_r, t);
			_r->slot->d->expired++;
		} else {
			     /* the contact was unregistered and is not marked 
			      * for replication so remove it, but the notify was
			      * already done during unregister */
			ptr = ptr->next;
		}
	}
	
	return 0;
}
/*
 * Create and insert new contact
 * into urecord
 */
int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, 
			int _cs, unsigned int _flags, int _rep, struct ucontact** _con)
{
	if (mem_insert_ucontact(_r, _c, _e, _q, _cid, _cs, _flags, _rep, _con) < 0) {
		LOG(L_ERR, "insert_ucontact(): Error while inserting contact\n");
		return -1;
	}

	notify_watchers(_r, PRES_ONLINE);
	
	if (db_mode == WRITE_THROUGH) {
		if (db_insert_ucontact(*_con) < 0) {
			LOG(L_ERR, "insert_ucontact(): Error while inserting in database\n");
			mem_delete_ucontact(_r, *_con);
			return -2;
		}
		(*_con)->state=CS_SYNC;
	}

	return 0;
}
/*
 * Delete ucontact from urecord
 */
int delete_ucontact(urecord_t* _r, struct ucontact* _c)
{
	if (exists_ulcb_type(UL_CONTACT_DELETE)) {
		run_ul_callbacks( UL_CONTACT_DELETE, _c);
	}

	notify_watchers(_r, _c, PRES_OFFLINE);
	
	if (st_delete_ucontact(_c) > 0) {
		if (db_mode == WRITE_THROUGH) {
			if (db_delete_ucontact(_c) < 0) {
				LOG(L_ERR, "delete_ucontact(): Can't remove contact from "
							"database\n");
			}
		}

		delete_reg_avps(_c);
		mem_delete_ucontact(_r, _c);
	}

	return 0;
}
/*
 * Delete ucontact from urecord
 */
int delete_ucontact(urecord_t* _r, struct ucontact* _c)
{
	struct ucontact* ptr;

	if (st_delete_ucontact(_c) > 0) {
		if (db_mode == WRITE_THROUGH) {
			if (db_delete_ucontact(_c) < 0) {
				LOG(L_ERR, "delete_ucontact(): Can't remove contact from "
							"database\n");
			}
		}
		mem_delete_ucontact(_r, _c);
	}

	ptr = _r->contacts;
	while(ptr) {
		if (ptr->state < CS_ZOMBIE_N) return 0;
		ptr = ptr->next;
	}
	notify_watchers(_r, PRES_OFFLINE);

	return 0;
}
Exemple #10
0
/*
 * This timer routine is used when
 * db_mode is set to NO_DB or READONLY
 */
static inline int nodb_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int not = 0;

	ptr = _r->contacts;

	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE))
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);

			notify_watchers(_r, ptr, PRES_OFFLINE);
	
			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
			    ptr->uid->len, ZSW(ptr->uid->s),
			    ptr->c.len, ZSW(ptr->c.s));
			
			t = ptr;
			ptr = ptr->next;
			
			     /* it was the last contact and it was in normal
			      * state, so notify */
			if (!ptr && t->state == CS_NEW) not=1;
			
			delete_reg_avps(t);
			mem_delete_ucontact(_r, t);
			_r->slot->d->expired++;
		} else {
			ptr = ptr->next;
		}
	}

	return 0;
}
Exemple #11
0
/*
 * Write-back timer
 */
static inline int wb_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int op;
	int not = 0;

	ptr = _r->contacts;

	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
			}

			notify_watchers(_r, ptr, PRES_OFFLINE);
	
			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
			    ptr->uid->len, ZSW(ptr->uid->s),
			    ptr->c.len, ZSW(ptr->c.s));
			if (ptr->next == 0) not=1;
			_r->slot->d->expired++;

			t = ptr;
			ptr = ptr->next;
			
			     /* Should we remove the contact from the database ? */
			if (st_expired_ucontact(t) == 1) {
				if (db_delete_ucontact(t) < 0) {
					LOG(L_ERR, "wb_timer(): Can't delete contact from the database\n");
				}
			}
			
			delete_reg_avps(t);
			mem_delete_ucontact(_r, t);
		} else {
			     /* Determine the operation we have to do */
			op = st_flush_ucontact(ptr);
			
			switch(op) {
			case 0: /* do nothing, contact is synchronized */
				break;

			case 1: /* insert */
				if (db_store_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Error while inserting contact into database\n");
				}
				break;

			case 2: /* update */
				if (db_store_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Error while updating contact in db\n");
				}
				break;

			case 4: /* delete */
				if (db_delete_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Can't delete contact from database\n");
				}
				     /* fall through to the next case statement */

			case 3: /* delete from memory */
				delete_reg_avps(ptr);
				mem_delete_ucontact(_r, ptr);
				break;
			}

			ptr = ptr->next;
		}
	}

	return 0;
}
Exemple #12
0
static void
apteryx__set (Apteryx__Server_Service *service,
              const Apteryx__Set *set,
              Apteryx__OKResult_Closure closure, void *closure_data)
{
    Apteryx__OKResult result = APTERYX__OKRESULT__INIT;
    const char *path = NULL;
    const char *value = NULL;
    result.result = 0;
    int validation_result = 0;
    int validation_lock = 0;
    int proxy_result = 0;
    bool db_result = false;
    int i;

    /* Check parameters */
    if (set == NULL || set->n_sets == 0 || set->sets == NULL)
    {
        ERROR ("SET: Invalid parameters.\n");
        result.result = -EINVAL;
        closure (&result, closure_data);
        INC_COUNTER (counters.set_invalid);
        return;
    }
    INC_COUNTER (counters.set);

    /* Debug */
    for (i=0; apteryx_debug && i<set->n_sets; i++)
    {
        DEBUG ("SET: %s = %s\n", set->sets[i]->path, set->sets[i]->value);
    }

    /* Proxy first */
    for (i=0; i<set->n_sets; i++)
    {
        path = set->sets[i]->path;
        value = set->sets[i]->value;
        if (value && value[0] == '\0')
            value = NULL;

        proxy_result = proxy_set (path, value, set->ts);
        if (proxy_result == 0)
        {
            /*  Result success */
            DEBUG ("SET: %s = %s proxied\n", path, value);
            /* Mark the set as processed */
            notify_watchers (set->sets[i]->path);
            free (set->sets[i]->path);
            set->sets[i]->path = NULL;
        }
        else if (proxy_result < 0)
        {
            result.result = proxy_result;
            goto exit;
        }
    }

    /* Validate */
    for (i=0; i<set->n_sets; i++)
    {
        path = set->sets[i]->path;
        if (!path)
            continue;
        value = set->sets[i]->value;
        if (value && value[0] == '\0')
            value = NULL;

        /* Validate new data */
        validation_result = validate_set (path, value);
        if (validation_result != 0)
            validation_lock++;
        if (validation_result < 0)
        {
            DEBUG ("SET: %s = %s refused by validate\n", path, value);
            result.result = validation_result;
            goto exit;
        }
    }

    /* Set in the database */
    pthread_rwlock_wrlock (&db_lock);
    for (i=0; i<set->n_sets; i++)
    {
        path = set->sets[i]->path;
        if (!path)
            continue;
        value = set->sets[i]->value;
        if (value && value[0] == '\0')
            value = NULL;

        /* Add/Delete to/from database */
        if (value)
            db_result = db_add_no_lock (path, (unsigned char*)value, strlen (value) + 1, set->ts);
        else
            db_result = db_delete_no_lock (path, set->ts);
        if (!db_result)
        {
            DEBUG ("SET: %s = %s refused by DB\n", path, value);
            result.result = -EBUSY;
            pthread_rwlock_unlock (&db_lock);
            goto exit;
        }
    }
    pthread_rwlock_unlock (&db_lock);

    /* Set succeeded */
    result.result = 0;

exit:
    /* Return result and notify watchers */
    if (validation_result >= 0 && result.result == 0)
    {
        /* Notify watchers */
        for (i=0; i<set->n_sets; i++)
        {
            if (set->sets[i]->path)
                notify_watchers (set->sets[i]->path);
        }
    }

    /* Return result */
    closure (&result, closure_data);

    /* Release validation lock - this is a sensitive value */
    while (validation_lock)
    {
        DEBUG("SET: unlocking mutex\n");
        pthread_mutex_unlock (&validating);
        validation_lock--;
    }
    return;
}
/*
 * Write-back timer
 */
static inline int wb_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int op;
	int not = 0;

	ptr = _r->contacts;

	while(ptr) {
		if (ptr->expires < act_time) {
			if (ptr->replicate != 0) {
				LOG(L_NOTICE, "Keeping binding '%.*s','%.*s' for "
					"replication\n", ptr->aor->len, ZSW(ptr->aor->s),
				    ptr->c.len, ZSW(ptr->c.s));

					/* keep it for replication, but it expired normaly
					 * and was the last contact, so notify */
				if (!ptr->next && ptr->state < CS_ZOMBIE_N) not=1;

				ptr = ptr->next;
			}
			else {
					/* state == ZOMBIE the contact was remove by user */
				if (ptr->state < CS_ZOMBIE_N) { 
					LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
					    ptr->aor->len, ZSW(ptr->aor->s),
					    ptr->c.len, ZSW(ptr->c.s));
					if (ptr->next == 0) not=1;
					_r->slot->d->expired++;
				}
				t = ptr;
				ptr = ptr->next;

				     /* Should we remove the contact from the database ? */
				if (st_expired_ucontact(t) == 1) {
					if (db_delete_ucontact(t) < 0) {
						LOG(L_ERR, "wb_timer(): Can't delete contact from the database\n");
					}
				}

				mem_delete_ucontact(_r, t);
			}
			if (not) notify_watchers(_r, PRES_OFFLINE);
		} else {
			     /* Determine the operation we have to do */
			op = st_flush_ucontact(ptr);
			
			switch(op) {
			case 0: /* do nothing, contact is synchronized */
				break;

			case 1: /* insert */
				if (db_insert_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Error while inserting contact into database\n");
				}
				break;

			case 2: /* update */
				if (db_update_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Error while updating contact in db\n");
				}
				break;
			case 3: /* delete from memory */
				mem_delete_ucontact(_r, ptr);
				break;
			case 4: /* delete */
				if (db_delete_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Can't delete contact from database\n");
				}
				mem_delete_ucontact(_r, ptr);
				break;
			}

			ptr = ptr->next;
		}
	}

	return 0;
}