#include "internal.h"
#include <lcbio/lcbio.h>
#include "bucketconfig/clconfig.h"
#include "hostlist.h"
static std::string&
ensure_scratch(lcb_t instance)
{
if (!instance->scratch) {
instance->scratch = new std::string;
}
instance->scratch->clear();
return *instance->scratch;
}
static const char *
mk_scratch_host(lcb_t instance, const lcb_host_t *host)
{
std::string& s = ensure_scratch(instance);
s.append(host->host);
s.append(":");
s.append(host->port);
return s.c_str();
}
static const char *
return_badhost(lcb_GETNODETYPE type)
{
if (type & LCB_NODE_NEVERNULL) {
return LCB_GETNODE_UNAVAILABLE;
} else {
return NULL;
}
}
LIBCOUCHBASE_API
const char *
lcb_get_node(lcb_t instance, lcb_GETNODETYPE type, unsigned ix)
{
lcbvb_SVCMODE mode;
lcbvb_CONFIG *vbc = LCBT_VBCONFIG(instance);
if (LCBT_SETTING(instance, sslopts) & LCB_SSL_ENABLED) {
mode = LCBVB_SVCMODE_SSL;
} else {
mode = LCBVB_SVCMODE_PLAIN;
}
if (type & LCB_NODE_HTCONFIG) {
if (type & LCB_NODE_CONNECTED) {
const lcb_host_t *host = lcb_confmon_get_rest_host(instance->confmon);
if (host) {
return mk_scratch_host(instance, host);
} else {
return return_badhost(type);
}
} else {
const char *hp = NULL;
if (instance->type == LCB_TYPE_BUCKET) {
if (vbc) {
ix %= LCBVB_NSERVERS(vbc);
hp = lcbvb_get_hostport(vbc, ix, LCBVB_SVCTYPE_MGMT, mode);
} else if ((type & LCB_NODE_NEVERNULL) == 0) {
return NULL;
}
}
if (hp == NULL && instance->ht_nodes && !instance->ht_nodes->empty()) {
ix %= instance->ht_nodes->size();
instance->ht_nodes->ensure_strlist();
hp = instance->ht_nodes->hoststrs[ix];
}
if (!hp) {
return return_badhost(type);
}
return ensure_scratch(instance).append(hp).c_str();
}
} else if (type & (LCB_NODE_DATA|LCB_NODE_VIEWS)) {
const mc_SERVER *server;
ix %= LCBT_NSERVERS(instance);
server = LCBT_GET_SERVER(instance, ix);
if ((type & LCB_NODE_CONNECTED) && server->connctx == NULL) {
return return_badhost(type);
}
if (server->curhost == NULL) {
return return_badhost(type);
}
if (type & LCB_NODE_DATA) {
return mk_scratch_host(instance, server->curhost);
} else {
return lcbvb_get_hostport(vbc, ix, LCBVB_SVCTYPE_VIEWS, mode);
}
} else {
return NULL;
}
}
LIBCOUCHBASE_API const char * lcb_get_host(lcb_t instance) {
char *colon;
const char *rv = lcb_get_node(instance,
static_cast<lcb_GETNODETYPE>(LCB_NODE_HTCONFIG|LCB_NODE_NEVERNULL), 0);
if (rv != NULL && (colon = (char *)strstr(rv, ":")) != NULL) {
if (instance->scratch && rv == instance->scratch->c_str()) {
size_t colon_pos = instance->scratch->find(':');
if (colon_pos != std::string::npos) {
instance->scratch->erase(colon_pos);
}
}
}
return rv;
}
LIBCOUCHBASE_API const char * lcb_get_port(lcb_t instance) {
const char *rv = lcb_get_node(instance,
static_cast<lcb_GETNODETYPE>(LCB_NODE_HTCONFIG|LCB_NODE_NEVERNULL), 0);
if (rv && (rv = strstr(rv, ":"))) {
rv++;
}
return rv;
}
LIBCOUCHBASE_API
lcb_int32_t lcb_get_num_replicas(lcb_t instance)
{
if (LCBT_VBCONFIG(instance)) {
return LCBT_NREPLICAS(instance);
} else {
return -1;
}
}
LIBCOUCHBASE_API
lcb_int32_t lcb_get_num_nodes(lcb_t instance)
{
if (LCBT_VBCONFIG(instance)) {
return LCBT_NSERVERS(instance);
} else {
return -1;
}
}
LIBCOUCHBASE_API
const char *const *lcb_get_server_list(lcb_t instance)
{
return hostlist_strents(instance->ht_nodes);
}
LIBCOUCHBASE_API
const char *
lcb_get_keynode(lcb_t instance, const void *key, size_t nkey)
{
lcbvb_CONFIG *vbc = LCBT_VBCONFIG(instance);
int srvix, vbid;
if (!vbc) {
return NULL;
}
lcbvb_map_key(vbc, key, nkey, &vbid, &srvix);
if (srvix < 0) {
return NULL;
}
return lcbvb_get_hostname(vbc, srvix);
}