Пример #1
0
bool session::set(const char* name, const void* value, size_t len,
	bool delay /* = false */)
{
	if (delay)
	{
		std::map<string, VBUF*>::iterator it = attrs_cache_.find(name);
		if (it == attrs_cache_.end())
			attrs_cache_[name] = vbuf_new(value, len, TODO_SET);
		else
			attrs_cache_[name] = vbuf_set(it->second, value, len, TODO_SET);
		dirty_ = true;
		return true;
	}

	// 直接操作后端 cache 服务器,设置(添加/修改) 属性字段

	string buf(256);

	// 调用纯虚接口,获得原来的 sid 数据
	if (get_data(sid_->buf, buf) == false)
	{
		// 如果没有则创建新的 sid 数据
		serialize(name, value, len, buf);
	}

	// 如果存在对应 sid 的数据,则将新数据添加在原来数据中
	else
	{
		if (!sid_saved_)
			sid_saved_ = true;

		// 反序列化
		deserialize(buf, attrs_);

		// 如果该属性已存在,则需要先释放原来的属性值后再添加新值

		std::map<string, VBUF*>::iterator it = attrs_.find(name);
		if (it == attrs_.end())
			attrs_[name] = vbuf_new(value, len, TODO_SET);
		else
			attrs_[name] = vbuf_set(it->second, value, len, TODO_SET);
		serialize(attrs_, buf);  // 序列化数据
		attrs_clear(attrs_);
	}

	// 调用纯虚接口,向 memcached 或类似缓存中添加数据
	if (set_data(sid_->buf, buf.c_str(), buf.length(), ttl_) == false)
	{
		logger_error("set cache error, sid(%s)", sid_->buf);
		return false;
	}
	if (!sid_saved_)
		sid_saved_ = true;
	return true;
}
Пример #2
0
void session::deserialize(string& buf, std::map<string, VBUF*>& attrs)
{
	attrs_clear(attrs);  // 先重置 session 前一次查询状态

	ACL_ARGV* tokens = acl_argv_split(buf.c_str(), "\t");
	ACL_ITER  iter;
	acl_foreach(iter, tokens)
	{
		char* ptr = (char*) iter.data;

		// 重复使用原来的内存区,因为 tokens 中已经存储了中间结果数据
		buf.clear();
		if (unescape(ptr, strlen(ptr), buf) == false)
		{
			logger_error("unescape error");
			continue;
		}
		ptr = buf.c_str();
		// 因为 acl::string 肯定能保证缓冲区数据的尾部有 \0,所以在用
		// strchr 时不必须担心越界问题,但 std::string 并不保证这样
		char* p1 = strchr(ptr, 1);
		if (p1 == NULL || *(p1 + 1) == 0)
			continue;
		*p1++ = 0;
		std::map<string, VBUF*>::iterator it = attrs.find(ptr);

		// xxx: 以防有重复的属性
		if (it != attrs.end())
			vbuf_free(it->second);
		// 将从后端取得数据属性都设为 TODO_SET
		attrs[ptr] = vbuf_new(p1, buf.length() - (p1 - buf.c_str()), TODO_SET);
	}
Пример #3
0
session::session(time_t ttl /* = 0 */, const char* sid /* = NULL */)
: ttl_(ttl)
, dirty_(false)
{
	struct timeval tv;

	(void) gettimeofday(&tv, NULL);
	if (sid == NULL || *sid == 0)
	{
		char buf[128];
		snprintf(buf, sizeof(buf), "acl.%d.%d.%d", (int) tv.tv_sec,
			(int) tv.tv_usec, rand());
		sid_ = vbuf_new(buf, strlen(buf), TODO_NUL);
		sid_saved_ = false;
	}
	else
	{
		sid_ = vbuf_new(sid, strlen(sid), TODO_NUL);
		sid_saved_ = true;
	}
}
Пример #4
0
bool session::del(const char* name, bool delay /* = false */)
{
	if (delay)
	{
		std::map<string, VBUF*>::iterator it = attrs_cache_.find(name);
		if (it == attrs_cache_.end())
			attrs_cache_[name] = vbuf_new("", 0, TODO_DEL);
		else
			it->second->todo = TODO_DEL;
		dirty_ = true;
		return true;
	}

	// 直接操作后端 cache 服务器,删除属性字段

	string buf(256);
	if (get_data(sid_->buf, buf) == false)
		return true;

	deserialize(buf, attrs_);
	std::map<string, VBUF*>::iterator it = attrs_.find(name);
	if (it == attrs_.end())
		return false;

	// 先删除并释放对应的对象
	vbuf_free(it->second);
	attrs_.erase(it);

	// 如果 sid 中已经没有了数据,则应该将 sid 对象从 memcached 中删除
	if (attrs_.empty())
	{
		// 调用虚函数,删除该 sid 对应的缓存内容
		if (del_data(sid_->buf) == false)
		{
			logger_error("del sid(%s) error", sid_->buf);
			return false;
		}
		return true;
	}

	// 向 memcached 中重新添加剩余的数据

	serialize(attrs_, buf);
	attrs_clear(attrs_);

	if (set_data(sid_->buf, buf.c_str(), buf.length(), ttl_) == false)
	{
		logger_error("set cache error, sid(%s)", sid_->buf);
		return false;
	}
	return true;
}
Пример #5
0
// TODO add API unit tests
int main()
{
    int i, r;
    const int szbuf = 40, szfrag = szbuf / 4 * 3;
    const char src[szbuf *2] = "hello, world";
    const char *fragstring = "1234567890ABCDEFGHIJabcdefhijk";
    const char *s;
    char dest[szbuf*2] = "";
    VBUF vbuf, *v = &vbuf;
    vbuf_new(v, szbuf);

    // check basic structure
    assert(v->buf && v->capacity == szbuf -1);
    assert(v->head == v->tail && v->tail == v->buf);
    assert(v->buf_end == v->buf + v->capacity + 1);

    // fragmentize it!
    vbuf_dbg_fragmentize(v);
    assert(vbuf_is_empty(v) && !vbuf_is_full(v));
    vbuf_putblk(v, src, szfrag);

    // check macro API
    assert(!vbuf_is_empty(v));
    assert(!vbuf_is_full(v));
    assert(vbuf_capacity(v) == szbuf-1);
    assert(vbuf_size(v) == szfrag);
    assert(vbuf_space(v) == vbuf_capacity(v) - szfrag);
    assert(vbuf_peek(v) == src[0]);

    // try filling buffer with putblk/getblk
    vbuf_dbg_fragmentize(v);
    for (i = 0; i < 10; i++)
    {
        r = vbuf_putblk(v, src, szbuf / 10);
        vbuf_dbg_rpt(v);
        assert( i == 9 ? !r : r);
        assert(!vbuf_is_full(v));
    }
    r = vbuf_putblk(v, src, vbuf_capacity(v) - vbuf_size(v));
    assert(r && vbuf_is_full(v) && !vbuf_is_empty(v));

    for (i = 0; i < 10; i++)
    {
        r = vbuf_getblk(v, dest, szbuf / 10);
        dest[szbuf/10] = 0;
        printf("%2d. [got: %s] ", i+1, dest);
        vbuf_dbg_rpt(v);
        assert(i == 9 ? !r : r);
        assert(!vbuf_is_full(v) && !vbuf_is_empty(v));
    }
    r = vbuf_getblk(v, dest, vbuf_size(v));
    assert(r && vbuf_is_empty(v) && !vbuf_is_full(v));

    // try unframgented
    vbuf_clear(v);
    r = vbuf_putblk(v, src, vbuf_capacity(v));
    assert(r && vbuf_is_full(v));
    r = vbuf_putblk(v, src, 1);
    assert(!r);
    r = vbuf_getblk(v, dest, szbuf-1);
    assert(r && vbuf_is_empty(v));
    r = vbuf_getblk(v, dest, 1);
    assert(!r && vbuf_is_empty(v));
    r = vbuf_putblk(v, src, szbuf);
    assert(!r && vbuf_is_empty(v));

    // string operation
    vbuf_clear(v);
    vbuf_putstr(v, "str test(1)");
    vbuf_putstr(v, "str test(2)");
    vbuf_putstr(v, "str test(3)");
    for (i = 0; i < 4; i++)
    {
        s = vbuf_getstr(v, dest, sizeof(dest));
        printf("put/getstr(%d): %s\n", i+1,
                s ? s : "(NULL)");
        assert(i < 3 ? s != NULL : s == NULL);
    }

    // cstr test
    vbuf_clear(v);
    vbuf_putstr(v, fragstring);
    vbuf_dbg_rpt(v);
    s = vbuf_cstr(v);
    printf("cstr test(simple): %s\n", s);
    assert(strcmp(s, fragstring)  == 0);
    vbuf_dbg_fragmentize(v);
    vbuf_putstr(v, fragstring);
    vbuf_dbg_rpt(v);
    s = vbuf_cstr(v);
    printf("cstr test(unwrap): %s\n", s);
    assert(strcmp(s, fragstring)  == 0);

    vbuf_dbg_fragmentize(v);
    vbuf_putblk(v, "*** peek test OK\n", sizeof("*** peek test OK\n"));
    while (EOF != (i = vbuf_pop(v)))
        putchar(i);

    // read/write test
    vbuf_dbg_fragmentize(v);
    printf("give me some input for finding location of 't': "); fflush(stdout);
    vbuf_read(v, 0, VBUF_RWSZ_MIN);
    printf("index of 't' = %d\n", vbuf_strchr(v, 't'));
    vbuf_dbg_rpt(v);
    printf("give me 4 chars: "); fflush(stdout);
    vbuf_read(v, 0, 4);
    vbuf_dbg_rpt(v);
    printf("\n flushing vbuf: ["); fflush(stdout);
    vbuf_write(v, 1, VBUF_RWSZ_ALL);
    printf("]\n");

    return 0;
}