コード例 #1
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_set_clientid(struct RIACK_CLIENT *client, RIACK_STRING clientid)
{
	int result;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	RpbSetClientIdReq req;
	size_t packed_size;
	uint8_t *request_buffer;

	rpb_set_client_id_req__init(&req);
	req.client_id.len = clientid.len;
    req.client_id.data = (uint8_t*)clientid.value;

	packed_size = rpb_set_client_id_req__get_packed_size(&req);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	result = RIACK_ERROR_COMMUNICATION;
	if (request_buffer) {
		rpb_set_client_id_req__pack(&req, request_buffer);
		msg_req.msg_len = packed_size;
		msg_req.msg_code = mc_RpbSetClientIdReq;
		msg_req.msg = request_buffer;
		if ((riack_send_message(client, &msg_req) > 0)&&
			(riack_receive_message(client, &msg_resp) > 0)) {
			if (msg_resp->msg_code == mc_RpbSetClientIdResp) {
				result = RIACK_SUCCESS;
			} else {
				riack_got_error_response(client, msg_resp);
				result = RIACK_ERROR_RESPONSE;
			}
			riack_message_free(client, &msg_resp);
		}
		RFREE(client, request_buffer);
	}
	return result;
}
コード例 #2
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_get_clientid(struct RIACK_CLIENT *client, RIACK_STRING *clientid)
{
	int result;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	RpbGetClientIdResp *id_resp;
	ProtobufCAllocator pb_allocator;

	pb_allocator = riack_pb_allocator(&client->allocator);
	msg_req.msg = 0;
	msg_req.msg_len = 0;
	msg_req.msg_code = mc_RpbGetClientIdReq;
	result = RIACK_ERROR_COMMUNICATION;
	if ((riack_send_message(client, &msg_req) > 0) &&
		(riack_receive_message(client, &msg_resp) > 0)) {
		if (msg_resp->msg_code == mc_RpbGetClientIdResp) {
			id_resp = rpb_get_client_id_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
			if (id_resp) {
				RMALLOCCOPY(client, clientid->value, clientid->len, id_resp->client_id.data, id_resp->client_id.len);
				rpb_get_client_id_resp__free_unpacked(id_resp, &pb_allocator);
				result = RIACK_SUCCESS;
			} else {
				result = RIACK_FAILED_PB_UNPACK;
			}
		} else {
			riack_got_error_response(client, msg_resp);
			result = RIACK_ERROR_RESPONSE;
		}
		riack_message_free(client, &msg_resp);
	}
	return result;
}
コード例 #3
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_get(struct RIACK_CLIENT *client,
			 RIACK_STRING bucket,
			 RIACK_STRING key,
			 struct RIACK_GET_PROPERTIES* props,
			 struct RIACK_GET_OBJECT* result_object)
{
	int result;
	size_t packed_size;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	ProtobufCAllocator pb_allocator;
	RpbGetReq get_req;
	RpbGetResp *get_resp;
	uint8_t *request_buffer;

	if (!bucket.value || !key.value || key.len == 0 || bucket.len == 0 || !client) {
		return RIACK_ERROR_INVALID_INPUT;
	}

	pb_allocator = riack_pb_allocator(&client->allocator);

	result = RIACK_ERROR_COMMUNICATION;
	rpb_get_req__init(&get_req);
	get_req.key.data = (uint8_t *) key.value;
	get_req.key.len = key.len;
	get_req.bucket.data = (uint8_t *) bucket.value;
	get_req.bucket.len = bucket.len;
	riack_set_get_properties(client, props, &get_req);

