source: rrlib_util/sFileIOUtils.cpp @ 94:5ab465115d30

Last change on this file since 94:5ab465115d30 was 94:5ab465115d30, checked in by Max Reichardt <mreichardt@…>, 7 years ago

Fix in sFileIOUtils::HostToIp functions: if host name cannot be resolved, program no longer terminates with a failed assertion

File size: 29.3 KB
Line 
1//
2// You received this file as part of RRLib
3// Robotics Research Library
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License
9// as published by the Free Software Foundation; either version 2
10// of the License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20//
21//----------------------------------------------------------------------
22/*!\file    rrlib/util/sFileIOUtils.cpp
23 *
24 * \author  Bernd Helge Schaefer
25 * \author  Jens Wettach
26 * \author  Tim Braun
27 *
28 * \date    2005-11-15
29 *
30 */
31//----------------------------------------------------------------------
32// Includes
33//----------------------------------------------------------------------
34#include "rrlib/util/sFileIOUtils.h"
35
36#include <algorithm>
37#include <iostream>
38#include <fstream>
39#include <sstream>
40#include <iterator>
41
42extern "C"
43{
44#include <netdb.h> // struct hostent, gethostbyname
45#include <unistd.h>
46#include <dirent.h>
47#include <wordexp.h>
48}
49
50#include "rrlib/util/sStringUtils.h"
51#include "rrlib/util/join.h"
52#include "rrlib/logging/messages.h"
53
54//----------------------------------------------------------------------
55// Debug
56//----------------------------------------------------------------------
57#include <cassert>
58
59//----------------------------------------------------------------------
60// Namespace usage
61//----------------------------------------------------------------------
62using namespace std;
63
64//----------------------------------------------------------------------
65// Namespace declaration
66//----------------------------------------------------------------------
67namespace rrlib
68{
69namespace util
70{
71
72//----------------------------------------------------------------------
73// initialization of static class vars
74//----------------------------------------------------------------------
75std::string sFileIOUtils::cached_local_host = "";
76std::map<std::string, std::string> sFileIOUtils::host_name_to_ip_cache = std::map<std::string, std::string>();
77std::map<std::string, std::string> sFileIOUtils::resource_cache = std::map<std::string, std::string>();
78
79
80
81bool sFileIOUtils::GetAllFilesInDirectory(std::string dir, std::vector<std::string> &files)
82{
83  DIR *dp;
84  struct dirent *dirp;
85  if ((dp  = opendir(dir.c_str())) == NULL)
86  {
87    return false;
88  }
89
90  while ((dirp = readdir(dp)) != NULL)
91  {
92    files.push_back(std::string(dirp->d_name));
93    //std::cout << "Found: " << dirp->d_name << std::endl;
94  }
95
96  closedir(dp);
97  return true;
98}
99
100
101
102//----------------------------------------------------------------------
103// class sFileIOUtils::GetCurrentDirectory()
104//----------------------------------------------------------------------
105std::string sFileIOUtils::GetCurrentDirectory()
106{
107  char *temp_path(NULL);
108  // POSIX.1 extension allocates buffer for path if given buffer is NULL and size = 0
109  temp_path = getcwd(temp_path, 0);
110  std::string path(temp_path);
111  path += "/";
112  free(temp_path);
113  return path;
114}
115
116//----------------------------------------------------------------------
117// class sFileIOUtils::ChangeCurrentDirectory()
118//----------------------------------------------------------------------
119int sFileIOUtils::ChangeCurrentDirectory(const std::string& dir)
120{
121  return chdir(dir.c_str());
122}
123
124//----------------------------------------------------------------------
125// class sFileIOUtils::CreateDirectory()
126//----------------------------------------------------------------------
127bool sFileIOUtils::CreateDirectory(const std::string& path)    //throw(runtime_error)
128{
129  std::stringstream sys_call;
130  sys_call << "mkdir -p " << path;
131
132  if (system(sys_call.str().c_str()) == -1)
133  {
134    RRLIB_LOG_PRINTF(USER, "sFileIOUtils>> Error creating dir: '%s'\n", path.c_str());
135//     std::stringstream error_msg;
136//     error_msg << "sFileIOUtils>> Error creating Dir:\n"
137//     << path << endl;
138    //throw runtime_error(error_msg.str());
139    return false;
140  }
141  else
142  {
143//     RRLIB_LOG_PRINTF(USER, "sFileIOUtils>> Directory: '%s' successfully created.\n", path.c_str());
144    return true;
145  }
146}
147
148//----------------------------------------------------------------------
149// class sFileIOUtils::CreateTempfile()
150//----------------------------------------------------------------------
151std::string sFileIOUtils::CreateTempfile()
152{
153  FILE * pipe = popen("mktemp", "r");
154  char buf[ 1024 ];
155  if (fgets(buf, sizeof(buf), pipe) == 0)
156  {
157    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::CreateTempfile() >> Error creating temp file!\n");
158    exit(EXIT_FAILURE);
159  }
160  std::string tempfile = buf;
161  tempfile = tempfile.substr(0, tempfile.find("\n"));
162  pclose(pipe);
163  return tempfile;
164} // CreateTempfile()
165
166//----------------------------------------------------------------------
167// class sFileIOUtils::DeleteFile()
168//----------------------------------------------------------------------
169void sFileIOUtils::DeleteFile(const std::string& filename)
170{
171  unlink(filename.c_str());
172} // DeleteFile()
173
174//----------------------------------------------------------------------
175// class sFileIOUtils::CompressFile()
176//----------------------------------------------------------------------
177void sFileIOUtils::CompressFile(const std::string& input_filename, std::string& output_filename)
178{
179  if (!sStringUtils::EndsWith(output_filename, ".gz"))
180    output_filename += ".gz";
181  std::stringstream cmd;
182  cmd << "gzip -c " << input_filename << " > " << output_filename;
183  if (system(cmd.str().c_str()) != 0)
184  {
185    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils>> Execution of command '%s' failed!\n", cmd.str().c_str());
186    exit(EXIT_FAILURE);
187  }
188} // CompressFile()
189
190//----------------------------------------------------------------------
191// class sFileIOUtils::DecompressFile()
192//----------------------------------------------------------------------
193void sFileIOUtils::DecompressFile(const std::string& input_filename, const std::string& output_filename)
194{
195  assert(sStringUtils::EndsWith(input_filename, ".gz"));
196  std::stringstream cmd;
197  cmd << "gunzip -c " << input_filename << " > " << output_filename;
198  if (system(cmd.str().c_str()) != 0)
199  {
200    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils>> Execution of command '%s' failed!\n", cmd.str().c_str());
201    exit(EXIT_FAILURE);
202  }
203} // DecompressFile()
204
205//----------------------------------------------------------------------
206// class sFileIOUtils::FileExists()
207//----------------------------------------------------------------------
208bool sFileIOUtils::FileExists(const std::string &filename)
209{
210  // catch empty file
211  if (filename == "")
212  {
213    return false;
214  }
215
216  // test if file exists
217  FILE* file = fopen(filename.c_str(), "rb");
218  if (file == 0)
219  {
220    return false;
221  }
222  fclose(file);
223
224  return true;
225}
226
227
228//----------------------------------------------------------------------
229// class sFileIOUtils::ShellExpandFilename()
230//----------------------------------------------------------------------
231bool sFileIOUtils::ShellExpandFilename(std::string &file_name)
232{
233  return ShellExpandFilename(file_name, file_name);
234} // ShellExpandFilename()
235
236//----------------------------------------------------------------------
237// class sFileIOUtils::ShellExpandFilename()
238//----------------------------------------------------------------------
239std::string sFileIOUtils::ShellExpandFilename(const std::string &file_name)
240{
241  std::string result("");
242  if (ShellExpandFilename(result, file_name))
243    return result;
244  else
245    return "";
246} // ShellExpandFilename()
247
248
249//----------------------------------------------------------------------
250// class sFileIOUtils::ShellExpandFilename()
251//----------------------------------------------------------------------
252bool sFileIOUtils::ShellExpandFilename(std::string &result, const std::string &file_name)
253{
254  //result = "";  //in case &result == &file_name, then it causes trouble.
255  wordexp_t expansion;
256  int error = wordexp(file_name.c_str(), &expansion, WRDE_SHOWERR | WRDE_UNDEF);
257  if (error)
258  {
259    const char *error_msg = 0;
260    switch (error)
261    {
262    case WRDE_BADCHAR:
263      error_msg = "Illegal occurrence of newline or one of |, &, ;, <, >, (, ), {, }";
264      break;
265    case WRDE_BADVAL:
266      error_msg = "An undefined shell variable was referenced";
267      break;
268    case WRDE_NOSPACE:
269      error_msg = "Out of memory";
270      break;
271    case WRDE_SYNTAX:
272      error_msg = "Shell syntax error, such as unbalanced parentheses or unmatched quotes";
273      break;
274    default:
275      error_msg = "Unknown error";
276    }
277    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::%s >> Could not expand '%s': %s!\n", __FUNCTION__, file_name.c_str(), error_msg);
278    return false;
279  }
280
281  std::stringstream stream;
282  stream << util::Join(expansion.we_wordv + expansion.we_offs, expansion.we_wordv + expansion.we_offs + expansion.we_wordc, " ");
283  wordfree(&expansion);
284
285  result = stream.str();
286
287  return true;
288} // ShellExpandFilename()
289
290//----------------------------------------------------------------------
291// class sFileIOUtils::SplitFullQualifiedFilename()
292//----------------------------------------------------------------------
293void sFileIOUtils::SplitFullQualifiedFilename(const std::string& complete_name, std::string& file_dir, std::string& file_base, std::string& file_ext)
294{
295
296  std::string::size_type pos_slash = complete_name.find_last_of("/");
297  std::string::size_type pos_name = pos_slash + 1;
298
299  if (pos_slash == std::string::npos)
300  {
301    // no slash found
302    file_dir = "./";
303    pos_name = 0;
304    pos_slash = 0;
305  }
306  else
307  {
308    file_dir = complete_name.substr(0, pos_slash);
309  }
310
311  //    cerr << "pos_slash: " << pos_slash << endl;
312  std::string::size_type pos_dot = complete_name.find_last_of(".");
313  if (pos_dot == std::string::npos || pos_dot < pos_slash)
314  {
315    // no dot found or dot in directory
316    file_base = complete_name.substr(pos_name);
317    file_ext = "";
318  }
319  else
320  {
321    file_base = complete_name.substr(pos_name, pos_dot - pos_name);
322    file_ext = complete_name.substr(pos_dot);
323  }
324
325} // SplitFullQualifiedFilename()
326
327
328
329//----------------------------------------------------------------------
330// class sFileIOUtils::GetHostName()
331//----------------------------------------------------------------------
332std::string sFileIOUtils::GetHostName(bool fqdn)
333{
334  //RRLIB_LOG_PRINTF(USER, "sFileIOUtils::GetHostName() >>> started\n");
335  std::string cmd = fqdn ? "hostname -f" : "hostname";
336  FILE * pipe = popen(cmd.c_str(), "r");
337  char buf[ 1024 ];
338  if (fgets(buf, sizeof(buf), pipe) == 0)
339  {
340    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::GetHostName(bool fqdn) >> Error querying host name!\n");
341    exit(EXIT_FAILURE);
342  }
343  pclose(pipe);
344  std::string name(buf);
345  sStringUtils::TrimWhitespace(name);
346  //boost::trim(name);
347  //RRLIB_LOG_PRINTF(USER, "sFileIOUtils::GetHostName() >>> finished with name <%s>\n", name.c_str());
348  return name;
349} // GetHostName()
350
351//----------------------------------------------------------------------
352// class sFileIOUtils::HostToIpViaGetHostByName()
353//----------------------------------------------------------------------
354struct ::in_addr sFileIOUtils::HostToIpViaGetHostByName(const std::string& name)
355{
356  struct in_addr address;
357  address.s_addr = 0;
358  struct hostent *host_ent = gethostbyname(name.c_str());       //alternative (from kernel/tTCPSocket): GetHostByName( name );
359  if (host_ent)
360  {
361    address = * ((struct in_addr *) host_ent->h_addr_list[ 0 ]);
362    RRLIB_LOG_PRINTF(USER, "ip address of host <%s> = <%s>\n", name.c_str(), inet_ntoa(address));
363  }
364  else
365  {
366    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::GetIpAddressOfHost() >>> could not get ip address of host <%s>\n", name.c_str());
367  }
368  return address;
369} //HostToIpViaGetHostByName()
370
371
372//----------------------------------------------------------------------
373// class sFileIOUtils::HostToIpViaNslookup()
374//----------------------------------------------------------------------
375struct in_addr sFileIOUtils::HostToIpViaNslookup(const std::string & name)
376{
377  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIpViaNslookup() >>> started with host <%s>\n", name.c_str());
378  struct in_addr address;
379  address.s_addr = 0;
380
381  std::stringstream command;
382  command << "nslookup \"" << name << "\"";
383  RRLIB_LOG_PRINTF(USER, "command = <%s>\n", command.str().c_str());
384  FILE * pipe = popen(command.str().c_str(), "r");
385  if (!pipe)
386  {
387    perror("error\n");
388    return address;
389  }
390  std::stringstream result;
391  char buf[ 512 ];
392  while (fgets(buf, 512, pipe) != NULL)
393  {
394    result << buf;
395  }
396  pclose(pipe);
397  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIpViaNslookup() >>> host = <%s> , result = <%s> \n", name.c_str(), result.str().c_str());
398
399  std::string result_str(result.str());
400  std::string search_token("Name:");
401  std::string::size_type pos = result_str.find(search_token);
402  if (pos == std::string::npos)
403  {
404    RRLIB_LOG_PRINTF(ERROR, "Could not find token <%s> in nslookup result ... returning <%s> \n", search_token.c_str(), inet_ntoa(address));
405    return address;
406  }
407  result_str.erase(0, pos + search_token.length());
408  RRLIB_LOG_PRINTF(USER, "pos = %zd\n", pos);
409
410  search_token = "Address:";
411  pos = result_str.find(search_token);
412  if (pos == std::string::npos)
413  {
414    RRLIB_LOG_PRINTF(ERROR, "Could not find token <%s> in nslookup result ... returning <%s> \n", search_token.c_str(), inet_ntoa(address));
415    return address;
416  }
417  RRLIB_LOG_PRINTF(USER, "pos = %zd\n", pos);
418
419  std::string found_name(result_str.substr(0, pos));
420  sStringUtils::TrimWhitespace(found_name);
421  //boost::trim(found_name);
422  std::string ip(result_str.substr(pos + search_token.length()));
423  sStringUtils::TrimWhitespace(ip);
424  //boost::trim(ip);
425
426  RRLIB_LOG_PRINTF(USER, "found_name <%s> , name <%s> \n", found_name.c_str(), name.c_str());
427
428  if (found_name != name)
429  {
430    RRLIB_LOG_PRINTF(ERROR, "nslookup failed .... returning <%s> \n", inet_ntoa(address));
431    return address;
432  }
433  RRLIB_LOG_PRINTF(USER, "found_name <%s> , ip <%s> \n", found_name.c_str(), ip.c_str());
434
435  inet_aton(ip.c_str(), &address);
436
437  //return ip.c_str();
438  return address;
439} // HostToIpViaNslookup()
440
441
442//----------------------------------------------------------------------
443// class sFileIOUtils::HostToIpViaHost()
444//----------------------------------------------------------------------
445struct in_addr sFileIOUtils::HostToIpViaHost(const std::string & name)
446{
447  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIpViaHost() >>> started with host <%s>\n", name.c_str());
448  struct in_addr address;
449  address.s_addr = 0;
450
451  std::stringstream command;
452  command << "host -t A \"" << name << "\"";
453  RRLIB_LOG_PRINTF(USER, "command = <%s>\n", command.str().c_str());
454  FILE * pipe = popen(command.str().c_str(), "r");
455  if (!pipe)
456  {
457    perror("error\n");
458    return address;
459  }
460  std::stringstream result;
461  char buf[ 512 ];
462  while (fgets(buf, 512, pipe) != NULL)
463  {
464    result << buf;
465  }
466  pclose(pipe);
467  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIpViaHost() >>> host = <%s> , result = <%s> \n", name.c_str(), result.str().c_str());
468
469  std::string result_str(result.str());
470  std::vector<std::string> tokens;
471  sStringUtils::Tokenize(result_str, tokens, " \t");
472
473  for_each(tokens.begin(), tokens.end(), sStringUtils::Trim<std::string>());
474  RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::HostToIpViaHost() >>> got %d tokens:\n", tokens.size());
475  RRLIB_LOG_PRINT(DEBUG_VERBOSE_1, Join(tokens, "\n"));
476  if (tokens.size() != 4)
477  {
478    RRLIB_LOG_PRINT(WARNING, "Could not determine IP for host name ", name);
479    return address;
480  }
481
482  assert(tokens.size() == 4);
483  RRLIB_LOG_PRINTF(USER, "found_name <%s> , ip <%s> \n", tokens[0].c_str(), tokens[3].c_str());
484
485  inet_aton(tokens[3].c_str(), &address);
486  return address;
487} // HostToIpViaHost()
488
489//----------------------------------------------------------------------
490// class sFileIOUtils::HostToIpViaHostsFile()
491//----------------------------------------------------------------------
492struct in_addr sFileIOUtils::HostToIpViaHostsFile(const std::string & name)
493{
494  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIpViaHostsFile() >>> started with host <%s>\n", name.c_str());
495  struct in_addr address;
496  address.s_addr = 0;
497
498  ifstream hosts_file("/etc/hosts");
499
500  char line[ 1024 ];
501  std::string line_str, ip_address;
502  std::vector<std::string> tokens;
503  bool found(false);
504  while (!hosts_file.eof() && !found)
505  {
506    hosts_file.getline(line, 1024);
507    line_str = std::string(line);
508    if (line_str.length() > 0 && line_str.find("#") == std::string::npos)
509    {
510      tokens.clear();
511      sStringUtils::Tokenize(line_str, tokens, " \t");
512
513      if (find(tokens.begin(), tokens.end(), name) != tokens.end())
514      {
515        for (std::vector<std::string>::const_iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
516        {
517          if (inet_aton(iter->c_str(), &address))
518          {
519            ip_address = *iter;
520            RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIpViaHostsFile() >>> got ip <%s> of host <%s> from hosts file\n", ip_address.c_str(), name.c_str());
521            found = true;
522            break;
523          }
524        }
525      }
526    }
527  }
528  hosts_file.close();
529  return address;
530} // HostToIpViaHostsFile()
531
532
533//----------------------------------------------------------------------
534// class sFileIOUtils::HostToIp()
535//----------------------------------------------------------------------
536struct in_addr sFileIOUtils::HostToIp(const std::string & name)
537{
538  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIp() >>> started with host <%s>\n", name.c_str());
539
540  struct in_addr address;
541  address.s_addr = 0;
542
543  if ((address = sFileIOUtils::HostToIpViaHostsFile(name)).s_addr != 0)
544  {
545    RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIp() >>> got ip <%s> of host <%s> from hosts_file\n", inet_ntoa(address), name.c_str());
546  }
547  else if ((address = sFileIOUtils::HostToIpViaHost(name)).s_addr != 0)
548  {
549    RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIp() >>> got ip <%s> of host <%s> via <host -t A>\n", inet_ntoa(address), name.c_str());
550  }
551  else if ((address = sFileIOUtils::HostToIpViaNslookup(name)).s_addr != 0)
552  {
553    RRLIB_LOG_PRINTF(USER, "sFileIOUtils::HostToIp() >>> got ip <%s> of host <%s> via <nslookup>\n", inet_ntoa(address), name.c_str());
554  }
555  else
556  {
557    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::HostToIp() >>> could not get ip of host <%s>\n", name.c_str());
558  }
559
560  return address;
561} // HostToIp()
562
563
564//----------------------------------------------------------------------
565// class sFileIOUtils::RSyncFile()
566//----------------------------------------------------------------------
567int sFileIOUtils::RSyncFile(const std::string& source_host_name, const std::string& source_host_ip_address, const std::string& source_directory, const std::string& source_file_name, const std::string& target_directory, const std::string &optional_rsync_flags)
568{
569  std::stringstream rsync_command;
570  rsync_command << "rsync -av" << optional_rsync_flags << " ";
571  if (source_host_ip_address == "")
572  {
573    rsync_command << inet_ntoa(sFileIOUtils::HostToIp(source_host_name));
574  }
575  else
576  {
577    rsync_command << source_host_ip_address;
578  }
579  rsync_command << ":"
580                << source_directory
581                << source_file_name
582                << " "
583                << target_directory;
584
585  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::RSyncFile() >>> executing <%s> ...\n", rsync_command.str().c_str());
586  int ret = system(rsync_command.str().c_str());
587  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::RSyncFile() >>> ... done.\n");
588
589  RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::RSyncFile() >>> finished with result %d\n", ret);
590  return ret;
591} // RSyncFile()
592
593
594//----------------------------------------------------------------------
595// class sFileIOUtils::RSyncFiles()
596//----------------------------------------------------------------------
597int sFileIOUtils::RSyncFiles(const std::string& source_host_name, const std::string& source_host_ip_address, const std::string& source_directory, const std::vector<std::string>& source_file_names, const std::string& target_directory, const std::string &optional_rsync_flags)
598{
599  std::string file_list_file_name(target_directory + "sfileioutils_rsyncfiles.txt");
600  ofstream tmp_file_list(file_list_file_name.c_str());
601  std::ostream_iterator<std::string> tmp_file_list_iterator(tmp_file_list, "\n");
602  unique_copy(source_file_names.begin(), source_file_names.end(), tmp_file_list_iterator);
603  tmp_file_list.close();
604
605  std::stringstream rsync_command;
606  rsync_command << "rsync -avr" << optional_rsync_flags << " --files-from=" << file_list_file_name << " ";
607  if (source_host_ip_address == "")
608  {
609    rsync_command << inet_ntoa(sFileIOUtils::HostToIp(source_host_name));
610  }
611  else
612  {
613    rsync_command << source_host_ip_address;
614  }
615  rsync_command << ":"
616                << source_directory
617                << " "
618                << target_directory;
619
620  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::RSyncFiles() >>> executing <%s> ...\n", rsync_command.str().c_str());
621  int ret = system(rsync_command.str().c_str());
622  RRLIB_LOG_PRINTF(USER, "sFileIOUtils::RSyncFiles() >>> ... done.\n");
623
624  RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::RSyncFiles() >>> finished with result %d\n", ret);
625  return ret;
626} // RSyncFiles()
627
628
629//----------------------------------------------------------------------
630// class sFileIOUtils::CheckAndGetFile()
631//----------------------------------------------------------------------
632bool sFileIOUtils::CheckAndGetFile(const std::string &file_name, std::string &full_local_file_name, const std::string& resource_repository, const std::string& resource_server, const std::string& local_resource_directory, const std::string& server_resource_directory, bool use_cache)
633{
634  RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::CheckAndGetFile() >>> started with local_resource_directory <%s>, resource_repository <%s>, file_name <%s>, resource_server <%s>, server_resource_directory <%s>\n", local_resource_directory.c_str(), resource_repository.c_str(), file_name.c_str(), resource_server.c_str(), server_resource_directory.c_str());
635
636  //!#####################################################################################################
637  //! step 0: check whether token "resource_repository + filename" is in local cache
638  //!         and thus file is *assumed* to have already been loaded since last clearing of cache
639  //!#####################################################################################################
640  std::map<std::string, std::string>::iterator resource_cache_entry;
641  if (use_cache && (resource_cache_entry = sFileIOUtils::resource_cache.find(resource_repository + file_name)) != sFileIOUtils::resource_cache.end())
642  {
643    full_local_file_name = resource_cache_entry->second;
644    return true;
645  }
646
647
648  //!#####################################################################################################
649  //! step 1: check whether file can be loaded from local host in local directory
650  //!         location of file is: "./ + resource_repository + filename"
651  //!         --> resource_repository is extracted from relative path within given scene description file
652  //!#####################################################################################################
653  full_local_file_name = "./" + resource_repository + file_name;
654
655  RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::CheckAndGetFile() >>> 1. check: trying to load <%s>\n", full_local_file_name.c_str());
656  ifstream try_1(full_local_file_name.c_str());
657  if (try_1)
658  {
659    try_1.close();
660  }
661  else
662  {
663    //!#################################################################################################################
664    //! step 2: check whether file can be loaded from local host in given local_resource_directory
665    //!         location of file is: "local_resource_directory + resource_repository + filename"
666    //!         --> resource_repository is extracted from relative path within given scene description file
667    //!#################################################################################################################
668
669    // replace possible environment variables in local_resource_directory by corresponding values
670    std::string expanded_local_resource_directory;
671    if (!sFileIOUtils::ShellExpandFilename(expanded_local_resource_directory, local_resource_directory + "/"))
672    {
673      RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::%s >> Could not expand local resource directory!\n", __FUNCTION__);
674      return false;
675    }
676    full_local_file_name = (expanded_local_resource_directory + resource_repository + file_name);
677
678    RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::CheckAndGetFile() >>> 2. check: trying to load <%s>\n", full_local_file_name.c_str());
679    ifstream try_2(full_local_file_name.c_str());
680    if (try_2)
681    {
682      try_2.close();
683    }
684    else
685    {
686      //!#################################################################################################################
687      //! step 3: check whether file can be loaded from resource server in given server_resource_directory
688      //!         location of file is: "server_resource_directory + resource_repository + filename"
689      //!#################################################################################################################
690
691      // get local host name
692      std::string local_host;
693      if (use_cache && sFileIOUtils::cached_local_host.length() > 0)
694      {
695        local_host = sFileIOUtils::cached_local_host;
696        RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::CheckAndGetFile() >>> retrieved local_host <%s> from cache\n", local_host.c_str());
697      }
698      else
699      {
700        local_host = sFileIOUtils::cached_local_host = sFileIOUtils::GetHostName();
701      }
702
703      // get server ip address
704      std::string server(resource_server);
705      std::string server_ip_address;
706      if (server != "")
707      {
708        // retrieve ip address of optional resource server
709        std::map<std::string, std::string>::iterator pos;
710        if (use_cache && ((pos = sFileIOUtils::host_name_to_ip_cache.find(server)) != sFileIOUtils::host_name_to_ip_cache.end()))
711        {
712          server_ip_address = pos->second;
713          RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::CheckAndGetFile() >>> retrieved ip address <%s> of host <%s> from cache\n", server_ip_address.c_str(), server.c_str());
714        }
715        else
716        {
717          server_ip_address = inet_ntoa(sFileIOUtils::HostToIp(server));
718          RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::CheckAndGetFile() >>> got ip address <%s> of host <%s>\n", server_ip_address.c_str(), server.c_str());
719
720          if (server_ip_address == "0.0.0.0")
721          {
722            RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::constructor >>> zero ip address ... clearing server\n");
723            server = "";
724          }
725          else
726          {
727            sFileIOUtils::host_name_to_ip_cache[ server ] = server_ip_address;
728          }
729        }
730      }
731
732      // start check
733      if (server != "")   //&& server != local_host)
734      {
735        RRLIB_LOG_PRINTF(DEBUG_VERBOSE_1, "sFileIOUtils::CheckAndGetFile() >>> 3. check: trying to rsync <%s:%s> to <%s> \n", server_ip_address.c_str(), (server_resource_directory + resource_repository + file_name).c_str(), expanded_local_resource_directory.c_str());
736
737        // rsync from <resource_server:server_resource_directory + resource_repository>
738        //       to <local_resource_directory> on local host
739
740        if (sFileIOUtils::RSyncFile("", server_ip_address, server_resource_directory + "/./" + resource_repository, file_name, expanded_local_resource_directory, "R") != 0)
741        {
742          RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::CheckAndGetFile() >>> could not rsync file <%s> from server <%s> at <%s> ... skipping\n", file_name.c_str(), server.c_str(), (server_resource_directory + resource_repository).c_str());
743          return false;
744        }
745        full_local_file_name = (expanded_local_resource_directory + resource_repository + file_name);
746      }
747      else
748      {
749        RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::CheckAndGetFile() >>> could neither load <%s> locally nor from resource server ... skipping\n", file_name.c_str());
750        return false;
751      }
752    }
753  }
754
755  //! ------------------------------- final check just to be sure that requested file is available --------------------
756  ifstream try_3(full_local_file_name.c_str());
757  if (!try_3)
758  {
759    RRLIB_LOG_PRINTF(ERROR, "sFileIOUtils::CheckAndGetFile() >>> final check failed: could not load <%s> ... skipping\n", full_local_file_name.c_str());
760    return false;
761  }
762  else
763  {
764    try_3.close();
765  }
766  sFileIOUtils::resource_cache[ resource_repository + file_name ] = full_local_file_name;
767  return true;
768} // CheckAndGetFile()
769
770
771//----------------------------------------------------------------------
772// class sFileIOUtils::ClearCaches()
773//----------------------------------------------------------------------
774void sFileIOUtils::ClearCaches()
775{
776  sFileIOUtils::cached_local_host = "";
777  sFileIOUtils::host_name_to_ip_cache.clear();
778} // ClearCaches()
779
780
781//----------------------------------------------------------------------
782// class sFileIOUtils::ClearResourceCache()
783//----------------------------------------------------------------------
784void sFileIOUtils::ClearResourceCache()
785{
786  sFileIOUtils::resource_cache.clear();
787} // ClearResourceCache()
788
789//----------------------------------------------------------------------
790// End of namespace declaration
791//----------------------------------------------------------------------
792}
793}
Note: See TracBrowser for help on using the repository browser.