STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
config.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * lib/mng/config.cpp
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002 Roman Dementiev <[email protected]>
7  * Copyright (C) 2007, 2009 Johannes Singler <[email protected]>
8  * Copyright (C) 2008, 2009 Andreas Beckmann <[email protected]>
9  * Copyright (C) 2013 Timo Bingmann <[email protected]>
10  *
11  * Distributed under the Boost Software License, Version 1.0.
12  * (See accompanying file LICENSE_1_0.txt or copy at
13  * http://www.boost.org/LICENSE_1_0.txt)
14  **************************************************************************/
15 
16 #include <fstream>
18 #include <stxxl/bits/config.h>
19 #include <stxxl/bits/io/file.h>
20 #include <stxxl/bits/mng/config.h>
22 #include <stxxl/version.h>
23 
24 #if STXXL_WINDOWS
25  #ifndef NOMINMAX
26  #define NOMINMAX
27  #endif
28  #include <windows.h>
29 #else
30  #include <unistd.h>
31 #endif
32 
34 
35 static inline bool exist_file(const std::string& path)
36 {
37  //STXXL_MSG("Checking " << path << " for disk configuration.");
38  std::ifstream in(path.c_str());
39  return in.good();
40 }
41 
42 config::~config()
43 {
44  for (disk_list_type::const_iterator it = disks_list.begin();
45  it != disks_list.end(); it++)
46  {
47  if (it->delete_on_exit)
48  {
49  STXXL_ERRMSG("Removing disk file: " << it->path);
50  unlink(it->path.c_str());
51  }
52  }
53 }
54 
55 void config::initialize()
56 {
57  // if disks_list is empty, then try to load disk configuration files
58  if (disks_list.size() == 0)
59  {
60  find_config();
61  }
62 
63  is_initialized = true;
64 }
65 
66 void config::find_config()
67 {
68  // check several locations for disk configuration files
69 
70  // check STXXLCFG environment path
71  const char* stxxlcfg = getenv("STXXLCFG");
72  if (stxxlcfg && exist_file(stxxlcfg))
73  return load_config_file(stxxlcfg);
74 
75 #if !STXXL_WINDOWS
76  // read environment, unix style
77  const char* hostname = getenv("HOSTNAME");
78  const char* home = getenv("HOME");
79  const char* suffix = "";
80 #else
81  // read environment, windows style
82  const char* hostname = getenv("COMPUTERNAME");
83  const char* home = getenv("APPDATA");
84  const char* suffix = ".txt";
85 #endif
86 
87  // check current directory
88  {
89  std::string basepath = "./.stxxl";
90 
91  if (hostname && exist_file(basepath + "." + hostname + suffix))
92  return load_config_file(basepath + "." + hostname + suffix);
93 
94  if (exist_file(basepath + suffix))
95  return load_config_file(basepath + suffix);
96  }
97 
98  // check home directory
99  if (home)
100  {
101  std::string basepath = std::string(home) + "/.stxxl";
102 
103  if (hostname && exist_file(basepath + "." + hostname + suffix))
104  return load_config_file(basepath + "." + hostname + suffix);
105 
106  if (exist_file(basepath + suffix))
107  return load_config_file(basepath + suffix);
108  }
109 
110  // load default configuration
111  load_default_config();
112 }
113 
114 void config::load_default_config()
115 {
116  STXXL_ERRMSG("Warning: no config file found.");
117  STXXL_ERRMSG("Using default disk configuration.");
118 #if !STXXL_WINDOWS
119  disk_config entry1("/var/tmp/stxxl", 1000 * 1024 * 1024, "syscall");
120  entry1.delete_on_exit = true;
121  entry1.autogrow = true;
122 #else
123  disk_config entry1("", 1000 * 1024 * 1024, "wincall");
124  entry1.delete_on_exit = true;
125  entry1.autogrow = true;
126 
127  char* tmpstr = new char[255];
128  if (GetTempPath(255, tmpstr) == 0)
129  STXXL_THROW_WIN_LASTERROR(resource_error, "GetTempPath()");
130  entry1.path = tmpstr;
131  entry1.path += "stxxl.tmp";
132  delete[] tmpstr;
133 #endif
134  disks_list.push_back(entry1);
135 
136  // no flash disks
137  first_flash = (unsigned int)disks_list.size();
138 }
139 
140 void config::load_config_file(const std::string& config_path)
141 {
142  std::vector<disk_config> flash_list;
143  std::ifstream cfg_file(config_path.c_str());
144 
145  if (!cfg_file)
146  return load_default_config();
147 
148  std::string line;
149 
150  while (std::getline(cfg_file, line))
151  {
152  // skip comments
153  if (line.size() == 0 || line[0] == '#') continue;
154 
155  disk_config entry;
156  entry.parse_line(line); // throws on errors
157 
158  if (!entry.flash)
159  disks_list.push_back(entry);
160  else
161  flash_list.push_back(entry);
162  }
163  cfg_file.close();
164 
165  // put flash devices after regular disks
166  first_flash = (unsigned int)disks_list.size();
167  disks_list.insert(disks_list.end(), flash_list.begin(), flash_list.end());
168 
169  if (disks_list.empty()) {
170  STXXL_THROW(std::runtime_error,
171  "No disks found in '" << config_path << "'.");
172  }
173 }
174 
175 uint64 config::total_size() const
176 {
177  assert(is_initialized);
178 
179  uint64 total_size = 0;
180 
181  for (disk_list_type::const_iterator it = disks_list.begin();
182  it != disks_list.end(); it++)
183  {
184  total_size += it->size;
185  }
186 
187  return total_size;
188 }
189 
190 disk_config::disk_config()
191  : size(0),
192  autogrow(false),
193  delete_on_exit(false),
194  direct(DIRECT_TRY),
195  flash(false),
196  queue(file::DEFAULT_QUEUE),
197  raw_device(false),
198  unlink_on_open(false)
199 { }
200 
201 disk_config::disk_config(const std::string& _path, uint64 _size,
202  const std::string& _io_impl)
203  : path(_path),
204  size(_size),
205  io_impl(_io_impl),
206  autogrow(false),
207  delete_on_exit(false),
208  direct(DIRECT_TRY),
209  flash(false),
210  queue(file::DEFAULT_QUEUE),
211  raw_device(false),
212  unlink_on_open(false)
213 {
214  parse_fileio();
215 }
216 
217 disk_config::disk_config(const std::string& line)
218  : size(0),
219  autogrow(false),
220  delete_on_exit(false),
221  direct(DIRECT_TRY),
222  flash(false),
223  queue(file::DEFAULT_QUEUE),
224  raw_device(false),
225  unlink_on_open(false)
226 {
227  parse_line(line);
228 }
229 
230 void disk_config::parse_line(const std::string& line)
231 {
232  // split off disk= or flash=
233  std::vector<std::string> eqfield = split(line, "=", 2, 2);
234 
235  if (eqfield[0] == "disk") {
236  flash = false;
237  }
238  else if (eqfield[0] == "flash") {
239  flash = true;
240  }
241  else {
242  STXXL_THROW(std::runtime_error,
243  "Unknown configuration token " << eqfield[0]);
244  }
245 
246  // *** Set Default Extra Options ***
247 
248  autogrow = false;
249  delete_on_exit = false;
250  direct = DIRECT_TRY;
251  // flash is already set
253  unlink_on_open = false;
254 
255  // *** Save Basic Options ***
256 
257  // split at commands, at least 3 fields
258  std::vector<std::string> cmfield = split(eqfield[1], ",", 3, 3);
259 
260  // path:
261  path = cmfield[0];
262  // replace ### -> pid in path
263  {
264  std::string::size_type pos;
265  if ((pos = path.find("###")) != std::string::npos)
266  {
267 #if !STXXL_WINDOWS
268  int pid = getpid();
269 #else
270  DWORD pid = GetCurrentProcessId();
271 #endif
272  path.replace(pos, 3, to_str(pid));
273  }
274  }
275 
276  // size: (default unit MiB)
277  if (!parse_SI_IEC_size(cmfield[1], size, 'M')) {
278  STXXL_THROW(std::runtime_error,
279  "Invalid disk size '" << cmfield[1] << "' in disk configuration file.");
280  }
281 
282  if (size == 0) {
283  autogrow = true;
284  delete_on_exit = true;
285  }
286 
287  // io_impl:
288  io_impl = cmfield[2];
289  parse_fileio();
290 }
291 
293 {
294  // skip over leading spaces
295  size_t leadspace = io_impl.find_first_not_of(' ');
296  if (leadspace > 0)
297  io_impl = io_impl.substr(leadspace);
298 
299  // split off extra fileio parameters
300  size_t spacepos = io_impl.find(' ');
301  if (spacepos == std::string::npos)
302  return; // no space in fileio
303 
304  // *** Parse Extra Fileio Parameters ***
305 
306  std::string paramstr = io_impl.substr(spacepos + 1);
307  io_impl = io_impl.substr(0, spacepos);
308 
309  std::vector<std::string> param = split(paramstr, " ");
310 
311  for (std::vector<std::string>::const_iterator p = param.begin();
312  p != param.end(); ++p)
313  {
314  // split at equal sign
315  std::vector<std::string> eq = split(*p, "=", 2, 2);
316 
317  // *** PLEASE try to keep the elseifs sorted by parameter name!
318  if (*p == "") {
319  // skip blank options
320  }
321  else if (*p == "autogrow")
322  {
323  // TODO: which fileio implementation support autogrow?
324  autogrow = true;
325  }
326  else if (*p == "delete" || *p == "delete_on_exit")
327  {
328  delete_on_exit = true;
329  }
330  else if (*p == "direct" || *p == "nodirect" || eq[0] == "direct")
331  {
332  // io_impl is not checked here, but I guess that is okay for DIRECT
333  // since it depends highly platform _and_ build-time configuration.
334 
335  if (*p == "direct") direct = DIRECT_ON; // force ON
336  else if (*p == "nodirect") direct = DIRECT_OFF; // force OFF
337  else if (eq[1] == "off") direct = DIRECT_OFF;
338  else if (eq[1] == "try") direct = DIRECT_TRY;
339  else if (eq[1] == "on") direct = DIRECT_ON;
340  else if (eq[1] == "no") direct = DIRECT_OFF;
341  else if (eq[1] == "yes") direct = DIRECT_ON;
342  else
343  {
344  STXXL_THROW(std::runtime_error,
345  "Invalid parameter '" << *p << "' in disk configuration file.");
346  }
347  }
348  else if (eq[0] == "queue")
349  {
350  char* endp;
351  queue = strtoul(eq[1].c_str(), &endp, 10);
352  if (endp && *endp != 0) {
353  STXXL_THROW(std::runtime_error,
354  "Invalid parameter '" << *p << "' in disk configuration file.");
355  }
356  }
357  else if (*p == "raw_device")
358  {
359  if (!(io_impl == "syscall")) {
360  STXXL_THROW(std::runtime_error, "Parameter '" << *p << "' invalid for fileio '" << io_impl << "' in disk configuration file.");
361  }
362 
363  raw_device = true;
364  }
365  else if (*p == "unlink" || *p == "unlink_on_open")
366  {
367  if (!(io_impl == "syscall" || io_impl == "mmap") || io_impl == "wbtl") {
368  STXXL_THROW(std::runtime_error, "Parameter '" << *p << "' invalid for fileio '" << io_impl << "' in disk configuration file.");
369  }
370 
371  unlink_on_open = true;
372  }
373  else
374  {
375  STXXL_THROW(std::runtime_error,
376  "Invalid optional parameter '" << *p << "' in disk configuration file.");
377  }
378  }
379 }
380 
381 std::string disk_config::fileio_string() const
382 {
383  std::ostringstream oss;
384 
385  oss << io_impl;
386 
387  if (autogrow)
388  oss << " autogrow";
389 
390  if (delete_on_exit)
391  oss << " delete_on_exit";
392 
393  // tristate direct variable: OFF, TRY, ON
394  if (direct == DIRECT_OFF)
395  oss << " direct=off";
396  else if (direct == DIRECT_TRY)
397  ; // silenced: oss << " direct=try";
398  else if (direct == DIRECT_ON)
399  oss << " direct=on";
400  else
401  assert(!"Invalid setting for 'direct' option.");
402 
403  if (flash)
404  oss << " flash";
405 
406  if (queue != file::DEFAULT_QUEUE)
407  oss << " queue=" << queue;
408 
409  if (raw_device)
410  oss << " raw_device";
411 
412  if (unlink_on_open)
413  oss << " unlink_on_open";
414 
415  return oss.str();
416 }
417 
419 // vim: et:ts=4:sw=4
int queue
select request queue for disk. Use different queues for files on different disks. queue=-1 -&gt; default...
Definition: config.h:92
unsigned long long int uint64
Definition: types.h:41
External FIFO queue container. Introduction to queue container: see STXXL Queue tutorial Design a...
Definition: queue.h:52
bool unlink_on_open
unlink file immediately after opening (available on most Unix)
Definition: config.h:98
#define STXXL_THROW(exception_type, error_message)
Throws exception_type with &quot;Error in [function] : [error_message]&quot;.
static bool exist_file(const std::string &path)
Definition: config.cpp:35
#define STXXL_THROW_WIN_LASTERROR(exception_type, error_message)
Throws exception_type with &quot;Error in [function] : [error_message] : [formatted GetLastError()]&quot;.
bool delete_on_exit
delete file on program exit (default for autoconfigurated files)
Definition: config.h:80
Defines interface of file.
Definition: file.h:52
std::string path
the file path used by the io implementation
Definition: config.h:42
Encapsulate the configuration of one &quot;disk&quot;. The disk is actually a file I/O object which block_manag...
Definition: config.h:35
static std::vector< std::string > split(const std::string &str, const std::string &sep, unsigned int min_fields=0, unsigned int limit_fields=std::numeric_limits< unsigned int >::max())
Split a string by given separator string. Returns a vector of strings with at least min_fields and at...
Definition: utils.h:57
bool autogrow
autogrow file if more disk space is needed, automatically set if size == 0.
Definition: config.h:77
std::string to_str(const Type &t)
Format any ostream-able type into a string.
Definition: utils.h:98
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
std::string fileio_string() const
return formatted fileio name and optional configuration parameters
Definition: config.cpp:381
void parse_line(const std::string &line)
parse a disk=&lt;path&gt;,&lt;size&gt;,&lt;fileio&gt; options line into disk_config, throws std::runtime_error on parse...
Definition: config.cpp:230
bool parse_SI_IEC_size(const std::string &str, uint64 &size, char def_unit=0)
Parse a string like &quot;343KB&quot; or &quot;44 GiB&quot; into the corresponding size in bytes. Returns the number of b...
Definition: utils.cpp:24
disk_config()
default constructor
Definition: config.cpp:190
#define STXXL_ERRMSG(x)
Definition: verbose.h:79
static const int DEFAULT_QUEUE
Definition: file.h:86
bool raw_device
turned on by syscall fileio when the path points to a raw block device
Definition: config.h:95
void parse_fileio()
parse the &quot;io_impl&quot; parameter into the optional parameter fields.
Definition: config.cpp:292
bool flash
marks flash drives (configuration entries with flash= instead of disk=)
Definition: config.h:88
enum stxxl::disk_config::direct_type direct
std::string io_impl
io implementation to access file
Definition: config.h:48
uint64 size
file size to initially allocate
Definition: config.h:45
#define STXXL_END_NAMESPACE
Definition: namespace.h:17