resource_internal.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #include "resource_internal.hpp"
27 #include "casadi_misc.hpp"
28 #include "archiver_impl.hpp"
29 
30 #include "filesystem_impl.hpp"
31 
32 
33 namespace casadi {
34 
35 
37  serialize_mode_ = "link";
38 }
39 
40 DirResource::DirResource(const std::string& path)
41  : ResourceInternal(),
42  path_(path) {
43  path_ = path;
44 }
45 
46 void DirResource::disp(std::ostream& stream, bool more) const {
47  stream << "DirResource(\"" << path_ << "\")";
48 }
49 
51 }
52 
53 void ResourceInternal::change_option(const std::string& option_name,
54  const GenericType& option_value) {
55  if (option_name=="serialize_mode") {
56  serialize_mode_ = option_value.to_string();
57  casadi_assert(serialize_mode_=="embed" || serialize_mode_=="link",
58  "Invalid serialization mode: " + serialize_mode_ + ". Pick 'link' or 'embed'.");
59  } else {
60  casadi_error("Option '" + option_name + "' does not exist");
61  }
62 }
63 
65  casadi_assert(Filesystem::is_enabled(),
66  "Unzipping '" + path_ + "' requires advanced filesystem access. Compile CasADi with WITH_GC=ON.\n"
67  "Alternatively, manually unzip it into a direcory, "
68  "and pass this directory name instead of the zip file name.");
69 
70  // Extract filename part of path
71  std::string zip_file = Filesystem::filename(path_);
72 
73  lock_file_ = temporary_file(zip_file + ".", ".lock");
74  dir_ = lock_file_.substr(0, lock_file_.size()-5) + ".unzipped";
75 
76  casadi_assert(Archiver::has_plugin("libzip"),
77  "Unzipping '" + path_ + "' requires libzip. Compile CasADi with WITH_LIBZIP=ON.\n"
78  "Alternatively, manually unzip it into a direcory, "
79  "and pass this directory name instead of the zip file name.");
80 
81 
82  Archiver::getPlugin("libzip").exposed.unpack(path_, dir_);
83 }
84 
86  std::string zip_file = "zip";
87  lock_file_ = temporary_file(zip_file + ".", ".lock");
88  dir_ = lock_file_.substr(0, lock_file_.size()-5) + ".unzipped";
89  casadi_assert(Archiver::has_plugin("libzip"),
90  "Unzipping stream requires libzip. Compile CasADi with WITH_LIBZIP=ON.\n"
91  "Alternatively, save with serialize option set to link. ");
92 
93  Archiver::getPlugin("libzip").exposed.unpack_from_stringstream(blob_, dir_);
94  // rewind
95  blob_.clear();
96  blob_.seekg(0, std::ios::beg);
97 }
98 
99 ZipResource::ZipResource(const std::string& path)
100  : ResourceInternal() {
101  path_ = path;
102  unpack();
103 }
104 
105 ZipMemResource::ZipMemResource(const std::istream& src)
106  : ResourceInternal() {
107  blob_ << src.rdbuf();
108  unpack();
109 }
110 
111 void ZipResource::disp(std::ostream& stream, bool more) const {
112  stream << "ZipResource(\"" << path_ << "\") -> \"" << dir_ << "\"";
113 }
114 
115 void ZipMemResource::disp(std::ostream& stream, bool more) const {
116  stream << "ZipMemResource(blob) -> \"" << dir_ << "\"";
117 }
118 
120  try {
122  } catch (...) {
123  casadi_warning("Error: Cannot remove temporary directory: " + dir_);
124  }
125  try {
126  Filesystem::remove(lock_file_);
127  } catch (...) {
128  casadi_warning("Error: Cannot remove lock file: " + lock_file_);
129  }
130 }
131 
133  try {
135  } catch (...) {
136  casadi_warning("Error: Cannot remove temporary directory: " + dir_);
137  }
138  try {
139  Filesystem::remove(lock_file_);
140  } catch (...) {
141  casadi_warning("Error: Cannot remove lock file: " + lock_file_);
142  }
143 }
144 
146  s.version("ResourceInternal", 1);
147  serialize_type(s);
148  serialize_body(s);
149 }
150 
152  s.pack("ResourceInternal::type", class_name());
153 }
154 
156  s.pack("ResourceInternal::serialize_mode", serialize_mode_);
157 }
158 
160  s.unpack("ResourceInternal::serialize_mode", serialize_mode_);
161  serialize_mode_ = "link";
162 }
163 
165  s.version("ResourceInternal", 1);
166  std::string class_name;
167  s.unpack("ResourceInternal::type", class_name);
168  if (class_name=="DirResource") {
169  return DirResource::deserialize(s);
170  } else if (class_name=="ZipResource") {
171  return ZipResource::deserialize(s);
172  } else if (class_name=="ZipMemResource") {
173  return ZipMemResource::deserialize(s);
174  } else {
175  casadi_error("Cannot deserialize type '" + class_name + "'");
176  }
177 }
178 
180  ZipResource* ret = new ZipResource(s);
181  return ret;
182 }
183 
185 ZipMemResource* ret = new ZipMemResource(s);
186  return ret;
187 }
188 
190  DirResource* ret = new DirResource(s);
191  return ret;
192 }
193 
195  s.version("ZipResource", 1);
196  s.unpack("ZipResource::path", path_);
197  unpack();
198 }
199 
201 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
202  std::lock_guard<std::mutex> lock(mutex_blob_);
203 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
204  s.version("ZipMemResource", 1);
205  s.unpack("ZipMemResource::blob", blob_);
206  unpack();
207 }
208 
210  s.version("DirResource", 1);
211  s.unpack("DirResource::path", path_);
212 }
213 
215  if (serialize_mode_=="embed") {
216  // Decay into ZipMemResource
217  std::string class_name = "ZipMemResource";
218  s.pack("ResourceInternal::type", class_name);
219  } else if (serialize_mode_=="link") {
220  std::string class_name = "ZipResource";
221  s.pack("ResourceInternal::type", class_name);
222  } else {
223  casadi_error("Unknown serialization mode: '" + serialize_mode_+ "'.");
224  }
225 }
226 
228  if (serialize_mode_=="embed") {
229  // Decay into ZipMemResource
230  std::string class_name = "ZipMemResource";
231  s.pack("ResourceInternal::type", class_name);
232  } else if (serialize_mode_=="link") {
233  std::string class_name = "DirResource";
234  s.pack("ResourceInternal::type", class_name);
235  } else {
236  casadi_error("Unknown serialization mode: " + serialize_mode_);
237  }
238 }
239 
240 
243  s.version("ZipResource", 1);
244  if (serialize_mode_=="embed") {
245  // Decay into ZipMemResource
246  std::ifstream binary(path_, std::ios_base::binary);
247  casadi_assert(binary.good(),
248  "Could not open zip file '" + path_ + "'.");
249  s.pack("ZipMemResource::blob", binary);
250  } else {
251  s.pack("ZipResource::path", path_);
252  }
253 }
254 
257  s.version("DirResource", 1);
258  if (serialize_mode_=="embed") {
259  // Decay into ZipMemResource
260  std::stringstream ss;
261  Archiver::getPlugin("libzip").exposed.pack_to_stream(path_, ss);
262  ss.clear();
263  ss.seekg(0, std::ios::beg);
264  s.pack("ZipMemResource::blob", ss);
265  } else {
266  s.pack("DirResource::path", path_);
267  }
268 }
269 
270 
271 
273 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
274  std::lock_guard<std::mutex> lock(mutex_blob_);
275 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
277  s.version("ZipMemResource", 1);
278  s.pack("ZipMemResource::blob", blob_);
279 
280  // rewind
281  blob_.clear();
282  blob_.seekg(0, std::ios::beg);
283 }
284 
285 
286 } // namespace casadi
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
void serialize_type(SerializingStream &s) const override
std::string class_name() const override
Get type name.
DirResource(const std::string &path)
Initialize with a path.
void serialize_body(SerializingStream &s) const override
const std::string & path() const override
Get path for a consumer.
void disp(std::ostream &stream, bool more) const override
Print description.
static ResourceInternal * deserialize(DeserializingStream &s)
static casadi_int remove_all(const std::string &path)
Definition: filesystem.cpp:48
static std::string filename(const std::string &path)
Definition: filesystem.cpp:73
static bool is_enabled()
Definition: filesystem.cpp:83
static bool remove(const std::string &path)
Definition: filesystem.cpp:43
Generic data type, can hold different types such as bool, casadi_int, std::string etc.
std::string to_string() const
Convert to a type.
static bool has_plugin(const std::string &pname, bool verbose=false)
Check if a plugin is available or can be loaded.
static Plugin & getPlugin(const std::string &pname)
Load and get the creator function.
RAII class base for reading from resources.
ResourceInternal()
Initialize with a path.
void serialize(SerializingStream &s) const
virtual void serialize_body(SerializingStream &s) const
void change_option(const std::string &option_name, const GenericType &option_value)
virtual void serialize_type(SerializingStream &s) const
static ResourceInternal * deserialize(DeserializingStream &s)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
virtual std::string class_name() const =0
Readable name of the internal class.
RAII class for reading from a zip held in memory.
void serialize_body(SerializingStream &s) const override
ZipMemResource(const std::istream &src)
void disp(std::ostream &stream, bool more) const override
Print description.
static ResourceInternal * deserialize(DeserializingStream &s)
RAII class for reading from a zip file.
void disp(std::ostream &stream, bool more) const override
Print description.
static ResourceInternal * deserialize(DeserializingStream &s)
void serialize_body(SerializingStream &s) const override
void serialize_type(SerializingStream &s) const override
Potentially decay into ZipMemResource.
const std::string & path() const override
Get path for a consumer.
ZipResource(const std::string &path)
Initialize with a path.
std::string class_name() const override
Get type name.
The casadi namespace.
Definition: archiver.cpp:28
std::string temporary_file(const std::string &prefix, const std::string &suffix)
std::vector< casadi_int > path(const std::vector< casadi_int > &map, casadi_int i_start)