0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
LoadBalancer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; version 3 of the
9  * License, or any later version.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 #include <Common/Compat.h>
22 
24 #include "BalanceAlgorithmLoad.h"
26 #include "LoadBalancer.h"
27 #include "Utility.h"
28 
29 #include <cstring>
30 
31 using namespace Hypertable;
32 using namespace std;
33 
35  : m_context(context), m_new_server_added(false), m_paused(false) {
36 
37  m_crontab = Crontab( m_context->props->get_str("Hypertable.LoadBalancer.Crontab") );
38 
40  m_context->props->get_i32("Hypertable.LoadBalancer.BalanceDelay.NewServer");
41 
42  m_enabled = context->props->get_bool("Hypertable.LoadBalancer.Enable");
43 
45  m_context->props->get_f64("Hypertable.LoadBalancer.LoadavgThreshold");
46 
47  time_t t = time(0) +
48  m_context->props->get_i32("Hypertable.LoadBalancer.BalanceDelay.Initial");
49 
51 
52  if (m_context->rsc_manager->exist_unbalanced_servers()) {
53  m_new_server_added = true;
55  }
56  else
58 }
59 
61  lock_guard<mutex> lock(m_add_mutex);
62  m_new_server_added = true;
64 }
65 
67  lock_guard<mutex> lock(m_add_mutex);
68  time_t now = time(0);
69  if (m_paused)
70  return false;
72  return true;
73  if (m_enabled && now >= m_next_balance_time_load)
74  return true;
75  return false;
76 }
77 
78 
80  lock_guard<mutex> lock(m_add_mutex);
81  time_t now = time(0);
82  m_new_server_added = false;
83  if (m_context->rsc_manager->exist_unbalanced_servers()) {
84  m_new_server_added = true;
86  }
88  m_paused = false;
89 }
90 
91 
92 void LoadBalancer::transfer_monitoring_data(vector<RangeServerStatistics> &stats) {
93  lock_guard<mutex> lock(m_add_mutex);
94  m_statistics.swap(stats);
95 }
96 
97 
99  std::vector <RangeServerConnectionPtr> &balanced) {
100  String name, arguments;
101  time_t now = time(0);
102  BalanceAlgorithmPtr algo;
103 
104  {
105  lock_guard<mutex> lock(m_add_mutex);
106  String algorithm_spec = plan->algorithm;
107 
108  if (m_statistics.empty())
109  HT_THROW(Error::MASTER_BALANCE_PREVENTED, "Statistics vector is empty");
110 
111  if (m_statistics.size() == 1) {
112  if (m_context->rsc_manager->server_count() == 1) {
113  if (m_new_server_added) {
115  if (m_context->rsc_manager->find_server_by_location(m_statistics[0].location, rsc))
116  balanced.push_back(rsc);
117  }
118  plan->clear();
119  m_paused = true;
120  return;
121  }
122  HT_THROW(Error::MASTER_BALANCE_PREVENTED, "Not enough server statistics");
123  }
124 
128  boost::trim(algorithm_spec);
129  if (algorithm_spec == "") {
131  name = "table_ranges";
132  else if (now >= m_next_balance_time_load)
133  name = "load";
134  else
135  HT_THROW(Error::MASTER_BALANCE_PREVENTED, "Balance not needed");
136  }
137  else {
138  char *ptr = strchr((char *)algorithm_spec.c_str(), ' ');
139  if (ptr) {
140  name = String(algorithm_spec, 0, ptr-algorithm_spec.c_str());
141  if (*ptr) {
142  arguments = String(ptr);
143  boost::trim(arguments);
144  }
145  }
146  else
147  name = algorithm_spec;
148  boost::to_lower(name);
149  }
150 
151  HT_INFOF("LoadBalance(name='%s', args='%s')", name.c_str(), arguments.c_str());
152 
153  if (name == "offload")
154  algo = make_shared<BalanceAlgorithmOffload>(m_context, m_statistics, arguments);
155  else if (name == "table_ranges")
156  algo = make_shared<BalanceAlgorithmEvenRanges>(m_context, m_statistics);
157  else if (name == "load")
158  algo = make_shared<BalanceAlgorithmLoad>(m_context, m_statistics);
159  else
161  "Unrecognized algorithm - %s", name.c_str());
162 
163  plan->algorithm = name;
164  }
165 
166  algo->compute_plan(plan, balanced);
167 
168  {
169  lock_guard<mutex> lock(m_add_mutex);
170  m_paused = true;
171  }
172 }
173 
175 
176 }
time_t next_event(time_t now)
Retrieves the timestamp of the next event.
Definition: Crontab.cc:46
std::shared_ptr< RangeServerConnection > RangeServerConnectionPtr
LoadBalancer(ContextPtr context)
Definition: LoadBalancer.cc:34
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
std::shared_ptr< BalancePlan > BalancePlanPtr
Definition: BalancePlan.h:81
STL namespace.
std::shared_ptr< Context > ContextPtr
Smart pointer to Context.
Definition: Context.h:265
time_t m_next_balance_time_new_server
Definition: LoadBalancer.h:60
void create_plan(BalancePlanPtr &plan, std::vector< RangeServerConnectionPtr > &balanced)
Definition: LoadBalancer.cc:98
Tracks timing of periodic events.
Definition: Crontab.h:55
std::shared_ptr< BalanceAlgorithm > BalanceAlgorithmPtr
Compatibility Macros for C/C++.
uint32_t m_new_server_balance_delay
Definition: LoadBalancer.h:62
Hypertable definitions
Declarations for general-purpose utility functions.
#define HT_INFOF(msg,...)
Definition: Logger.h:272
#define HT_THROWF(_code_, _fmt_,...)
Definition: Error.h:490
std::vector< RangeServerStatistics > m_statistics
Definition: LoadBalancer.h:66
void transfer_monitoring_data(vector< RangeServerStatistics > &stats)
Definition: LoadBalancer.cc:92
void reenable_balancer(LoadBalancer *balancer)
#define HT_THROW(_code_, _msg_)
Definition: Error.h:478