0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
HyperspaceMasterFile.h
Go to the documentation of this file.
1 /* -*- c++ -*-
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 
26 
27 #ifndef Hypertable_Master_HyperspaceMasterFile_h
28 #define Hypertable_Master_HyperspaceMasterFile_h
29 
30 #include <Hyperspace/Session.h>
31 
32 #include <Common/Properties.h>
33 #include <Common/ScopeGuard.h>
34 
35 #include <condition_variable>
36 #include <mutex>
37 #include <string>
38 
39 namespace Hypertable {
40 namespace Master {
41 
44 
45  using namespace Hyperspace;
46 
49  public:
50 
55  : m_props(props), m_hyperspace(hyperspace) {}
56 
58 
59  HyperspaceMasterFile &operator=(const HyperspaceMasterFile &) = delete;
60 
63 
85  template<typename Function>
86  bool obtain_master_lock(const std::string &toplevel_dir,
87  Function set_startup_status) {
88  try {
89  uint64_t handle {};
90  HT_ON_SCOPE_EXIT(&Hyperspace::close_handle_ptr, m_hyperspace, &handle);
91 
92  // Create TOPLEVEL directory if not exist
93  m_hyperspace->mkdirs(toplevel_dir);
94 
95  // Create /hypertable/master if not exist
96  if (!m_hyperspace->exists( toplevel_dir + "/master" )) {
97  handle = m_hyperspace->open( toplevel_dir + "/master",
99  m_hyperspace->close(handle);
100  handle = 0;
101  }
102 
103  {
104  LockStatus lock_status = LOCK_STATUS_BUSY;
105  uint32_t oflags = OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_LOCK;
106  LockSequencer sequencer;
107  bool reported = false;
108  uint32_t retry_interval = m_props->get_i32("Hypertable.Connection.Retry.Interval");
109 
110  m_handle = m_hyperspace->open(toplevel_dir + "/master", oflags);
111 
112  while (lock_status != LOCK_STATUS_GRANTED) {
113 
114  m_hyperspace->try_lock(m_handle, LOCK_MODE_EXCLUSIVE,
115  &lock_status, &sequencer);
116 
117  if (lock_status != LOCK_STATUS_GRANTED) {
118  if (!reported) {
119  set_startup_status(false);
120  HT_INFOF("Couldn't obtain lock on '%s/master' due to conflict, entering retry loop ...",
121  toplevel_dir.c_str());
122  reported = true;
123  }
124  {
125  unique_lock<mutex> lock(m_mutex);
126  m_cond.wait_for(lock, std::chrono::milliseconds(retry_interval));
127  if (m_shutdown)
128  return false;
129  }
130  }
131  }
132 
133  set_startup_status(true);
134  m_acquired = true;
135 
136  HT_INFOF("Obtained lock on '%s/master'", toplevel_dir.c_str());
137 
138  if (!m_hyperspace->attr_exists(m_handle, "next_server_id"))
139  m_hyperspace->attr_set(m_handle, "next_server_id", "1", 2);
140  }
141 
142  m_hyperspace->mkdirs(toplevel_dir + "/servers");
143  m_hyperspace->mkdirs(toplevel_dir + "/tables");
144 
145  // Create /hypertable/root
146  handle = m_hyperspace->open(toplevel_dir + "/root",
148 
149  }
150  catch (Exception &e) {
151  HT_FATAL_OUT << e << HT_END;
152  }
153  return true;
154  }
155 
157  bool lock_acquired() { return m_acquired; }
158 
160  void write_master_address();
161 
164  uint64_t next_server_id();
165 
166  void shutdown();
167 
168  private:
169 
172 
174  std::condition_variable m_cond;
175 
178 
181 
183  uint64_t m_handle {};
184 
186  bool m_shutdown {};
187 
189  bool m_acquired {};
190  };
191 
193 
194 }}
195 
196 #endif // HyperspaceMasterFile_h
static std::mutex mutex
Definition: Logger.cc:43
Lock successfully granted.
Definition: LockSequencer.h:58
Exclusive lock attempt failed because another has it locked.
Definition: LockSequencer.h:60
Program options handling.
LockStatus
Lock status.
Definition: LockSequencer.h:56
#define HT_ON_SCOPE_EXIT(...)
Definition: ScopeGuard.h:301
bool lock_acquired()
Returns flag indicating if lock was acquired.
SessionPtr m_hyperspace
Hyperspace session.
HyperspaceMasterFile(PropertiesPtr props, SessionPtr &hyperspace)
Constructor.
Hyperspace definitions
std::mutex m_mutex
Mutex for serializing member access
Open file for locking.
Definition: Session.h:75
bool obtain_master_lock(const std::string &toplevel_dir, Function set_startup_status)
Acquires lock on toplevel_dir/master file in hyperspace.
void shutdown(ResponseCallback *cb, uint64_t session_id)
Definition: Master.cc:1160
Open file for writing.
Definition: Session.h:73
std::shared_ptr< Session > SessionPtr
Definition: Session.h:734
std::shared_ptr< Properties > PropertiesPtr
Definition: Properties.h:447
void close_handle_ptr(SessionPtr hyperspace, uint64_t *handlep)
Definition: Session.cc:1400
#define HT_END
Definition: Logger.h:220
Facilitates operations on the master file in Hyperspace.
Hypertable definitions
Lock exclusive mode.
Definition: LockSequencer.h:51
void lock(ResponseCallbackLock *cb, uint64_t session_id, uint64_t handle, uint32_t mode, bool try_lock)
Definition: Master.cc:1203
#define HT_INFOF(msg,...)
Definition: Logger.h:272
std::condition_variable m_cond
Condition variable signalling shutdown.
This is a generic exception class for Hypertable.
Definition: Error.h:314
Create file if it does not exist.
Definition: Session.h:77
Open file for reading.
Definition: Session.h:71
#define HT_FATAL_OUT
Definition: Logger.h:347
Executes user-defined functions when leaving the current scope.