Tools: hv: Support enumeration from all the pools
[linux-flexiantxendom0.git] / tools / hv / hv_kvp_daemon.c
index 2fb9c3d..146fd61 100644 (file)
@@ -148,6 +148,51 @@ static void kvp_update_file(int pool)
        kvp_release_lock(pool);
 }
 
+static void kvp_update_mem_state(int pool)
+{
+       FILE *filep;
+       size_t records_read = 0;
+       struct kvp_record *record = kvp_file_info[pool].records;
+       struct kvp_record *readp;
+       int num_blocks = kvp_file_info[pool].num_blocks;
+       int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
+
+       kvp_acquire_lock(pool);
+
+       filep = fopen(kvp_file_info[pool].fname, "r");
+       if (!filep) {
+               kvp_release_lock(pool);
+               syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
+               exit(-1);
+       }
+       while (!feof(filep)) {
+               readp = &record[records_read];
+               records_read += fread(readp, sizeof(struct kvp_record),
+                                       ENTRIES_PER_BLOCK * num_blocks,
+                                       filep);
+
+               if (!feof(filep)) {
+                       /*
+                        * We have more data to read.
+                        */
+                       num_blocks++;
+                       record = realloc(record, alloc_unit * num_blocks);
+
+                       if (record == NULL) {
+                               syslog(LOG_ERR, "malloc failed");
+                               exit(-1);
+                       }
+                       continue;
+               }
+               break;
+       }
+
+       kvp_file_info[pool].num_blocks = num_blocks;
+       kvp_file_info[pool].records = record;
+       kvp_file_info[pool].num_records = records_read;
+
+       kvp_release_lock(pool);
+}
 static int kvp_file_init(void)
 {
        int ret, fd;
@@ -223,8 +268,16 @@ static int kvp_key_delete(int pool, __u8 *key, int key_size)
 {
        int i;
        int j, k;
-       int num_records = kvp_file_info[pool].num_records;
-       struct kvp_record *record = kvp_file_info[pool].records;
+       int num_records;
+       struct kvp_record *record;
+
+       /*
+        * First update the in-memory state.
+        */
+       kvp_update_mem_state(pool);
+
+       num_records = kvp_file_info[pool].num_records;
+       record = kvp_file_info[pool].records;
 
        for (i = 0; i < num_records; i++) {
                if (memcmp(key, record[i].key, key_size))
@@ -259,14 +312,23 @@ static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
 {
        int i;
        int j, k;
-       int num_records = kvp_file_info[pool].num_records;
-       struct kvp_record *record = kvp_file_info[pool].records;
-       int num_blocks = kvp_file_info[pool].num_blocks;
+       int num_records;
+       struct kvp_record *record;
+       int num_blocks;
 
        if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
                (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
                return 1;
 
+       /*
+        * First update the in-memory state.
+        */
+       kvp_update_mem_state(pool);
+
+       num_records = kvp_file_info[pool].num_records;
+       record = kvp_file_info[pool].records;
+       num_blocks = kvp_file_info[pool].num_blocks;
+
        for (i = 0; i < num_records; i++) {
                if (memcmp(key, record[i].key, key_size))
                        continue;
@@ -304,13 +366,21 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
                        int value_size)
 {
        int i;
-       int num_records = kvp_file_info[pool].num_records;
-       struct kvp_record *record = kvp_file_info[pool].records;
+       int num_records;
+       struct kvp_record *record;
 
        if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
                (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
                return 1;
 
+       /*
+        * First update the in-memory state.
+        */
+       kvp_update_mem_state(pool);
+
+       num_records = kvp_file_info[pool].num_records;
+       record = kvp_file_info[pool].records;
+
        for (i = 0; i < num_records; i++) {
                if (memcmp(key, record[i].key, key_size))
                        continue;
@@ -324,6 +394,31 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
        return 1;
 }
 
+static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
+                               __u8 *value, int value_size)
+{
+       struct kvp_record *record;
+
+       /*
+        * First update our in-memory database.
+        */
+       kvp_update_mem_state(pool);
+       record = kvp_file_info[pool].records;
+
+       if (index >= kvp_file_info[pool].num_records) {
+               /*
+                * This is an invalid index; terminate enumeration;
+                * - a NULL value will do the trick.
+                */
+               strcpy(value, "");
+               return;
+       }
+
+       memcpy(key, record[index].key, key_size);
+       memcpy(value, record[index].value, value_size);
+}
+
+
 void kvp_get_os_info(void)
 {
        FILE    *file;
@@ -678,6 +773,21 @@ int main(void)
                if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)
                        goto kvp_done;
 
+               /*
+                * If the pool is KVP_POOL_AUTO, dynamically generate
+                * both the key and the value; if not read from the
+                * appropriate pool.
+                */
+               if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) {
+                       kvp_pool_enumerate(hv_msg->kvp_hdr.pool,
+                                       hv_msg->body.kvp_enum_data.index,
+                                       hv_msg->body.kvp_enum_data.data.key,
+                                       HV_KVP_EXCHANGE_MAX_KEY_SIZE,
+                                       hv_msg->body.kvp_enum_data.data.value,
+                                       HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+                       goto kvp_done;
+               }
+
                hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
                key_name = (char *)hv_msg->body.kvp_enum_data.data.key;
                key_value = (char *)hv_msg->body.kvp_enum_data.data.value;