Постоянное множественное хранилище типа "ключ-значение" GWAN

Я хочу записать ключ-значение в постоянном режиме, но когда я хочу использовать 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 = "[email protected]";
          item.flags = 0;
          kv_add(data[0]->kv, &item);

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

Эта ошибка находится в строке 15 с функцией kv_init ().

Я хотел бы, например, использовать data [0] -> kv для чтения и записи значения в магазине «users» и использовать < strong> data [1] -> kv для чтения и записи значения в другом хранилище ...


person John S    schedule 26.04.2014    source источник
comment
Можете уточнить, какую ошибку вы получаете?   -  person Nagi    schedule 27.04.2014


Ответы (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 - настраиваемый макрос)

person Nagi    schedule 27.04.2014
comment
спасибо за помощь, ваше решение работает. Но подразумеваете ли вы, что оно менее оптимизировано (с точки зрения производительности), чем решение, предложенное Гилом ниже? (что, кстати, мне не удалось заставить работать) Потому что у меня может быть очень большое количество данных для одновременной обработки. С Уважением. - person John S; 27.04.2014
comment
В моем решении я должен выполнять поиск (*blog_db = (kv_t *) kv_get(kv_db[0], "blog_db", 7);) всякий раз, когда я хочу получить доступ к своему blog_db kv; в решении Гила у него есть прямой доступ к нему, поскольку это просто поле в структуре. Так что, конечно, мое решение менее оптимизировано. - person Nagi; 28.04.2014
comment
Кстати, размер вашего набора данных (размер каждого хранилища kv) не имеет значения в этом случае, поскольку в моем решении важно количество хранилищ kv. В любом случае, если у вас слишком много магазинов кв, возможно, вы захотите пересмотреть свой дизайн. Подумайте об объединении хранилищ kv, используя вместо этого ключевые префиксы (например, user_db: префикс для пользователя kv, blog_db: префикс для сообщений и т. Д.) - person Nagi; 28.04.2014

Джон,

Ваша проблема связана с трудностью играть с указателями на указатели. Мы могли бы исправить этот код, но он, вероятно, сломается позже в ваших скриптах из-за своей сложности.

В долгосрочной перспективе следует использовать более простое решение, чтобы избежать ошибок.

Структуру, прикрепленную к 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.

Затем, если вы делаете все это в вызове init() обработчика G-WAN (или в gwan/main.c сценарии обслуживания, или даже в недавно добавленном gwan/init.c сценарии), у вас будет монопольный доступ (инициализация выполняется одним потоком), и вы получите иметь возможность атаковать магазины G-WAN KV (и другие объекты) по мере необходимости.

Если позже сервлеты или обработчики G-WAN изменяют эти указатели на структуру, вам придется использовать блокировку, спин-блокировку и т. Д. Или атомарные переменные для самих указателей.

Надеюсь это поможет.

person Gil    schedule 26.04.2014