0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
TimerHandler.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 
28 #include <Common/Compat.h>
29 
30 #include "Global.h"
31 #include "RangeServer.h"
33 #include "TimerHandler.h"
34 
35 #include <Hypertable/Lib/KeySpec.h>
36 
37 #include <Common/Config.h>
38 #include <Common/Error.h>
39 #include <Common/InetAddr.h>
40 #include <Common/StringExt.h>
41 #include <Common/System.h>
42 #include <Common/Time.h>
43 
44 #include <algorithm>
45 #include <sstream>
46 
47 using namespace Hypertable;
48 using namespace Hypertable::RangeServer;
49 using namespace Hypertable::Config;
50 
52  : m_comm(comm), m_range_server(range_server) {
53  int32_t maintenance_interval;
54 
55  m_query_cache_memory = get_i64("Hypertable.RangeServer.QueryCache.MaxMemory");
56  m_timer_interval = get_i32("Hypertable.RangeServer.Timer.Interval");
57  maintenance_interval = get_i32("Hypertable.RangeServer.Maintenance.Interval");
59  m_max_app_queue_pause = get_i32("Hypertable.RangeServer.Maintenance.MaxAppQueuePause");
60 
61  if (m_timer_interval > (maintenance_interval+10)) {
62  m_timer_interval = maintenance_interval + 10;
63  HT_INFOF("Reducing timer interval to %d to support maintenance interval %d",
64  m_timer_interval, maintenance_interval);
65  }
66 
68 
69  m_last_schedule = std::chrono::steady_clock::now();
70 
72 
73  return;
74 }
75 
76 
77 
79  int error;
80  if ((error = m_comm->set_timer(0, shared_from_this())) != Error::OK)
81  HT_FATALF("Problem setting timer - %s", Error::get_text(error));
82 }
83 
84 
86  lock_guard<mutex> lock(m_mutex);
87 
89  auto now = std::chrono::steady_clock::now();
90  uint64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_last_schedule).count();
91  int error;
92  uint32_t millis = (elapsed < 1000) ? 1000 - elapsed : 0;
93  HT_INFOF("Scheduling immediate maintenance for %u millis in the future", millis);
94  if ((error = m_comm->set_timer(millis, shared_from_this())) != Error::OK)
95  HT_FATALF("Problem setting timer - %s", Error::get_text(error));
97  }
98  return;
99 }
100 
101 
103  lock_guard<mutex> lock(m_mutex);
104 
105  m_schedule_outstanding = false;
106  m_last_schedule = std::chrono::steady_clock::now();
107 
110  if (!m_app_queue_paused)
111  pause_app_queue();
112  }
113  else if (m_app_queue_paused && !low_memory())
115  }
116 
119  else {
120  int error;
121  if ((error = m_comm->set_timer(m_current_interval, shared_from_this())) != Error::OK)
122  HT_FATALF("Problem setting timer - %s", Error::get_text(error));
123  }
124 }
125 
126 
128  lock_guard<mutex> lock(m_mutex);
129  m_shutdown = true;
130  m_comm->cancel_timer(shared_from_this());
131 }
132 
133 
135  lock_guard<mutex> lock(m_mutex);
136  int error;
137  bool do_maintenance = !m_schedule_outstanding;
138 
139  if (m_shutdown)
140  return;
141 
142  auto now = std::chrono::steady_clock::now();
143 
144  if (m_app_queue_paused) {
145  unsigned int elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_pause_time).count();
146  HT_DEBUGF("App queue paused (pause_time=%u, lmm=%s, restart_gen=%lld, "
147  "queue_gen=%lld)", (unsigned)elapsed,
148  m_low_memory_mode ? "true" : "false", (Lld)m_restart_generation,
149  (Lld)Global::maintenance_queue->generation());
150  if ((m_low_memory_mode && !low_memory()) ||
151  (now - m_pause_time) >= std::chrono::milliseconds(m_max_app_queue_pause) ||
152  m_restart_generation <= Global::maintenance_queue->generation())
155  }
156  else {
157  if (low_memory()) {
158  if (m_low_memory_mode)
159  pause_app_queue();
160  else
161  m_low_memory_mode = true;
162  }
163  else {
164  m_low_memory_mode = false;
166  pause_app_queue();
167  }
168  }
169 
170  // If immediate maintenance requested, disable low memory mode
172  m_low_memory_mode = false;
173 
174  HT_DEBUGF("aq_paused=%s, lowmm=%s, ci=%d, ims=%s, so=%s, dm=%s",
175  m_app_queue_paused ? "true" : "false",
176  m_low_memory_mode ? "true" : "false",
177  (int)m_current_interval,
178  m_immediate_maintenance_scheduled ? "true" : "false",
179  m_schedule_outstanding ? "true" : "false",
180  do_maintenance ? "true" : "false");
181 
182  try {
183 
184  if (event->type == Hypertable::Event::TIMER) {
185 
186  if (do_maintenance) {
188  m_schedule_outstanding = true;
189  }
190  else {
191  if ((error = m_comm->set_timer(m_current_interval, shared_from_this())) != Error::OK)
192  HT_FATALF("Problem setting timer - %s", Error::get_text(error));
193  }
194  }
195  else
196  HT_ERRORF("Unexpected event - %s", event->to_str().c_str());
197  }
198  catch (Hypertable::Exception &e) {
199  HT_ERROR_OUT << e << HT_END;
200  }
201 }
202 
204  m_app_queue->stop();
205  m_app_queue_paused = true;
206  m_current_interval = 500;
209  HT_INFOF("Application queue PAUSED due to %s",
210  m_low_memory_mode ? "low memory" : "log size threshold exceeded");
211  m_pause_time = std::chrono::steady_clock::now();
212 }
213 
214 
217  auto now = std::chrono::steady_clock::now();
218  int64_t pause_millis = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_pause_time).count();
219  HT_INFOF("Restarting application queue (pause time = %lld millis)",
220  (Lld)pause_millis);
221  m_app_queue->start();
222  m_app_queue_paused = false;
224  m_low_memory_mode = false;
225 
226  std::stringstream ss;
227  auto seconds = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
228  ss << seconds << "\tapp-queue-pause\t" << pause_millis;
230 }
231 
233  int64_t memory_used = Global::memory_tracker->balance();
234  bool low_physical_memory = false;
235 
236  // ensure unused physical memory if it makes sense
239 
240  // adjust current limit according to the actual memory situation
241  int64_t free_memory = (int64_t)(System::mem_stat().free * Property::MiB);
244 
245  // low physical memory reached?
246  low_physical_memory = free_memory < Global::memory_limit_ensure_unused_current;
247  if (low_physical_memory)
248  HT_INFOF("Low physical memory (free %.2fMB, limit %.2fMB)", free_memory / (double)Property::MiB,
249  Global::memory_limit_ensure_unused_current / (double)Property::MiB);
250  }
251 
252  return low_physical_memory || memory_used > Global::memory_limit;
253 }
Retrieves system information (hardware, installation directory, etc)
void handle(Hypertable::EventPtr &event)
Timer event handler callback method.
int64_t m_userlog_size_threshold
Pause app queue if USER log exceeds this size.
Definition: TimerHandler.h:172
static int64_t memory_limit_ensure_unused_current
Definition: Global.h:105
static int64_t memory_limit
Definition: Global.h:99
const uint64_t MiB
Definition: Properties.h:157
void shutdown()
Start shutdown sequence.
std::shared_ptr< Event > EventPtr
Smart pointer to Event.
Definition: Event.h:228
bool m_shutdown
Indicates that a shutdown is in progress.
Definition: TimerHandler.h:193
Declarations for RangeServer.
void schedule_immediate_maintenance()
Force maintenance to be scheduled immediately.
Definition: TimerHandler.cc:85
#define HT_ASSERT(_e_)
Definition: Logger.h:396
int32_t m_current_interval
Current timer interval (set to 500 when app queue is paused)
Definition: TimerHandler.h:187
static int64_t memory_limit_ensure_unused
Definition: Global.h:102
static int64_t log_prune_threshold_max
Definition: Global.h:96
bool m_low_memory_mode
Low memory mode.
Definition: TimerHandler.h:202
static Hypertable::MemoryTracker * memory_tracker
Definition: Global.h:94
bool m_schedule_outstanding
A maintenance scheduling operation is outstanding.
Definition: TimerHandler.h:205
void restart_app_queue()
Restarts the application queue.
void write_profile_data(const String &line)
Definition: RangeServer.h:218
Apps::RangeServer * m_range_server
RangeServer.
Definition: TimerHandler.h:163
void start()
Start timer.
Definition: TimerHandler.cc:78
const char * get_text(int error)
Returns a descriptive error message.
Definition: Error.cc:330
Compatibility Macros for C/C++.
std::mutex m_mutex
Mutex for serializing access
Definition: TimerHandler.h:157
#define HT_END
Definition: Logger.h:220
TimerHandler(Comm *comm, Apps::RangeServer *range_server)
Constructor.
Definition: TimerHandler.cc:51
ApplicationQueuePtr get_application_queue()
Definition: RangeServer.h:206
Declarations for TimerHandler.
#define HT_ERROR_OUT
Definition: Logger.h:301
Time related declarations.
bool low_memory()
Checks for low memory.
Hypertable definitions
int32_t m_timer_interval
Timer interval.
Definition: TimerHandler.h:184
#define HT_FATALF(msg,...)
Definition: Logger.h:343
#define HT_DEBUGF(msg,...)
Definition: Logger.h:260
static Hypertable::MaintenanceQueuePtr maintenance_queue
Definition: Global.h:67
long long int Lld
Shortcut for printf formats.
Definition: String.h:53
bool m_immediate_maintenance_scheduled
An immediate maintenance timer has been scheduled.
Definition: TimerHandler.h:196
bool m_app_queue_paused
Application queue is paused.
Definition: TimerHandler.h:199
Entry point to AsyncComm service.
Definition: Comm.h:61
void pause_app_queue()
Pauses the application queue.
int64_t m_restart_generation
Generation of maintenance queue signalling application queue restart.
Definition: TimerHandler.h:175
int32_t m_max_app_queue_pause
Maximum time to keep application queue paused each time it is paused.
Definition: TimerHandler.h:190
int64_t m_query_cache_memory
Query cache max size (Hypertable.RangeServer.QueryCache.MaxMemory)
Definition: TimerHandler.h:169
#define HT_INFOF(msg,...)
Definition: Logger.h:272
Internet address wrapper classes and utility functions.
Timer event
Definition: Event.h:65
This is a generic exception class for Hypertable.
Definition: Error.h:314
std::chrono::steady_clock::time_point m_pause_time
Last time application queue was paused.
Definition: TimerHandler.h:181
static CommitLogPtr user_log
Definition: Global.h:77
std::chrono::steady_clock::time_point m_last_schedule
Last time maintenance was scheduled.
Definition: TimerHandler.h:178
ApplicationQueuePtr m_app_queue
Application queue.
Definition: TimerHandler.h:166
#define HT_ERRORF(msg,...)
Definition: Logger.h:300
void maintenance_scheduled_notify()
Signal maintenance scheduling complete.
int set_timer(uint32_t duration_millis, const DispatchHandlerPtr &handler)
Sets a timer for duration_millis milliseconds in the future.
Definition: Comm.cc:465
void cancel_timer(const DispatchHandlerPtr &handler)
Cancels all scheduled timers registered with the dispatch handler handler.
Definition: Comm.cc:483
Configuration settings.
Comm * m_comm
Comm object.
Definition: TimerHandler.h:160
String extensions and helpers: sets, maps, append operators etc.
static const MemStat & mem_stat()
Retrieves updated Memory statistics (see SystemInfo.h)
Definition: SystemInfo.cc:339
Error codes, Exception handling, error logging.
int64_t balance()
Return total range server memory used.
Definition: MemoryTracker.h:70