tensor-0.1.0
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
data_file.cc
1 // -*- mode: c++; fill-column: 80; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 /*
3  Copyright (c) 2013 Juan Jose Garcia Ripoll
4 
5  Tensor is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published
7  by the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Library General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/file.h>
23 #include <fcntl.h>
24 #include <tensor/config.h>
25 #include <tensor/sdf.h>
26 #include <errno.h>
27 #include <unistd.h>
28 
29 namespace sdf {
30 
31 #ifdef TENSOR_BIGENDIAN
32 const enum DataFile::endianness DataFile::endian = BIG_ENDIAN_FILE;
33 #else
34 const enum DataFile::endianness DataFile::endian = LITTLE_ENDIAN_FILE;
35 #endif
36 
37 /* Try to get lock. Return its file descriptor or -1 if failed.
38  */
39 static int get_lock(char const *lockName, bool wait)
40 {
41  int fd;
42  do {
43  mode_t m = umask(0);
44  fd = open(lockName, O_RDWR|O_CREAT, 0666);
45  umask(m);
46  if( fd >= 0 && flock( fd, LOCK_EX | LOCK_NB ) < 0 )
47  {
48  if (errno == ENOTSUP) {
49  std::cout << "Locking not supported. We assume you know what you are doing.\n";
50  return fd;
51  }
52  close(fd);
53  fd = -1;
54  }
55  if (fd > 0 || !wait)
56  return fd;
57  sleep(1);
58  } while (1);
59 }
60 
61 /* Release the lock obtained with tryGetLock( lockName ).
62  */
63 static void giveup_lock(int fd, char const *lockName)
64 {
65  if( fd < 0 )
66  return;
67  unlink(lockName);
68  close(fd);
69 }
70 
71 const size_t DataFile::var_name_size;
72 
73 DataFile::DataFile(const std::string &a_filename, int flags) :
74  _flags(flags),
75  _actual_filename(a_filename),
76  _filename(_actual_filename),
77  _lock_filename(_actual_filename + ".lck"),
78  _lock((flags == SDF_SHARED) ? get_lock(_lock_filename.c_str(), true) : 0),
79  _open(true)
80 {
81  switch (flags) {
82  case SDF_OVERWRITE:
83  if (!delete_file(_actual_filename)) {
84  std::cerr << "Cannot overwrite file " << _actual_filename << std::endl;
85  abort();
86  }
87  break;
88  case SDF_SHARED:
89  break;
90  case SDF_PARANOID:
91  _actual_filename = _actual_filename + ".tmp";
92  delete_file(_actual_filename);
93  break;
94  default:
95  std::cerr << "Unrecognized DataFile mode " << flags << std::endl;
96  abort();
97  }
98 }
99 
100 DataFile::~DataFile()
101 {
102  close();
103 }
104 
105 void
106 DataFile::close()
107 {
108  if (is_open()) {
109  _open = false;
110  switch (_flags) {
111  case SDF_SHARED:
112  if (is_locked()) {
113  giveup_lock(_lock, _lock_filename.c_str());
114  }
115  break;
116  case SDF_PARANOID:
117  if (file_exists(_actual_filename))
118  rename_file(_actual_filename, _filename);
119  }
120  }
121 }
122 
123 const char *
124 DataFile::tag_to_name(size_t tag)
125 {
126  static const char *names[] = {
127  "RTensor", "CTensor", "Real MPS", "Complex MPS"
128  };
129 
130  if (tag > 4 /* || tag < 0 */) {
131  std::cerr << "Not a valid tag code, " << tag << " found in " << _filename;
132  }
133  return names[tag];
134 }
135 
136 }
137