	packed_size = rpb_get_req__get_packed_size(&get_req);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_get_req__pack(&get_req, request_buffer);
		msg_req.msg_code = mc_RpbGetReq;
		msg_req.msg_len = packed_size;
		msg_req.msg = request_buffer;
		if ((riack_send_message(client, &msg_req) > 0)&&
			(riack_receive_message(client, &msg_resp) > 0))
		{
			if (msg_resp->msg_code == mc_RpbGetResp) {
				get_resp = rpb_get_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
				if (get_resp) {
					riak_set_object_response_values_get(client, result_object, get_resp);
					rpb_get_resp__free_unpacked(get_resp, &pb_allocator);
					result = RIACK_SUCCESS;
				} else {
					result = RIACK_FAILED_PB_UNPACK;
				}
			} else {
				riack_got_error_response(client, msg_resp);
				result = RIACK_ERROR_RESPONSE;
			}
			riack_message_free(client, &msg_resp);
		}
		RFREE(client, request_buffer);
	}
	return result;
}
コード例 #4
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_put(struct RIACK_CLIENT *client,
			struct RIACK_OBJECT object,
			struct RIACK_OBJECT* preturned_object,
			struct RIACK_PUT_PROPERTIES* properties)
{
	int result;
	size_t packed_size;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	ProtobufCAllocator pb_allocator;
	RpbPutReq put_req;
	RpbPutResp *put_resp;
	uint8_t *request_buffer;

    if (!client || !object.bucket.value) {
		return RIACK_ERROR_INVALID_INPUT;
	}

	pb_allocator = riack_pb_allocator(&client->allocator);
	result = RIACK_ERROR_COMMUNICATION;
	rpb_put_req__init(&put_req);
	riack_copy_object_to_rpbputreq(client, &object, &put_req);
    riack_set_object_properties(properties, &put_req);

