【问题标题】:GWAN Key-Value persistent multiple storeGWAN Key-Value 持久化多重存储
【发布时间】:2014-06-11 21:47:59
【问题描述】:

我想在持久模式下记录一个键值,但是当我想使用 2 个或更多不同的存储时它不起作用。

这是我的脚本:

    ...
    typedef struct{
       kv_t  *kv;
       char  *name;
    } kv_data;

    int main(int argc, char *argv[])
    {
       kv_data **data = (kv_data**)get_env(argv, US_SERVER_DATA);
       if(!data[0]){
          data[0] = (kv_data*)calloc(1, sizeof(kv_data));
          if(!data[0]){
             return 500;
          }
          kv_t users;
          kv_init(&users, "users", 10, 0, 0, 0);
          data[0]->kv = &users;

          kv_item item;
          item.key = "pierre";
          item.klen = sizeof("pierre") - 1;
          item.val = "pierre@example.com";
          item.flags = 0;
          kv_add(data[0]->kv, &item);

          data[0]->name = strdup("users");
       }
    ...

这个错误出现在第 15 行,使用 kv_init() 函数。

我的愿望是例如使用 data[0]->kv 来读取和记录“users”存储中的值和使用 data[1]->kv 读取和记录 other 存储中的值...

【问题讨论】:

  • 你能澄清你得到的错误吗?

标签: c key-value g-wan key-value-store


【解决方案1】:

约翰,

您的问题来自于在指针上玩指针的困难。我们可以修复此代码,但由于其复杂性,它可能会在您的脚本中中断。

从长远来看,应该使用更简单的解决方案来避免错误。

US_SERVER_DATA 附加的结构可以更简单:

typedef struct
{
   char *name;
   kv_t *kv_1;
   kv_t *kv_2;
   void *callback;
   u32   current_time;
}

这是要走的路:使用calloc(sizeof(my_struct)); 分配内存,并将此结构附加到您的US_SERVER_DATA 指针。

然后,如果您在 G-WAN 处理程序 init() 调用(或在 gwan/main.c 维护脚本中,甚至在最近添加的 gwan/init.c 脚​​本中)执行所有这些操作,您将拥有独占访问权限(一个线程正在执行初始化),您将能够根据需要攻击 G-WAN KV 存储(和其他对象)。

如果稍后 G-WAN servlet 或处理程序正在修改这些结构指针,那么您将不得不为指针本身使用锁、自旋锁等或原子变量。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我只是将一个包含我需要的所有 kv 存储的 kv 存储附加到持久性指针。 G-WAN kv 速度快,加上记录数少,应该不会影响性能。

      xbuf_t *reply = get_reply(argv);
      kv_t **kv_db = (kv_t **)get_env(argv, US_VHOST_DATA);
    
      if (!kv_db[0])
      {
         kv_db[0] = (kv_t*) malloc(sizeof(kv_t));
    
         if (!kv_db[0])
         {
            puts("Could not allocate memory for the v-host kv store");
            return 500;
         }
    
         kv_init(kv_db[0], "kv_db", 10, 0, 0, 0);
      }
    
      kv_t *blog_db = (kv_t *) kv_get(kv_db[0], "blog_db", 7);
    
      if (blog_db)
      {
         xbuf_cat(reply, "Blog already installed. GTFO.");
         return 200;
      }
    
      blog_db = (kv_t *) malloc(sizeof(kv_t));
      kv_init(blog_db, "blog_db", 0, 0, 0, 0);
    
      if (!blog_db)
      {
         puts("Could not allocate memory for the blog kv store");
         return 500;
      }
    
      _KV_ADD(kv_db[0], item, blog_db->name, blog_db, 0);
    

    (_KV_ADD 是自定义宏)

    【讨论】:

    • 感谢您的帮助,您的解决方案有效。但是您是否暗示它的优化程度低于 Gil 下面提出的解决方案(从性能的角度来看)? (顺便说一句,我没能成功)因为我可能要同时处理大量数据。问候。
    • 在我的解决方案中,每当我想访问我的 blog_db kv 时,我都必须执行查找 (*blog_db = (kv_t *) kv_get(kv_db[0], "blog_db", 7););在 Gil 的解决方案中,他可以直接访问它,因为它只是结构中的一个字段。所以当然我的解决方案没有那么优化。
    • 顺便说一句,在这种情况下,数据集的大小(每个 kv 存储的大小)无关紧要,因为在我的解决方案中重要的是 kv 存储的数量。无论如何,如果您的 kv 商店太多,您可能需要重新考虑您的设计。考虑使用键前缀来合并 kv 存储(例如:用户 kv 的“user_db:”前缀,帖子的“blog_db:”前缀等)