Loading [MathJax]/extensions/tex2jax.js
LSST Applications g04dff08e69+fafbcb10e2,g0d33ba9806+e09a96fa4e,g0fba68d861+cc01b48236,g1e78f5e6d3+fb95f9dda6,g1ec0fe41b4+f536777771,g1fd858c14a+ae46bc2a71,g35bb328faa+fcb1d3bbc8,g4af146b050+dd94f3aad7,g4d2262a081+7ee6f976aa,g53246c7159+fcb1d3bbc8,g5a012ec0e7+b20b785ecb,g60b5630c4e+e09a96fa4e,g6273192d42+bf8cfc5e62,g67b6fd64d1+4086c0989b,g78460c75b0+2f9a1b4bcd,g786e29fd12+cf7ec2a62a,g7b71ed6315+fcb1d3bbc8,g87b7deb4dc+831c06c8fc,g8852436030+54b48a5987,g89139ef638+4086c0989b,g9125e01d80+fcb1d3bbc8,g94187f82dc+e09a96fa4e,g989de1cb63+4086c0989b,g9f33ca652e+64be6d9d51,g9f7030ddb1+d11454dffd,ga2b97cdc51+e09a96fa4e,gabe3b4be73+1e0a283bba,gabf8522325+fa80ff7197,gb1101e3267+23605820ec,gb58c049af0+f03b321e39,gb89ab40317+4086c0989b,gcf25f946ba+54b48a5987,gd6cbbdb0b4+af3c3595f5,gd9a9a58781+fcb1d3bbc8,gde0f65d7ad+15f2daff9d,ge278dab8ac+d65b3c2b70,ge410e46f29+4086c0989b,gf67bdafdda+4086c0989b,v29.0.0.rc5
LSST Data Management Base Package
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
OutputArchive.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2
3#include <typeinfo>
4#include <vector>
5#include <map>
6#include <memory>
7
8#include "boost/format.hpp"
9
10#include "lsst/pex/exceptions.h"
15#include "lsst/afw/fits.h"
16
17namespace lsst {
18namespace afw {
19namespace table {
20namespace io {
21
22namespace {
23
25
26// we don't need sorting, but you can't use weak_ptrs as keys in an
27// unordered_map
28using Map = std::map<std::weak_ptr<Persistable const>, int,
29 std::owner_less<std::weak_ptr<Persistable const>>>;
30
31using MapItem = Map::value_type;
32
33} // namespace
34
35// ----- OutputArchive::Impl --------------------------------------------------------------------------------
36
38public:
40 int catArchive = 1;
41 CatalogVector::iterator iter = _catalogs.begin();
43 for (; iter != _catalogs.end(); ++iter, ++catArchive) {
44 if (iter->getSchema().compare(schema, flags) == flags) {
45 break;
46 }
47 }
48 if (iter == _catalogs.end()) {
49 iter = _catalogs.insert(_catalogs.end(), BaseCatalog(schema));
50 }
51 if (!iter->getTable()->getMetadata()) {
53 iter->getTable()->setMetadata(metadata);
54 metadata->set("EXTTYPE", "ARCHIVE_DATA");
55 metadata->set("AR_CATN", catArchive, "# of this catalog relative to the start of this archive");
56 }
57 return BaseCatalog(iter->getTable());
58 }
59
61 auto indexRecord = _index.addNew();
62 indexRecord->set(indexKeys.id, id);
63 indexRecord->set(indexKeys.name, name);
64 indexRecord->set(indexKeys.module, module);
65 return indexRecord;
66 }
67
68 void saveEmpty(int id, std::string const &name, std::string const &module) {
69 auto indexRecord = addIndexRecord(id, name, module);
70 indexRecord->set(indexKeys.nRows, 0);
71 indexRecord->set(indexKeys.catPersistable, ArchiveIndexSchema::NO_CATALOGS_SAVED);
72 indexRecord->set(indexKeys.row0, ArchiveIndexSchema::NO_CATALOGS_SAVED);
73 indexRecord->set(indexKeys.catArchive, ArchiveIndexSchema::NO_CATALOGS_SAVED);
74 }
75
76 void saveCatalog(BaseCatalog const &catalog, int id, std::string const &name, std::string const &module,
77 int catPersistable) {
78 auto indexRecord = addIndexRecord(id, name, module);
79 indexRecord->set(indexKeys.catPersistable, catPersistable);
80 indexRecord->set(indexKeys.nRows, catalog.size());
81 int catArchive = 1;
82 CatalogVector::iterator iter = _catalogs.begin();
83 for (; iter != _catalogs.end(); ++iter, ++catArchive) {
84 if (iter->getTable() == catalog.getTable()) {
85 break;
86 }
87 }
88 if (iter == _catalogs.end()) {
90 "All catalogs passed to saveCatalog must be created by makeCatalog");
91 }
92 auto metadata = iter->getTable()->getMetadata();
93 // If EXTNAME exists we have already assigned an EXTVER.
94 // Otherwise must scan through all catalogs looking for other
95 // catalogs with the same name that have been assigned EXTNAME
96 // to determine this EXTVER.
97 auto found_extname = metadata->exists("EXTNAME");
98 if (!found_extname) {
99 int extver = 1;
100 // Catalogs can be filled out of order, so look for other
101 // catalogs with this EXTNAME.
102 CatalogVector::iterator ver_iter = _catalogs.begin();
103 for (; ver_iter != _catalogs.end(); ++ver_iter) {
104 auto cat_metadata = ver_iter->getTable()->getMetadata();
105 if (cat_metadata->exists("EXTNAME") && cat_metadata->getAsString("EXTNAME") == name) {
106 ++extver;
107 }
108 }
109 if (extver > 1) { // 1 is the default so no need to write it.
110 metadata->set("EXTVER", extver);
111 }
112 }
113 // Add the name of the class to the header so anyone looking at it can
114 // tell what's stored there. But we don't want to add it multiple times.
115 try {
116 auto names = metadata->getArray<std::string>("AR_NAME");
117 if (std::find(names.begin(), names.end(), name) == names.end()) {
118 iter->getTable()->getMetadata()->add("AR_NAME", name, "Class name for objects stored here");
119 }
121 metadata->add("AR_NAME", name, "Class name for objects stored here");
122 }
123 // Also add an EXTNAME. The most recent AR_NAME given will be used.
124 metadata->set("EXTNAME", name);
125 indexRecord->set(indexKeys.row0, iter->size());
126 indexRecord->set(indexKeys.catArchive, catArchive);
127 iter->insert(iter->end(), catalog.begin(), catalog.end(), false);
128 }
129
130 int put(Persistable const *obj, std::shared_ptr<Impl> const &self, bool permissive) {
131 if (!obj) return 0;
132 if (permissive && !obj->isPersistable()) return 0;
133 int const currentId = _nextId;
134 ++_nextId;
135 OutputArchiveHandle handle(currentId, obj->getPersistenceName(), obj->getPythonModule(), self);
136 obj->write(handle);
137 return currentId;
138 }
139
140 int put(std::shared_ptr<Persistable const> obj, std::shared_ptr<Impl> const &self, bool permissive) {
141 if (!obj) return 0;
142 if (permissive && !obj->isPersistable()) return 0;
143 MapItem item(obj, _nextId);
144 std::pair<Map::iterator, bool> r = _map.insert(item);
145 if (r.second) {
146 // We've never seen this object before. Save it.
147 return put(obj.get(), self, permissive);
148 } else {
149 // We had already saved this object, and insert returned an iterator
150 // to the ID we used before; return that.
151 return r.first->second;
152 }
153 }
154
155 void writeFits(fits::Fits &fitsfile) {
156 _index.getTable()->getMetadata()->set("AR_NCAT", int(_catalogs.size() + 1),
157 "# of catalogs in this archive, including the index");
158 _index.writeFits(fitsfile);
159 int n = 1;
160 for (CatalogVector::const_iterator iter = _catalogs.begin(); iter != _catalogs.end(); ++iter, ++n) {
161 iter->writeFits(fitsfile);
162 }
163 }
164
165 Impl() : _map(), _index(ArchiveIndexSchema::get().schema) {
167 metadata->set("EXTTYPE", "ARCHIVE_INDEX");
168 metadata->set("EXTNAME", "ARCHIVE_INDEX");
169 metadata->set("AR_CATN", 0, "# of this catalog relative to the start of this archive");
170 _index.getTable()->setMetadata(metadata);
171 }
172
173 int _nextId{1};
174 Map _map;
177};
178
179// ----- OutputArchive --------------------------------------------------------------------------------------
180
182
183OutputArchive::OutputArchive(OutputArchive const &other) = default;
184// Delegate to copy constructor for backward compatibility
186
188// Delegate to copy assignment for backward compatibility
189OutputArchive &OutputArchive::operator=(OutputArchive &&other) { return *this = other; }
190
192
193int OutputArchive::put(Persistable const *obj, bool permissive) {
194 if (_impl.use_count() != 1) { // copy on write
195 std::shared_ptr<Impl> tmp(new Impl(*_impl));
196 _impl.swap(tmp);
197 }
198 return _impl->put(obj, _impl, permissive);
199}
200
202 if (_impl.use_count() != 1) { // copy on write
203 std::shared_ptr<Impl> tmp(new Impl(*_impl));
204 _impl.swap(tmp);
205 }
206 return _impl->put(std::move(obj), _impl, permissive);
207}
208
209BaseCatalog const &OutputArchive::getIndexCatalog() const { return _impl->_index; }
210
212 if (n == 0) return _impl->_index;
213 if (std::size_t(n) > _impl->_catalogs.size() || n < 0) {
214 throw LSST_EXCEPT(
216 (boost::format("Catalog number %d is out of range [0,%d]") % n % _impl->_catalogs.size())
217 .str());
218 }
219 return _impl->_catalogs[n - 1];
220}
221
222std::size_t OutputArchive::countCatalogs() const { return _impl->_catalogs.size() + 1; }
223
224void OutputArchive::writeFits(fits::Fits &fitsfile) const { _impl->writeFits(fitsfile); }
225
226// ----- OutputArchiveHandle ------------------------------------------------------------------------------
227
228BaseCatalog OutputArchiveHandle::makeCatalog(Schema const &schema) { return _impl->makeCatalog(schema); }
229
230void OutputArchiveHandle::saveEmpty() { _impl->saveEmpty(_id, _name, _module); }
231
233 _impl->saveCatalog(catalog, _id, _name, _module, _catPersistable);
234 ++_catPersistable;
235}
236
237int OutputArchiveHandle::put(Persistable const *obj, bool permissive) {
238 // Handle doesn't worry about copy-on-write, because Handles should only exist
239 // while an OutputArchive::put() call is active.
240 return _impl->put(obj, _impl, permissive);
241}
242
244 // Handle doesn't worry about copy-on-write, because Handles should only exist
245 // while an OutputArchive::put() call is active.
246 return _impl->put(std::move(obj), _impl, permissive);
247}
248
249OutputArchiveHandle::OutputArchiveHandle(int id, std::string const &name, std::string const &module,
251 : _id(id), _catPersistable(0), _name(name), _module(module), _impl(impl) {}
252
254} // namespace io
255} // namespace table
256} // namespace afw
257} // namespace lsst
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition fits.h:308
Defines the fields and offsets for a table.
Definition Schema.h:51
@ EQUAL_NAMES
Fields have the same names (ordered).
Definition Schema.h:67
@ EQUAL_KEYS
Keys have the same types offsets, and sizes.
Definition Schema.h:66
A vector of catalogs used by Persistable.
std::shared_ptr< BaseRecord > addIndexRecord(int id, std::string const &name, std::string const &module)
int put(Persistable const *obj, std::shared_ptr< Impl > const &self, bool permissive)
BaseCatalog makeCatalog(Schema const &schema)
int put(std::shared_ptr< Persistable const > obj, std::shared_ptr< Impl > const &self, bool permissive)
void saveEmpty(int id, std::string const &name, std::string const &module)
void saveCatalog(BaseCatalog const &catalog, int id, std::string const &name, std::string const &module, int catPersistable)
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
OutputArchiveHandle(const OutputArchiveHandle &)=delete
void saveEmpty()
Indicate that the object being persisted has no state, and hence will never call makeCatalog() or sav...
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
int put(Persistable const *obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
A multi-catalog archive object used to save table::io::Persistable objects.
std::size_t countCatalogs() const
Return the total number of catalogs, including the index.
int put(std::shared_ptr< Persistable const > obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
void writeFits(fits::Fits &fitsfile) const
Write the archive to an already-open FITS object.
BaseCatalog const & getCatalog(int n) const
Return the nth catalog. Catalog 0 is always the index catalog.
OutputArchive & operator=(OutputArchive const &other)
Assign from another OutputArchive. Saved objects are not deep-copied.
BaseCatalog const & getIndexCatalog() const
Return the index catalog that specifies where objects are stored in the data catalogs.
OutputArchive()
Construct an empty OutputArchive containing no objects.
A base class for objects that can be persisted via afw::table::io Archive classes.
Definition Persistable.h:74
Class for storing ordered metadata with comments.
Reports attempts to exceed implementation-defined length limits for some classes.
Definition Runtime.h:76
Reports errors in the logical structure of the program.
Definition Runtime.h:46
Reports attempts to access elements using an invalid key.
Definition Runtime.h:151
T find(T... args)
T move(T... args)
CatalogT< BaseRecord > BaseCatalog
Definition fwd.h:72
Schema for the index catalog that specifies where objects are stored in the data catalogs.
static constexpr int const NO_CATALOGS_SAVED
Special value used for catArchive, catPersistable, and row0 when an object with no state is saved.
static ArchiveIndexSchema const & get()
Return the singleton instance.