	packed_size = rpb_put_req__get_packed_size(&put_req);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_put_req__pack(&put_req, request_buffer);
		msg_req.msg_code = mc_RpbPutReq;
		msg_req.msg_len = packed_size;
		msg_req.msg = request_buffer;
		if ((riack_send_message(client, &msg_req) > 0)&&
			(riack_receive_message(client, &msg_resp) > 0))
		{
			if (msg_resp->msg_code == mc_RpbPutResp) {
				result = RIACK_SUCCESS;
				if (preturned_object) {
					put_resp = rpb_put_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
					if (put_resp) {
						riak_set_object_response_values(client, preturned_object, put_resp);
						rpb_put_resp__free_unpacked(put_resp, &pb_allocator);
					} else {
						result = RIACK_FAILED_PB_UNPACK;
					}
				}
			} else {
				riack_got_error_response(client, msg_resp);
				result = RIACK_ERROR_RESPONSE;
			}
			riack_message_free(client, &msg_resp);
		}
		RFREE(client, request_buffer);
	}
    riack_free_copied_rpb_put_req(client, &put_req);
	return result;
}
コード例 #5
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_get_bucket_props(struct RIACK_CLIENT *client, RIACK_STRING bucket, uint32_t *n_val, uint8_t *allow_mult)
{
	int result;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	ProtobufCAllocator pb_allocator;
	size_t packed_size;
	uint8_t *request_buffer;
	RpbGetBucketResp *response;
	RpbGetBucketReq get_request = RPB_GET_BUCKET_REQ__INIT;

	if (!client || !bucket.value || bucket.len == 0) {
		return RIACK_ERROR_INVALID_INPUT;
	}
	pb_allocator = riack_pb_allocator(&client->allocator);
	result = RIACK_ERROR_COMMUNICATION;
	get_request.bucket.len = bucket.len;
	get_request.bucket.data = (uint8_t*)bucket.value;
	packed_size = rpb_get_bucket_req__get_packed_size(&get_request);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_get_bucket_req__pack(&get_request, request_buffer);
		msg_req.msg_code = mc_RpbGetBucketReq;
		msg_req.msg_len = packed_size;
		msg_req.msg = request_buffer;
		if ((riack_send_message(client, &msg_req) > 0)&&
			(riack_receive_message(client, &msg_resp) > 0))
		{
			if (msg_resp->msg_code == mc_RpbGetBucketResp) {
				response = rpb_get_bucket_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
				if (response) {
					if (response->props->has_allow_mult) {
						*allow_mult = response->props->allow_mult ? 1 : 0;
					}
					if (response->props->has_n_val) {
						*n_val = response->props->n_val;
					}
					rpb_get_bucket_resp__free_unpacked(response, &pb_allocator);
					result = RIACK_SUCCESS;
				} else {
					result = RIACK_FAILED_PB_UNPACK;
				}
			} else {
				riack_got_error_response(client, msg_resp);
				result = RIACK_ERROR_RESPONSE;
			}
			riack_message_free(client, &msg_resp);
		}

		RFREE(client, request_buffer);
	}
	return result;
}
コード例 #6
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_list_buckets(struct RIACK_CLIENT *client, RIACK_STRING_LIST* bucket_list)
{
	int result;
	struct RIACK_PB_MSG msg_req;
	struct RIACK_PB_MSG *msg_resp;
	RpbListBucketsResp *list_resp;
	ProtobufCAllocator pb_allocator;
	size_t i;

	if (!client || !bucket_list) {
		return RIACK_ERROR_INVALID_INPUT;
	}

	pb_allocator = riack_pb_allocator(&client->allocator);
	result = RIACK_ERROR_COMMUNICATION;

	msg_req.msg_code = mc_RpbListBucketsReq;
	msg_req.msg_len = 0;
	bucket_list->string_count = 0;
	if ((riack_send_message(client, &msg_req) > 0)&&
		(riack_receive_message(client, &msg_resp) > 0)) {
		if (msg_resp->msg_code == mc_RpbListBucketsResp) {
			list_resp = rpb_list_buckets_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
			if (list_resp) {
				bucket_list->string_count = list_resp->n_buckets;
				bucket_list->strings = (RIACK_STRING*)RMALLOC(client, sizeof(RIACK_STRING) * list_resp->n_buckets);
				for (i=0; i<list_resp->n_buckets; ++i) {
					RMALLOCCOPY(client,
								bucket_list->strings[i].value,
								bucket_list->strings[i].len,
								list_resp->buckets[i].data,
								list_resp->buckets[i].len);
				}
				rpb_list_buckets_resp__free_unpacked(list_resp, &pb_allocator);
				result = RIACK_SUCCESS;
			} else {
				result = RIACK_FAILED_PB_UNPACK;
			}
		} else {
			riack_got_error_response(client, msg_resp);
			result = RIACK_ERROR_RESPONSE;
		}
		riack_message_free(client, &msg_resp);
	}
	return result;
}
コード例 #7
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_delete(struct RIACK_CLIENT *client, RIACK_STRING bucket, RIACK_STRING key, struct RIACK_DEL_PROPERTIES *props)
{
	int result;
	size_t packed_size;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	RpbDelReq del_req;
	uint8_t *request_buffer;

	if (!client || !bucket.value || !key.value || key.len == 0 || bucket.len == 0) {
		return RIACK_ERROR_INVALID_INPUT;
	}

	result = RIACK_ERROR_COMMUNICATION;
	rpb_del_req__init(&del_req);

	del_req.bucket.len = bucket.len;
	del_req.bucket.data = (uint8_t *) bucket.value;
	del_req.key.len = key.len;
	del_req.key.data = (uint8_t *) key.value;
	riack_set_del_properties(client, props, &del_req);

	packed_size = rpb_del_req__get_packed_size(&del_req);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_del_req__pack(&del_req, request_buffer);
		msg_req.msg_code = mc_RpbDelReq;
		msg_req.msg_len = packed_size;
		msg_req.msg = request_buffer;
		if ((riack_send_message(client, &msg_req) > 0)&&
			(riack_receive_message(client, &msg_resp) > 0))
		{
			if (msg_resp->msg_code == mc_RpbDelResp) {
				result = RIACK_SUCCESS;
			} else {
				riack_got_error_response(client, msg_resp);
				result = RIACK_ERROR_RESPONSE;
			}
			riack_message_free(client, &msg_resp);
		}
		RFREE(client, request_buffer);
	}

    RFREE(client, del_req.vclock.data);
    return result;
}
コード例 #8
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_2i_query(struct RIACK_CLIENT *client, RpbIndexReq* request, RIACK_STRING_LIST* result_keys)
{
	struct RIACK_PB_MSG msg_req, *msg_resp;
	ProtobufCAllocator pb_allocator;
	RpbIndexResp *index_resp;
	int result;
	size_t packed_size, keys, i;
	uint8_t *request_buffer;
	result = RIACK_ERROR_COMMUNICATION;
	pb_allocator = riack_pb_allocator(&client->allocator);
	packed_size = rpb_index_req__get_packed_size(request);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_index_req__pack(request, request_buffer);
		msg_req.msg = request_buffer;
		msg_req.msg_code = mc_RpbIndexReq;
		msg_req.msg_len = packed_size;
		if ((riack_send_message(client, &msg_req) > 0) &&
			(riack_receive_message(client, &msg_resp) > 0)) {
			if (msg_resp->msg_code == mc_RpbIndexResp) {
				index_resp = rpb_index_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
				if (index_resp) {
					keys = index_resp->n_keys;
					result_keys->string_count = keys;
					result_keys->strings = RMALLOC(client, sizeof(RIACK_STRING) * keys);
					for (i=0; i<keys; ++i) {
						RMALLOCCOPY(client, result_keys->strings[i].value, result_keys->strings[i].len,
								index_resp->keys[i].data, index_resp->keys[i].len);
					}
					rpb_index_resp__free_unpacked(index_resp, &pb_allocator);
					result = RIACK_SUCCESS;
				} else {
					result = RIACK_FAILED_PB_UNPACK;
				}
			} else {
				riack_got_error_response(client, msg_resp);
				result = RIACK_ERROR_RESPONSE;
			}
			riack_message_free(client, &msg_resp);
		}
		RFREE(client, request_buffer);
	}
	return result;
}
コード例 #9
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_set_bucket_props(struct RIACK_CLIENT *client, RIACK_STRING bucket, uint32_t n_val, uint8_t allow_mult)
{
	int result;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	size_t packed_size;
	uint8_t *request_buffer;
	RpbSetBucketReq set_request = RPB_SET_BUCKET_REQ__INIT;
	RpbBucketProps bck_props = RPB_BUCKET_PROPS__INIT;

	if (!client || !bucket.value || bucket.len == 0) {
		return RIACK_ERROR_INVALID_INPUT;
	}

	result = RIACK_ERROR_COMMUNICATION;
	bck_props.has_allow_mult = 1;
	bck_props.allow_mult = allow_mult;
	bck_props.has_n_val = 1;
	bck_props.n_val = n_val;
	set_request.props = &bck_props;
	set_request.bucket.len = bucket.len;
	set_request.bucket.data = (uint8_t*)bucket.value;
	packed_size = rpb_set_bucket_req__get_packed_size(&set_request);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_set_bucket_req__pack(&set_request, request_buffer);
		msg_req.msg_code = mc_RpbSetBucketReq;
		msg_req.msg_len = packed_size;
		msg_req.msg = request_buffer;
		if ((riack_send_message(client, &msg_req) > 0)&&
			(riack_receive_message(client, &msg_resp) > 0))
		{
			if (msg_resp->msg_code == mc_RpbSetBucketResp) {
				result = RIACK_SUCCESS;
			} else {
				riack_got_error_response(client, msg_resp);
				result = RIACK_ERROR_RESPONSE;
			}
			riack_message_free(client, &msg_resp);
		}
		RFREE(client, request_buffer);
	}
	return result;
}
コード例 #10
0
ファイル: riack.c プロジェクト: fumpierrez/riack
int riack_server_info(struct RIACK_CLIENT *client, RIACK_STRING *node, RIACK_STRING* version)
{
	int result;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	RpbGetServerInfoResp *response;
	ProtobufCAllocator pb_allocator;
	msg_req.msg_code = mc_RpbGetServerInfoReq;
	msg_req.msg_len = 0;

	pb_allocator = riack_pb_allocator(&client->allocator);
	result = RIACK_ERROR_COMMUNICATION;
	if ((riack_send_message(client, &msg_req) > 0) &&
		(riack_receive_message(client, &msg_resp) > 0)) {
		if (msg_resp->msg_code == mc_RpbGetServerInfoResp) {
			response = rpb_get_server_info_resp__unpack(&pb_allocator, msg_req.msg_len, msg_req.msg);
			if (response->has_node) {
				RMALLOCCOPY(client, node->value, node->len, response->node.data, response->node.len);
			} else {
				node->len = 0;
				node->value = 0;
			}
			if (response->has_server_version) {
				RMALLOCCOPY(client, version->value, version->len,
						response->server_version.data, response->server_version.len);
			} else {
				version->len = 0;
				version->value = 0;
			}
			// Copy responses
			rpb_get_server_info_resp__free_unpacked(response, &pb_allocator);
			result = RIACK_SUCCESS;
		} else {
			riack_got_error_response(client, msg_resp);
			result = RIACK_ERROR_RESPONSE;
		}
		riack_message_free(client, &msg_resp);
	}
	return result;
}
コード例 #11
0
ファイル: riack_commands.c プロジェクト: ecks/riack
int riack_perform_commmand(riack_client *client, const struct pb_command* cmd, const struct rpb_base_req* req,
        cmd_response_cb cb, void** cb_arg)
{
    riack_pb_msg msg_req, *msg_resp;
    ProtobufCAllocator pb_allocator;
    void* resp;
    uint8_t *request_buffer;
    size_t packed_size;
    int retval;
    if (!client) {
        return RIACK_ERROR_INVALID_INPUT;
    }
    retval = RIACK_ERROR_COMMUNICATION;
    pb_allocator = riack_pb_allocator(&client->allocator);
    request_buffer = 0;
    packed_size = 0;

    // Not all commands have data
    if (cmd->packed_size_fn != NULL && cmd->pack_fn != NULL) {
        packed_size = cmd->packed_size_fn(req);
        if (packed_size > 0) {
            request_buffer = (uint8_t *) RMALLOC(client, packed_size);
        }
    }
    if (request_buffer != NULL || packed_size == 0) {
        if (packed_size > 0 && cmd->pack_fn != NULL) {
            // Pack if we have data
            cmd->pack_fn(req, request_buffer);
        }
        msg_req.msg_code = cmd->req_msg_code;
        msg_req.msg_len = (uint32_t) packed_size;
        msg_req.msg = request_buffer;
        if (riack_send_message(client, &msg_req) > 0) {
            int done = 0;
            while (!done && riack_receive_message(client, &msg_resp) > 0) {
                done = 1;
                if (msg_resp->msg_code == cmd->resp_msg_code) {
                    if (cmd->unpack_fn != NULL && cb != NULL) {
                        resp = cmd->unpack_fn(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
                        if (resp) {
                            retval = RIACK_SUCCESS;
                            if (cb(client, resp, cb_arg) == RIACK_CMD_CONTINUE) {
                                done = 0;
                            }
                            cmd->free_unpacked_fn(resp, &pb_allocator);
                        } else {
                            retval = RIACK_FAILED_PB_UNPACK;
                        }
                    } else {
                        retval = RIACK_SUCCESS;
                    }
                } else {
                    riack_got_error_response(client, msg_resp);
                    retval = RIACK_ERROR_RESPONSE;
                }
                riack_message_free(client, &msg_resp);
            }
        }
        if (request_buffer != 0) {
            RFREE(client, request_buffer);
        }
    }
    return retval;
}
コード例 #12
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_map_reduce_stream(struct RIACK_CLIENT *client,
										 size_t data_len,
										 uint8_t* data,
										 enum RIACK_MAPRED_CONTENT_TYPE content_type,
                                         void(*callback)(struct RIACK_CLIENT*, void*, struct RIACK_MAPRED_RESPONSE*),
										 void* callback_arg)
{
    struct RIACK_MAPRED_RESPONSE mapred_result_current;
	int result;
	size_t packed_size;
	struct RIACK_PB_MSG msg_req, *msg_resp;
	RpbMapRedReq mr_req;
	RpbMapRedResp *mr_resp;
	ProtobufCAllocator pb_allocator;
	uint8_t *request_buffer;
	char* content_type_sz;
	uint8_t last_message;

	memset(&mapred_result_current, 0, sizeof(mapred_result_current));

	if (!client || !data || data_len == 0 || !callback) {
		return RIACK_ERROR_INVALID_INPUT;
	}

	pb_allocator = riack_pb_allocator(&client->allocator);
	result = RIACK_ERROR_COMMUNICATION;

	rpb_map_red_req__init(&mr_req);
	if (content_type == APPLICATION_JSON) {
		content_type_sz = "application/json";
	} else if (content_type == APPLICATION_ERLANG_TERM) {
		content_type_sz = "application/x-erlang-binary";
	} else {
		return RIACK_ERROR_INVALID_INPUT;
	}
	mr_req.content_type.len = strlen(content_type_sz);
    mr_req.content_type.data = (uint8_t*)content_type_sz;
	mr_req.request.len = data_len;
	mr_req.request.data = data;
	packed_size = rpb_map_red_req__get_packed_size(&mr_req);
	request_buffer = (uint8_t*)RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_map_red_req__pack(&mr_req, request_buffer);
		msg_req.msg_code = mc_RpbMapRedReq;
		msg_req.msg_len = packed_size;
		msg_req.msg = request_buffer;
		if (riack_send_message(client, &msg_req) > 0) {
			last_message = 0;
			while ((last_message == 0) && (riack_receive_message(client, &msg_resp) > 0)) {
				if (msg_resp->msg_code == mc_RpbMapRedResp) {
					mr_resp = rpb_map_red_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
					if (mr_resp) {
						riack_link_strmapred_with_rpbmapred(client, mr_resp, &mapred_result_current);
						callback(client, callback_arg, &mapred_result_current);
						if (mr_resp->has_done && mr_resp->done) {
							result = RIACK_SUCCESS;
							last_message = 1;
						}
						rpb_map_red_resp__free_unpacked(mr_resp, &pb_allocator);
					} else {
						result = RIACK_FAILED_PB_UNPACK;
					}
				} else {
					riack_got_error_response(client, msg_resp);
					result = RIACK_ERROR_RESPONSE;
					last_message = 1;
				}
				riack_message_free(client, &msg_resp);
			}
		}
		RFREE(client, request_buffer);
	}

	return result;
}
コード例 #13
0
ファイル: riack_kv.c プロジェクト: iehoyeba/riack
int riack_stream_keys(struct RIACK_CLIENT *client, RIACK_STRING bucket,
					  void(*callback)(struct RIACK_CLIENT*, void*, RIACK_STRING), void *callback_arg)
{
	int result;
	struct RIACK_PB_MSG msg_req;
	struct RIACK_PB_MSG *msg_resp;
	RpbListKeysReq list_req;
	RpbListKeysResp *list_resp;
	RIACK_STRING current_string;
	ProtobufCAllocator pb_allocator;
	size_t packed_size, num_keys, i;
	uint8_t *request_buffer, recvdone;

	if (!client || !callback || bucket.len == 0) {
		return RIACK_ERROR_INVALID_INPUT;
	}
	pb_allocator = riack_pb_allocator(&client->allocator);
	result = RIACK_ERROR_COMMUNICATION;
	rpb_list_keys_req__init(&list_req);
	list_req.bucket.len = bucket.len;
    list_req.bucket.data = (uint8_t*)bucket.value;
	packed_size = rpb_list_keys_req__get_packed_size(&list_req);
	request_buffer = RMALLOC(client, packed_size);
	if (request_buffer) {
		rpb_list_keys_req__pack(&list_req, request_buffer);
		msg_req.msg_code = mc_RpbListKeysReq;
		msg_req.msg_len = packed_size;
		msg_req.msg = request_buffer;
		if (riack_send_message(client, &msg_req) > 0)
		{
			recvdone = 0;
			while (!recvdone) {
				if (riack_receive_message(client, &msg_resp) > 0) {
					if (msg_resp->msg_code == mc_RpbListKeysResp) {
						list_resp = rpb_list_keys_resp__unpack(&pb_allocator, msg_resp->msg_len, msg_resp->msg);
						if (list_resp) {
							if (list_resp->has_done && list_resp->done) {
								recvdone = 1;
								result = RIACK_SUCCESS;
							}
							num_keys = list_resp->n_keys;
							for (i=0; i<num_keys; ++i) {
								current_string.value = (char*)list_resp->keys[i].data;
								current_string.len   = list_resp->keys[i].len;
								callback(client, callback_arg, current_string);
							}
							rpb_list_keys_resp__free_unpacked(list_resp, &pb_allocator);
						} else {
							result = RIACK_FAILED_PB_UNPACK;
						}
					} else {
						riack_got_error_response(client, msg_resp);
						recvdone = 1;
					}
					riack_message_free(client, &msg_resp);
				}
			}
		}
		RFREE(client, request_buffer);
	}
	return result;
}