HavoqGT
distributed_db.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Lawrence Livermore National Security, LLC.
3  * Produced at the Lawrence Livermore National Laboratory.
4  * Written by Roger Pearce <rpearce@llnl.gov>.
5  * LLNL-CODE-644630.
6  * All rights reserved.
7  *
8  * This file is part of HavoqGT, Version 0.1.
9  * For details, see https://computation.llnl.gov/casc/dcca-pub/dcca/Downloads.html
10  *
11  * Please also read this link – Our Notice and GNU Lesser General Public License.
12  * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
13  *
14  * This program is free software; you can redistribute it and/or modify it under
15  * the terms of the GNU Lesser General Public License (as published by the Free
16  * Software Foundation) version 2.1 dated February 1999.
17  *
18  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
19  * WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A
20  * PARTICULAR PURPOSE. See the terms and conditions of the GNU General Public
21  * License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License along
24  * with this program; if not, write to the Free Software Foundation, Inc.,
25  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
28  *
29  * Our Preamble Notice
30  *
31  * A. This notice is required to be provided under our contract with the
32  * U.S. Department of Energy (DOE). This work was produced at the Lawrence
33  * Livermore National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE.
34  *
35  * B. Neither the United States Government nor Lawrence Livermore National
36  * Security, LLC nor any of their employees, makes any warranty, express or
37  * implied, or assumes any liability or responsibility for the accuracy,
38  * completeness, or usefulness of any information, apparatus, product, or process
39  * disclosed, or represents that its use would not infringe privately-owned rights.
40  *
41  * C. Also, reference herein to any specific commercial products, process, or
42  * services by trade name, trademark, manufacturer or otherwise does not
43  * necessarily constitute or imply its endorsement, recommendation, or favoring by
44  * the United States Government or Lawrence Livermore National Security, LLC. The
45  * views and opinions of authors expressed herein do not necessarily state or
46  * reflect those of the United States Government or Lawrence Livermore National
47  * Security, LLC, and shall not be used for advertising or product endorsement
48  * purposes.
49  *
50  */
51 
52 
53 
54 #ifndef HAVOQGT_DISTRIBUTED_DB_HPP_INCLUDED
55 #define HAVOQGT_DISTRIBUTED_DB_HPP_INCLUDED
56 
57 #include <boost/interprocess/managed_mapped_file.hpp>
58 #include <boost/interprocess/allocators/allocator.hpp>
59 #include <boost/lexical_cast.hpp>
60 #include <boost/uuid/uuid.hpp>
61 #include <boost/uuid/uuid_generators.hpp>
62 #include <boost/uuid/uuid_io.hpp>
63 
64 #include <string>
65 #include <sstream>
66 #include <stdlib.h>
67 
68 #include <sys/types.h>
69 #include <sys/stat.h>
70 #include <fcntl.h>
71 
72 #include <havoqgt/environment.hpp>
73 
74 
75 namespace havoqgt {
76 
80 class db_create {};
81 class db_open {};
82 
87 private:
88  struct header {
89  int comm_rank;
90  int comm_size;
91  boost::uuids::uuid uuid;
93  };
94 
95  typedef boost::interprocess::basic_managed_mapped_file
96  <char
97  ,boost::interprocess::rbtree_best_fit<boost::interprocess::null_mutex_family>
98  ,boost::interprocess::iset_index> mapped_type;
99 
100 public:
101  typedef mapped_type::segment_manager segment_manager_type;
102 
106  distributed_db(db_create, const char* base_fname)
107  {
108  int mpi_rank = havoqgt_env()->world_comm().rank();
109  int mpi_size = havoqgt_env()->world_comm().size();
110 
111  init_rank_filename(base_fname);
112  if(rank_file_exists())
113  {
114  HAVOQGT_ERROR_MSG("File already exists.");
115  }
116 
117  m_pm = new mapped_type(boost::interprocess::create_only, m_rank_filename.c_str(), get_file_size());
118 
119  #ifdef HAVE_POSIX_FALLOCATE
120  {
121  int fd = open(m_rank_filename.c_str(), O_RDWR);
122  if(fd == -1) {
123  HAVOQGT_ERROR_MSG("Error opening file.");
124  }
125  int ret = posix_fallocate(fd,0,get_file_size());
126  if(ret != 0)
127  {
128  HAVOQGT_ERROR_MSG("posix_fallocate failed.");
129  }
130  close(fd);
131  }
132  #else
133  #warning posix_fallocate not found; OSX?
134  #endif
135 
136  //
137  // Create header
138  header* phead = m_pm->construct<header>(boost::interprocess::unique_instance)();
139  if(mpi_rank == 0) {
140  phead->uuid = boost::uuids::random_generator()();
141  }
142  mpi::mpi_bcast(phead->uuid,0,havoqgt_env()->world_comm().comm());
143  //std::cout << "Rank = " << mpi_rank << ", UUID = " << phead->uuid << std::endl;
144  phead->comm_rank = mpi_rank;
145  phead->comm_size = mpi_size;
146  phead->clean_close = false;
147  }
148 
152  distributed_db(db_open, const char* base_fname)
153  {
154  int mpi_rank = havoqgt_env()->world_comm().rank();
155  int mpi_size = havoqgt_env()->world_comm().size();
156 
157  init_rank_filename(base_fname);
158  if(!rank_file_exists())
159  {
160  std::stringstream error;
161  error << "ERROR: " << __FILE__ << ":" << __LINE__ << ": file not found.";
162  throw std::runtime_error(error.str());
163  }
164 
165  m_pm = new mapped_type(boost::interprocess::open_only, m_rank_filename.c_str());
166 
167  //
168  // Check for header
169  std::pair<header*, std::size_t> ret = m_pm->find<header>(boost::interprocess::unique_instance);
170  if(ret.second == 0) {
171  std::stringstream error;
172  error << "ERROR: " << __FILE__ << ":" << __LINE__ << ": header now found.";
173  throw std::runtime_error(error.str());
174  }
175 
176  //
177  // Check UUID
178  boost::uuids::uuid uuid;
179  if(mpi_rank == 0) {
180  uuid = ret.first->uuid;
181  }
182  mpi::mpi_bcast(uuid,0,havoqgt_env()->world_comm().comm());
183  if(uuid != ret.first->uuid)
184  {
185  std::stringstream error;
186  error << "ERROR: " << __FILE__ << ":" << __LINE__ << ": UUIDs don't match.";
187  throw std::runtime_error(error.str());
188  }
189  //std::cout << "Rank = " << mpi_rank << ", UUID = " << ret.first->uuid << std::endl;
190  if(ret.first->comm_rank != mpi_rank ||
191  ret.first->comm_size != mpi_size ||
192  !ret.first->clean_close) {
193  std::stringstream error;
194  error << "ERROR: " << __FILE__ << ":" << __LINE__ << ": DB corrupt.";
195  throw std::runtime_error(error.str());
196  }
197  }
198 
203  {
204  //
205  // Mark clean close
206  std::pair<header*, std::size_t> ret = m_pm->find<header>(boost::interprocess::unique_instance);
207  if(ret.second == 0) {
208  std::stringstream error;
209  error << "ERROR: " << __FILE__ << ":" << __LINE__ << ": header now found.";
210  throw std::runtime_error(error.str());
211  }
212  ret.first->clean_close = true;
213 
214  delete m_pm;
215  m_pm = nullptr;
216  bool shrink_ret = mapped_type::shrink_to_fit(m_rank_filename.c_str());
217  }
218 
219  segment_manager_type* get_segment_manager()
220  {
221  return m_pm->get_segment_manager();
222  }
223 
224 private:
225 
229  uint64_t get_file_size()
230  {
231  const char* fsize = getenv("HAVOQGT_DB_SIZE");
232  if(fsize == NULL) {
233  //return 700ULL * 1024ULL * 1024ULL * 1024ULL / 24;
234  //return 799700000000ULL;
235  //return 500ULL * 1024ULL * 1024ULL * 1024ULL;
236  // causing probs return 799700000000ULL / 24ULL;
237  // MAXES OUT CATALST!! return 799595142400 / 24ULL;
238  return 512*1024*1024 / havoqgt_env()->node_local_comm().size();
239  }
240  return boost::lexical_cast<uint64_t>(fsize);
241  }
242 
243 
248  {
249  std::ifstream fin(m_rank_filename.c_str());
250  return fin.good();
251  }
252 
256  void init_rank_filename(const char* base_fname)
257  {
258  int mpi_rank = havoqgt_env()->world_comm().rank();
259  int mpi_size = havoqgt_env()->world_comm().size();
260  std::stringstream sstr;
261  sstr << base_fname << "_" << mpi_rank << "_of_" << mpi_size;
262  m_rank_filename = sstr.str();
263  }
264 
265 
266 private:
267  mapped_type* m_pm;
268  std::string m_rank_filename;
269 
270 };
271 
272 
273 } //havoqgt
274 
275 
276 
277 #endif //HAVOQGT_DISTRIBUTED_DB_HPP_INCLUDED
distributed_db(db_open, const char *base_fname)
const communicator & world_comm() const
int size() const
Definition: mpi.hpp:618
int rank() const
Definition: mpi.hpp:619
environment * havoqgt_env()
mapped_type::segment_manager segment_manager_type
boost::interprocess::basic_managed_mapped_file< char,boost::interprocess::rbtree_best_fit< boost::interprocess::null_mutex_family >,boost::interprocess::iset_index > mapped_type
segment_manager_type * get_segment_manager()
void init_rank_filename(const char *base_fname)
const communicator & node_local_comm() const
void mpi_bcast(T &data, int root, MPI_Comm comm)
Definition: mpi.hpp:559
distributed_db(db_create, const char *base_fname)
#define HAVOQGT_ERROR_MSG(msg)
Definition: error.hpp:62