1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * Copyright 2014-2017 Couchbase, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <lcbio/lcbio.h>
19 #include <lcbio/timer-ng.h>
20 #include <lcbio/timer-cxx.h>
21 #include <libcouchbase/vbucket.h>
22 #include "clconfig.h"
23
24 #define LOGARGS(mcr, lvlbase) mcr->parent->settings, "bc_static", LCB_LOG_##lvlbase, __FILE__, __LINE__
25 #define LOGFMT "(STATIC=%p)> "
26 #define LOGID(mcr) (void *)mcr
27
28 using namespace lcb::clconfig;
29 using lcb::Hostlist;
30
31
32 // Base class for providers which only generate a config once, statically.
33 class StaticProvider : public Provider {
34 public:
StaticProvider(Confmon * parent_,Method m)35 StaticProvider(Confmon *parent_, Method m)
36 : Provider(parent_, m), async(parent_->iot, this), config(NULL) {
37 }
38
~StaticProvider()39 virtual ~StaticProvider() {
40 if (config) {
41 config->decref();
42 }
43 async.release();
44 }
45
get_cached()46 ConfigInfo *get_cached() {
47 return config;
48 }
49
refresh()50 lcb_error_t refresh() {
51 async.signal();
52 return LCB_SUCCESS;
53 }
54
configure_nodes(const Hostlist & hl)55 void configure_nodes(const Hostlist& hl) {
56 if (hl.empty()) {
57 lcb_log(LOGARGS(this, FATAL), "No nodes provided");
58 return;
59 }
60
61 lcbvb_CONFIG *vbc = gen_config(hl);
62 if (vbc != NULL) {
63 if (config != NULL) {
64 config->decref();
65 config = NULL;
66 }
67 config = ConfigInfo::create(vbc, type);
68 }
69 }
70
71 virtual lcbvb_CONFIG* gen_config(const Hostlist& hl) = 0;
72
73 private:
async_update()74 void async_update() {
75 if (config != NULL) {
76 parent->provider_got_config(this, config);
77 }
78 }
79
80 lcb::io::Timer<StaticProvider, &StaticProvider::async_update> async;
81 ConfigInfo *config;
82 };
83
84
85 /* Raw memcached provider */
86
87 struct McRawProvider : public StaticProvider {
McRawProviderMcRawProvider88 McRawProvider(Confmon* parent_) : StaticProvider(parent_, CLCONFIG_MCRAW) {
89 }
90 lcbvb_CONFIG *gen_config(const lcb::Hostlist& l);
91 };
92
gen_config(const lcb::Hostlist & hl)93 lcbvb_CONFIG * McRawProvider::gen_config(const lcb::Hostlist& hl)
94 {
95 std::vector<lcbvb_SERVER> servers;
96 servers.reserve(hl.size());
97
98 for (size_t ii = 0; ii < hl.size(); ii++) {
99 const lcb_host_t& curhost = hl[ii];
100 servers.resize(servers.size() + 1);
101
102 lcbvb_SERVER& srv = servers.back();
103 memset(&srv, 0, sizeof srv);
104
105 /* just set the memcached port and hostname */
106 srv.hostname = (char *)curhost.host;
107 srv.svc.data = std::atoi(curhost.port);
108 if (parent->settings->sslopts) {
109 srv.svc_ssl.data = srv.svc.data;
110 }
111 }
112
113 lcbvb_CONFIG *newconfig = lcbvb_create();
114 lcbvb_genconfig_ex(newconfig, "NOBUCKET", "deadbeef", &servers[0], servers.size(), 0, 2);
115 lcbvb_make_ketama(newconfig);
116 newconfig->revid = -1;
117 return newconfig;
118 }
119
new_mcraw_provider(Confmon * parent)120 Provider* lcb::clconfig::new_mcraw_provider(Confmon* parent) {
121 return new McRawProvider(parent);
122 }
123
124 struct ClusterAdminProvider : public StaticProvider {
ClusterAdminProviderClusterAdminProvider125 ClusterAdminProvider(Confmon *parent_) : StaticProvider(parent_, CLCONFIG_CLADMIN) {
126 }
127
gen_configClusterAdminProvider128 lcbvb_CONFIG *gen_config(const lcb::Hostlist& hl) {
129 std::vector<lcbvb_SERVER> servers;
130 servers.reserve(hl.size());
131 for (size_t ii = 0; ii < hl.size(); ++ii) {
132 servers.resize(servers.size() + 1);
133 lcbvb_SERVER& srv = servers[ii];
134 const lcb_host_t& curhost = hl[ii];
135 srv.hostname = const_cast<char*>(curhost.host);
136 if (parent->settings->sslopts) {
137 srv.svc_ssl.mgmt = std::atoi(curhost.port);
138 } else {
139 srv.svc.mgmt = std::atoi(curhost.port);
140 }
141 }
142 lcbvb_CONFIG *vbc = lcbvb_create();
143 lcbvb_genconfig_ex(vbc, "NOBUCKET", "deadbeef", &servers[0], servers.size(), 0, 0);
144 return vbc;
145 }
146 };
147
new_cladmin_provider(Confmon * parent)148 Provider* lcb::clconfig::new_cladmin_provider(Confmon *parent) {
149 return new ClusterAdminProvider(parent);
150 }
151