Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
open.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file basic/database/open.cc
11 /// @brief Functions for opening database files
12 /// @author Stuart G. Mentzer (Stuart_Mentzer@objexx.com)
13 
14 
15 // Unit headers
16 #include <basic/database/open.hh>
17 #include <basic/Tracer.hh>
18 
19 // Project headers
21 #include <basic/options/option.hh>
22 
23 // Utility headers
24 #include <utility/io/izstream.hh>
26 #include <utility/file/PathName.hh>
28 
29 // C++ headers
30 #include <cstdlib>
31 #include <iostream>
32 
33 #if defined(MAC) || defined(__APPLE__) || defined(__OSX__) || defined(linux) || defined(__linux__) || defined(__linux)
34 // POSIX specific headers
35 #include <pwd.h>
36 #endif
37 
38 using basic::T;
39 
40 //Auto Headers
41 #include <utility/vector1.hh>
42 
43 
44 using basic::Error;
45 using basic::Warning;
46 
47 namespace basic {
48 namespace database {
49 
50 static THREAD_LOCAL basic::Tracer TR( "basic.io.database" );
51 
52 
53 /// @brief Open a database file on a provided stream
54 bool
56  utility::io::izstream & db_stream,
57  std::string const & db_file,
58  bool warn /* = true */
59 )
60 {
61  using namespace utility::excn;
62 
63  if ( db_stream.good() ) {
64  db_stream.close();
65  db_stream.clear();
66  }
67  if ( db_file.length() == 0 ) {
68  throw EXCN_Msg_Exception("Unable to open database file ''");
69  return false;
70  }
71 
72  db_stream.open( full_name( db_file, warn ) );
73 
74  if ( db_stream ) { // Open succeeded
75  TR << "Database file opened: " << db_file << std::endl;
76  return true;
77  } else { // Open failed
78  std::stringstream err_msg;
79  err_msg
80  << "Database file open failed for: \"" << db_file << "\"" << std::endl;
81  throw EXCN_Msg_Exception(err_msg.str());
82 
83 #ifdef __native_client__
84  throw( "ERROR: Database file open failed for: " + db_file );
85 #endif
86  db_stream.close();
87  db_stream.clear();
88  return false;
89  }
90 }
91 
92 
93 /// @brief Full-path database file name
94 std::string
96  std::string const & db_file,
97  bool warn // = true
98 )
99 {
100  using namespace basic::options;
101  using namespace basic::options::OptionKeys;
102 
103  for ( size_t i = 1, i_end = option[ in::path::database ]().size(); i <= i_end; ++i ) {
104  std::string fname = option[ in::path::database ](i).name() + db_file;
105  if ( utility::file::file_exists(fname) || utility::file::file_exists(fname + ".gz") ) return fname;
106  }
107  // Don't exit -- sometimes caller wants to check if file exists (e.g. Dunbrack .bin file)
108  //utility_exit_with_message("Unable to locate database file "+db_file);
109  if ( warn ) Warning() << "Unable to locate database file " << db_file << std::endl;
110  return option[ in::path::database ](1).name() + db_file;
111 }
112 
113 /// @brief Find a path to a file.
114 ///
115 /// Try various combinations to locate the specific file being requested by the user.
116 /// (inspired by core::scoring::ScoreFunction::find_weights_file())
117 ///
118 /// @athor Labonte <JWLabonte@jhu.edu>
119 std::string
120 find_database_path( std::string dir, std::string filename)
121 {
122  using namespace utility::io;
123 
124  std::string const & path( basic::database::full_name( dir ) );
125 
126  izstream potential_file( filename );
127  if ( potential_file.good() ) {
128  return filename;
129  } else {
130  izstream potential_file( path + filename); // Let's assume it's in the database in the usual spot.
131  if ( potential_file.good() ) {
132  return path + filename;
133  } else {
134  utility_exit_with_message( "Unable to open file. Neither ./" + filename +
135  " nor " + "./" + filename +
136  " nor " + path + filename + " exists." );
137  }
138  }
139  return "WHAT THE @#$%!"; // Code can never reach here.
140 }
141 
142 
143 /// @brief Find a path to a file.
144 ///
145 /// Try various combinations to locate the specific file being requested by the user.
146 /// (inspired by core::scoring::ScoreFunction::find_weights_file())
147 ///
148 /// @athor Labonte <JWLabonte@jhu.edu>
149 std::string
150 find_database_path( std::string dir, std::string filename, std::string ext)
151 {
152  using namespace utility::io;
153 
154  std::string const & path( basic::database::full_name( dir ) );
155 
156  izstream potential_file( filename );
157  if ( potential_file.good() ) {
158  return filename;
159  } else {
160  izstream potential_file( filename + ext ); // Perhaps the user didn't use the .table extension.
161  if ( potential_file.good() ) {
162  return filename + ext;
163  } else {
164  izstream potential_file( path + filename); // Let's assume it's in the database in the usual spot.
165  if ( potential_file.good() ) {
166  return path + filename;
167  } else {
168  izstream potential_file( path + filename + ext ); // last try
169  if ( potential_file.good() ) {
170  return path + filename + ext;
171  } else {
172  utility_exit_with_message( "Unable to open file. Neither ./" + filename +
173  " nor " + "./" + filename + ext +
174  " nor " + path + filename +
175  " nor " + path + filename + ext + " exists." );
176  }
177  }
178  }
179  }
180  return "WHAT THE @#$%!"; // Code can never reach here.
181 }
182 
183 
184 /// @brief Does cache file (absolute path) exist?
185 /// if dir_only is true, will return true if the cache file could be created.
186 bool
188  std::string const & cache_file,
189  bool dir_only
190 ) {
191  if ( ! dir_only ) {
192  bool exists = (utility::file::file_exists(cache_file) || utility::file::file_exists(cache_file + ".gz") );
193  if ( TR.Debug.visible() && exists ) {
194  TR.Debug << "Using '" << cache_file << "' as the cached file." << std::endl;
195  }
196  return exists;
197  } else {
198  // Does the directory exist/can it be created?
199  std::string cache_dir = utility::file::FileName( cache_file ).path();
200  if ( ! utility::file::create_directory_recursive( cache_dir ) ) {
201  return false;
202  }
203  // Can we write a file in the directory?
204  // Note that we *don't* want to try actually writing the actual file, due to race conditions.
205  std::string tempfilename( utility::file::create_temp_filename( cache_dir, "writability_check" ) );
206  std::ofstream tempfile( tempfilename.c_str() );
207  bool usable = tempfile.good();
208  tempfile.close();
209  utility::file::file_delete(tempfilename); // Has internal file exist checks.
210  if ( TR.Debug.visible() && usable ) {
211  TR.Debug << "Using '" << cache_dir << "' as a cache directory." << std::endl;
212  }
213  return usable;
214  }
215 }
216 
217 /// @brief Get the (absolute) path to a given cached file.
218 /// If source_file is given, it's the full path to the source database file that's being cached.
219 /// If for_writing is true, will only check that the given file would be creatable.
220 /// Will return an empty string if it can't find a cache file.
221 std::string
223  std::string const & short_name,
224  std::string const & source_file,
225  bool for_writing
226 )
227 {
228  using namespace basic::options;
229  using namespace basic::options::OptionKeys;
230 
231  std::string cache_name;
232 
233  // First try the specified cache directories, if possible.
235  cache_name = std::string(option[ in::path::database_cache_dir ]()) + short_name;
236  if ( find_cache_file( cache_name, for_writing ) ) {
237  return cache_name;
238  }
239  }
240 
241  char const * path = getenv("ROSETTA3_DBCACHE");
242  if ( path && strlen(path) > 0 ) {
243  cache_name = std::string(path) + "/" + short_name;
244  if ( find_cache_file( cache_name, for_writing ) ) {
245  return cache_name;
246  }
247  }
248 
249  // Then try the database directory
250  // We don't iterate through all database directories, because in a multiple directory situation we don't want
251  // to put the cache for one database into a different one
252  if ( source_file.size() != 0 ) {
253  cache_name = utility::file::FileName( source_file ).path() + utility::file::FileName( short_name ).bare_name();
254  if ( find_cache_file( cache_name, for_writing ) ) {
255  return cache_name;
256  }
257  }
258 
259  // No luck? Then fall back to the user's home directories.
260  char const * homedir = getenv("XDG_CONFIG_HOME");
261  if ( ! homedir || strlen(homedir) == 0 ) {
262  homedir = getenv("HOME");
263  }
264 #if defined(MAC) || defined(__APPLE__) || defined(__OSX__) || defined(linux) || defined(__linux__) || defined(__linux)
265  if ( ! homedir || strlen(homedir) == 0 ) {
266  passwd const * unix_pwd( getpwuid(getuid()) );
267  if ( unix_pwd ) {
268  homedir = unix_pwd->pw_dir;
269  }
270  }
271 #endif
272 
273  if ( homedir && strlen(homedir) > 0 ) {
274  cache_name = std::string(homedir) + "/.rosetta/database/" + short_name;
275  if ( find_cache_file( cache_name, for_writing ) ) {
276  return cache_name;
277  }
278  }
279 
280  return "";
281 }
282 
283 } // namespace database
284 } // namespace basic
#define utility_exit_with_message(m)
Exit with file + line + message.
Definition: exit.hh:47
#define THREAD_LOCAL
bool good() const
Good?
Definition: izstream.hh:572
std::string full_name(std::string const &db_file, bool warn)
Full-path database file name.
Definition: open.cc:95
dictionary size
Definition: amino_acids.py:44
static THREAD_LOCAL basic::Tracer TR("basic.io.database")
std::string find_database_path(std::string dir, std::string filename)
Find a path to a file.
Definition: open.cc:120
bool visible() const
Definition: Tracer.hh:240
Platform independent operations on files (except I/O)
FileName & path(std::string const &path_a)
Path assignment.
Definition: FileName.cc:46
bool find_cache_file(std::string const &cache_file, bool dir_only)
Does cache file (absolute path) exist? if dir_only is true, will return true if the cache file could ...
Definition: open.cc:187
std::string bare_name() const
Bare name (without volume or path or version)
Definition: FileName.hh:398
File name class supporting Windows and UN*X/Linux format names.
Definition: FileName.hh:37
Tracer & T(std::string const &channel, TracerPriority priority)
T is special function for assign tracer property on the static object.
Definition: Tracer.cc:573
common derived classes for thrown exceptions
std::string full_cache_name(std::string const &short_name, std::string const &source_file, bool for_writing)
Get the (absolute) path to a given cached file. If source_file is given, it's the full path to the so...
Definition: open.cc:222
tuple database
void close()
Close the ifstream and reset the state.
Definition: izstream.hh:219
Functions for opening database files.
Tracer & Error(TracerPriority priority=t_error)
Predefined Error tracer.
Definition: Tracer.hh:395
bool open(utility::io::izstream &db_stream, std::string const &db_file, bool warn)
Open a database file on a provided stream.
Definition: open.cc:55
Tracer IO system.
izstream: Input file stream wrapper for uncompressed and compressed files
Definition: izstream.hh:44
Input file stream wrapper for uncompressed and compressed files.
void clear()
Clear the stream(s)
Definition: izstream.hh:202
basic::options::OptionKeys collection
bool create_directory_recursive(std::string const &dir_path)
Create a directory and its parent directories if they doesn't already exist.
rule< Scanner, options_closure::context_t > options
Definition: Tag.cc:377
PathVectorOptionKey const path
PathOptionKey const database_cache_dir("in:path:database_cache_dir")
int file_delete(std::string const &path)
Delete File.
Tracer & Warning(TracerPriority priority=t_warning)
Predefined Warning tracer.
Definition: Tracer.hh:398
Path name class supporting Windows and UN*X/Linux format names.
vector1: std::vector with 1-based indexing
Class for handling user debug/warnings/errors. Use instance of this class instead of 'std::cout' for ...
Definition: Tracer.hh:134
bool file_exists(std::string const &path)
Does File Exist?
rule< Scanner, string_closure::context_t > name
Definition: Tag.cc:376
PathVectorOptionKey const database("in:path:database")
Program options global and initialization function.
std::string create_temp_filename(std::string const &dir, std::string const &prefix)
Find an unused random tempfile name with a given prefix (which may include a directory) ...
void open(std::string const &filename_a, std::ios_base::openmode open_mode=std::ios_base::in)
Open a file.
Definition: izstream.cc:34
TracerProxy Debug
Definition: Tracer.hh:262
rule< Scanner, option_closure::context_t > option
Definition: Tag.cc:378