Spdk/module/bdev/longhorn/bdev_longhorn_remote.c
Keith Lucas 70f0921810 Initial changes.
Signed-off-by: Keith Lucas <keith.lucas@suse.com>
2022-02-08 15:51:30 -05:00

167 lines
3.5 KiB
C

#include "spdk/stdinc.h"
#include "spdk/env.h"
#include "spdk/jsonrpc.h"
#include "spdk/thread.h"
#include "bdev_longhorn_remote.h"
struct tcp_client_handler_entry {
char *command;
int32_t id;
void *arg;
json_remote_response_handler_fn fn;
TAILQ_ENTRY(tcp_client_handler_entry) entries;
};
struct tcp_client_entry {
const char *addr;
struct spdk_jsonrpc_client *client;
TAILQ_HEAD(, tcp_client_handler_entry) handlers;
TAILQ_ENTRY(tcp_client_entry) entries;
};
static TAILQ_HEAD(, tcp_client_entry) tcp_clients = TAILQ_HEAD_INITIALIZER(tcp_clients);
static struct spdk_poller *poller = NULL;
static void handler_free(struct tcp_client_handler_entry *handler) {
if (handler) {
free(handler->command);
free(handler);
}
}
static void remote_client_handle(struct tcp_client_entry *entry)
{
struct spdk_jsonrpc_client_response *response = NULL;
int32_t id = 0;
struct tcp_client_handler_entry *handler = NULL;
struct tcp_client_handler_entry *next = NULL;
response = spdk_jsonrpc_client_get_response(entry->client);
if (spdk_json_number_to_int32(response->id, &id) != 0) {
printf("Unable to decode TCP client message.\n");
spdk_jsonrpc_client_free_response(response);
return;
}
handler = TAILQ_FIRST(&entry->handlers);
while (handler != NULL) {
next = TAILQ_NEXT(handler, entries);
if (handler->id == id) {
(*(handler->fn))(entry->addr, handler->command, id,
response->result, response->error,
handler->arg);
TAILQ_REMOVE(&entry->handlers, handler, entries);
handler_free(handler);
break;
}
handler = next;
}
spdk_jsonrpc_client_free_response(response);
}
static int remote_client_poll(void *arg)
{
struct tcp_client_entry *entry = NULL;
struct tcp_client_entry *next = NULL;
int error = 0;
entry = TAILQ_FIRST(&tcp_clients);
while (entry != NULL) {
next = TAILQ_NEXT(entry, entries);
error = spdk_jsonrpc_client_poll(entry->client, 0);
if (error > 0) {
remote_client_handle(entry);
} else if (error == -EIO) {
}
entry = next;
}
return SPDK_POLLER_BUSY;
}
static struct tcp_client_entry *
json_client_lookup(const char *addr) {
struct tcp_client_entry *entry = NULL;
TAILQ_FOREACH(entry, &tcp_clients, entries) {
if (strcmp(addr, entry->addr) == 0) {
return entry;
}
}
return NULL;
}
int json_remote_client(const char *addr)
{
struct spdk_jsonrpc_client *client = NULL;
struct tcp_client_entry *entry = json_client_lookup(addr);
if (entry == NULL) {
client = spdk_jsonrpc_client_connect(addr, AF_INET);
if (client != NULL) {
entry = calloc(1, sizeof(struct tcp_client_entry));
entry->addr = strdup(addr);
entry->client = client;
TAILQ_INIT(&entry->handlers);
TAILQ_INSERT_TAIL(&tcp_clients, entry, entries);
if (poller == NULL) {
poller = SPDK_POLLER_REGISTER(remote_client_poll,
NULL, 4000);
}
}
}
return 0;
}
int json_remote_client_send_command(const char *addr,
const char *command,
int32_t id,
struct spdk_jsonrpc_client_request *request,
json_remote_response_handler_fn fn,
void *arg) {
struct tcp_client_entry *entry = json_client_lookup(addr);
struct tcp_client_handler_entry *handler;
if (entry) {
handler = calloc(1, sizeof(struct tcp_client_handler_entry));
handler->command = strdup(command);
handler->id = id;
handler->fn = fn;
handler->arg = arg;
TAILQ_INSERT_TAIL(&entry->handlers, handler, entries);
spdk_jsonrpc_client_send_request(entry->client, request);
}
return 0;
}