1 /**
2 * \file RMF/Category.h
3 * \brief Handle read/write of Model data from/to files.
4 *
5 * Copyright 2007-2021 IMP Inventors. All rights reserved.
6 *
7 */
8
9 #include <algorithm>
10 #include <exception>
11 #include <functional>
12 #include <iostream>
13 #include <string>
14
15 #include "RMF/ID.h"
16 #include "RMF/compiler_macros.h"
17 #include "RMF/constants.h"
18 #include "RMF/enums.h"
19 #include "RMF/exceptions.h"
20 #include "RMF/infrastructure_macros.h"
21 #include "RMF/internal/SharedData.h"
22 #include "RMF/internal/large_set_map.h"
23 #include "RMF/log.h"
24 #include "RMF/types.h"
25 #include "backend/IO.h"
26
27 RMF_ENABLE_WARNINGS
28
29 namespace RMF {
30 namespace internal {
31
32 namespace {
33 RMF_LARGE_UNORDERED_SET<std::string> open_for_writing;
34 }
SharedData(boost::shared_ptr<backends::IO> io,std::string name,bool write,bool created)35 SharedData::SharedData(boost::shared_ptr<backends::IO> io, std::string name,
36 bool write, bool created)
37 : path_(name), write_(write), io_(io) {
38 if (!created) {
39 reload();
40 }
41 RMF_USAGE_CHECK(
42 open_for_writing.find(get_file_path()) == open_for_writing.end(),
43 "Opening a file that is still being written is asking for trouble.");
44 if (write) open_for_writing.insert(get_file_path());
45 }
46
set_loaded_frame(FrameID frame)47 void SharedData::set_loaded_frame(FrameID frame) {
48 RMF_USAGE_CHECK(!write_, "Can't call set loaded frame when writing.");
49 RMF_USAGE_CHECK(frame != ALL_FRAMES, "Trying to set loaded to all frames");
50 RMF_USAGE_CHECK(
51 frame == FrameID() || frame.get_index() < get_number_of_frames(),
52 "Trying to load a frame that isn't there");
53 if (frame == get_loaded_frame()) return;
54 RMF_INFO("Setting loaded frame to " << frame);
55 loaded_frame_ = frame;
56
57 clear_loaded_values();
58 if (frame != FrameID()) {
59 io_->load_loaded_frame(this);
60 }
61 }
62
add_frame(std::string name,FrameType type)63 FrameID SharedData::add_frame(std::string name, FrameType type) {
64 RMF_INTERNAL_CHECK(write_, "Can't add frame if not writing");
65 FrameID ret(get_number_of_frames());
66 FrameID cl = get_loaded_frame();
67 RMF_INTERNAL_CHECK(cl != ret, "Huh, frames are the same");
68 if (cl != FrameID()) {
69 if (SharedDataFile::get_is_dirty()) {
70 RMF_INFO("Flushing file info");
71 io_->save_file(this);
72 SharedDataFile::set_is_dirty(false);
73 }
74 if (SharedDataHierarchy::get_is_dirty()) {
75 RMF_INFO("Flushing node hierarchy");
76 io_->save_hierarchy(this);
77 SharedDataHierarchy::set_is_dirty(false);
78 }
79 io_->save_loaded_frame(this);
80 }
81 add_frame_data(ret, name, type);
82
83 clear_loaded_values();
84 loaded_frame_ = ret;
85 return ret;
86 }
87
add_frame(std::string name,FrameID parent,FrameType type)88 FrameID SharedData::add_frame(std::string name, FrameID parent,
89 FrameType type) {
90 FrameID ret = add_frame(name, type);
91 add_child_frame(parent, ret);
92 return ret;
93 }
94
flush()95 void SharedData::flush() {
96 if (!write_) return;
97 RMF_INFO("Flushing file " << get_file_path());
98 if (SharedDataFile::get_is_dirty()) {
99 RMF_INFO("Flushing file info");
100 io_->save_file(this);
101 SharedDataFile::set_is_dirty(false);
102 }
103 if (SharedDataHierarchy::get_is_dirty()) {
104 RMF_INFO("Flushing node hierarchy");
105 io_->save_hierarchy(this);
106 SharedDataHierarchy::set_is_dirty(false);
107 }
108 if (get_static_is_dirty()) {
109 RMF_INFO("Saving static frame");
110 io_->save_static_frame(this);
111 set_static_is_dirty(false);
112 }
113 io_->flush();
114 }
115
reload()116 void SharedData::reload() {
117 RMF_INFO("(Re)loading file " << get_file_path());
118 SharedDataHierarchy::clear();
119 io_->load_file(this);
120 SharedDataFile::set_is_dirty(false);
121 io_->load_hierarchy(this);
122 SharedDataHierarchy::set_is_dirty(false);
123
124 clear_static_values();
125 io_->load_static_frame(this);
126 set_static_is_dirty(false);
127
128 clear_loaded_values();
129 if (get_loaded_frame() != FrameID() &&
130 get_loaded_frame().get_index() < get_number_of_frames()) {
131 io_->load_loaded_frame(this);
132 }
133 }
134
~SharedData()135 SharedData::~SharedData() {
136 if (write_) {
137 try {
138 RMF_INFO("Closing file " << get_file_path());
139 flush();
140 if (get_loaded_frame() != FrameID()) {
141 io_->save_loaded_frame(this);
142 }
143 io_.reset();
144 }
145 catch (const std::exception &e) {
146 std::cerr << "Exception caught in shared data destructor " << e.what()
147 << std::endl;
148 }
149 open_for_writing.erase(get_file_path());
150 }
151 }
152
153 } // namespace internal
154 } /* namespace RMF */
155
156 RMF_DISABLE_WARNINGS
157