Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio::chain::eosvmoc::code_cache_sync Class Reference

#include <code_cache.hpp>

Inheritance diagram for sysio::chain::eosvmoc::code_cache_sync:
Collaboration diagram for sysio::chain::eosvmoc::code_cache_sync:

Public Member Functions

 ~code_cache_sync ()
 
const code_descriptor *const get_descriptor_for_code_sync (const digest_type &code_id, const uint8_t &vm_version)
 
 code_cache_base (const bfs::path data_dir, const eosvmoc::config &eosvmoc_config, const chainbase::database &db)
 
- Public Member Functions inherited from sysio::chain::eosvmoc::code_cache_base
 code_cache_base (const bfs::path data_dir, const eosvmoc::config &eosvmoc_config, const chainbase::database &db)
 
 ~code_cache_base ()
 
const int & fd () const
 
void free_code (const digest_type &code_id, const uint8_t &vm_version)
 

Additional Inherited Members

- Protected Types inherited from sysio::chain::eosvmoc::code_cache_base
typedef boost::multi_index_container< code_descriptor, indexed_by< sequenced<>, hashed_unique< tag< by_hash >, composite_key< code_descriptor, member< code_descriptor, digest_type, &code_descriptor::code_hash >, member< code_descriptor, uint8_t, &code_descriptor::vm_version > > > > > code_cache_index
 
- Protected Member Functions inherited from sysio::chain::eosvmoc::code_cache_base
void check_eviction_threshold (size_t free_bytes)
 
void run_eviction_round ()
 
void set_on_disk_region_dirty (bool)
 
template<typename T >
void serialize_cache_index (fc::datastream< T > &ds)
 
- Protected Attributes inherited from sysio::chain::eosvmoc::code_cache_base
code_cache_index _cache_index
 
const chainbase::database_db
 
bfs::path _cache_file_path
 
int _cache_fd
 
io_context _ctx
 
local::datagram_protocol::socket _compile_monitor_write_socket {_ctx}
 
local::datagram_protocol::socket _compile_monitor_read_socket {_ctx}
 
std::unordered_set< code_tuple_queued_compiles
 
std::unordered_map< code_tuple, bool > _outstanding_compiles_and_poison
 
size_t _free_bytes_eviction_threshold
 

Detailed Description

Definition at line 108 of file code_cache.hpp.

Constructor & Destructor Documentation

◆ ~code_cache_sync()

sysio::chain::eosvmoc::code_cache_sync::~code_cache_sync ( )

Definition at line 168 of file code_cache.cpp.

168 {
169 //it's exceedingly critical that we wait for the compile monitor to be done with all its work
170 //This is easy in the sync case
171 _compile_monitor_write_socket.shutdown(local::datagram_protocol::socket::shutdown_send);
173 if(success)
174 elog("unexpected response from SYS VM OC compile monitor during shutdown");
175}
local::datagram_protocol::socket _compile_monitor_write_socket
local::datagram_protocol::socket _compile_monitor_read_socket
#define elog(FORMAT,...)
Definition logger.hpp:130
std::tuple< bool, eosvmoc_message, std::vector< wrapped_fd > > read_message_with_fds(boost::asio::local::datagram_protocol::socket &s)
Here is the call graph for this function:

Member Function Documentation

◆ code_cache_base()

sysio::chain::eosvmoc::code_cache_base::code_cache_base ( const bfs::path data_dir,
const eosvmoc::config & eosvmoc_config,
const chainbase::database & db )

Definition at line 41 of file code_cache.cpp.

205 :
206 _db(db),
207 _cache_file_path(data_dir/"code_cache.bin")
208{
209 static_assert(sizeof(allocator_t) <= header_offset, "header offset intersects with allocator");
210
211 bfs::create_directories(data_dir);
212
213 if(!bfs::exists(_cache_file_path)) {
214 SYS_ASSERT(eosvmoc_config.cache_size >= allocator_t::get_min_size(total_header_size), database_exception, "configured code cache size is too small");
215 std::ofstream ofs(_cache_file_path.generic_string(), std::ofstream::trunc);
216 SYS_ASSERT(ofs.good(), database_exception, "unable to create SYS VM Optimized Compiler code cache");
217 bfs::resize_file(_cache_file_path, eosvmoc_config.cache_size);
218 bip::file_mapping creation_mapping(_cache_file_path.generic_string().c_str(), bip::read_write);
219 bip::mapped_region creation_region(creation_mapping, bip::read_write);
220 new (creation_region.get_address()) allocator_t(eosvmoc_config.cache_size, total_header_size);
221 new ((char*)creation_region.get_address() + header_offset) code_cache_header;
222 }
223
224 code_cache_header cache_header;
225 {
226 char header_buff[total_header_size];
227 std::ifstream hs(_cache_file_path.generic_string(), std::ifstream::binary);
228 hs.read(header_buff, sizeof(header_buff));
229 SYS_ASSERT(!hs.fail(), bad_database_version_exception, "failed to read code cache header");
230 memcpy((char*)&cache_header, header_buff + header_offset, sizeof(cache_header));
231 }
232
233 SYS_ASSERT(cache_header.id == header_id, bad_database_version_exception, "existing SYS VM OC code cache not compatible with this version");
234 SYS_ASSERT(!cache_header.dirty, database_exception, "code cache is dirty");
235
237
238 auto existing_file_size = bfs::file_size(_cache_file_path);
239 if(eosvmoc_config.cache_size > existing_file_size) {
240 bfs::resize_file(_cache_file_path, eosvmoc_config.cache_size);
241
242 bip::file_mapping resize_mapping(_cache_file_path.generic_string().c_str(), bip::read_write);
243 bip::mapped_region resize_region(resize_mapping, bip::read_write);
244
245 allocator_t* resize_allocator = reinterpret_cast<allocator_t*>(resize_region.get_address());
246 resize_allocator->grow(eosvmoc_config.cache_size - existing_file_size);
247 }
248
249 _cache_fd = ::open(_cache_file_path.generic_string().c_str(), O_RDWR | O_CLOEXEC);
250 SYS_ASSERT(_cache_fd >= 0, database_exception, "failure to open code cache");
251
252 //load up the previous cache index
253 char* code_mapping = (char*)mmap(nullptr, eosvmoc_config.cache_size, PROT_READ|PROT_WRITE, MAP_SHARED, _cache_fd, 0);
254 SYS_ASSERT(code_mapping != MAP_FAILED, database_exception, "failure to mmap code cache");
255
256 allocator_t* allocator = reinterpret_cast<allocator_t*>(code_mapping);
257
258 if(cache_header.serialized_descriptor_index) {
259 fc::datastream<const char*> ds(code_mapping + cache_header.serialized_descriptor_index, eosvmoc_config.cache_size - cache_header.serialized_descriptor_index);
260 unsigned number_entries;
261 fc::raw::unpack(ds, number_entries);
262 for(unsigned i = 0; i < number_entries; ++i) {
263 code_descriptor cd;
264 fc::raw::unpack(ds, cd);
265 if(cd.codegen_version != current_codegen_version) {
266 allocator->deallocate(code_mapping + cd.code_begin);
267 allocator->deallocate(code_mapping + cd.initdata_begin);
268 continue;
269 }
270 _cache_index.push_back(std::move(cd));
271 }
272 allocator->deallocate(code_mapping + cache_header.serialized_descriptor_index);
273
274 ilog("SYS VM Optimized Compiler code cache loaded with ${c} entries; ${f} of ${t} bytes free", ("c", number_entries)("f", allocator->get_free_memory())("t", allocator->get_size()));
275 }
276 munmap(code_mapping, eosvmoc_config.cache_size);
277
278 _free_bytes_eviction_threshold = eosvmoc_config.cache_size * .1;
279
280 wrapped_fd compile_monitor_conn = get_connection_to_compile_monitor(_cache_fd);
281
282 //okay, let's do this by the book: we're not allowed to write & read on different threads to the same asio socket. So create two fds
283 //representing the same unix socket. we'll read on one and write on the other
284 int duped = dup(compile_monitor_conn);
285 _compile_monitor_write_socket.assign(local::datagram_protocol(), duped);
286 _compile_monitor_read_socket.assign(local::datagram_protocol(), compile_monitor_conn.release());
287}
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
const chainbase::database & _db
#define ilog(FORMAT,...)
Definition logger.hpp:118
static const Segment ds(Segment::ds)
bip::allocator< T, pinnable_mapped_file::segment_manager > allocator
Definition chainbase.hpp:56
void unpack(Stream &s, std::deque< T > &value)
Definition raw.hpp:540
bip::rbtree_best_fit< bip::null_mutex_family, bip::offset_ptr< void >, alignof(std::max_align_t)> allocator_t
wrapped_fd get_connection_to_compile_monitor(int cache_fd)
key Invalid authority Invalid transaction Invalid block ID Invalid packed transaction Invalid chain ID Invalid symbol Signature type is not a currently activated type Block can not be found Unlinkable block Block does not guarantee concurrent execution without conflicts Block exhausted allowed resources Block is from the future Block is not signed by expected producer Block includes an ill formed protocol feature activation extension Block includes an ill formed additional block signature extension Error decompressing transaction Transaction should have at least one required authority Expired Transaction Invalid Reference Block Duplicate deferred transaction The transaction can not be found Transaction is too big Invalid transaction extension Transaction includes disallowed Transaction exceeded transient resource limit Account name already exists sysio_assert_message assertion failure Action can not be found Attempt to use unaccessible API Inline Action exceeds maximum size limit sysio_assert_code assertion failure uses restricted error code value action return value size too big database_exception
memcpy((char *) pInfo->slotDescription, s, l)

◆ get_descriptor_for_code_sync()

const code_descriptor *const sysio::chain::eosvmoc::code_cache_sync::get_descriptor_for_code_sync ( const digest_type & code_id,
const uint8_t & vm_version )

Definition at line 177 of file code_cache.cpp.

177 {
178 //check for entry in cache
179 code_cache_index::index<by_hash>::type::iterator it = _cache_index.get<by_hash>().find(boost::make_tuple(code_id, vm_version));
180 if(it != _cache_index.get<by_hash>().end()) {
181 _cache_index.relocate(_cache_index.begin(), _cache_index.project<0>(it));
182 return &*it;
183 }
184
185 const code_object* const codeobject = _db.find<code_object,by_code_hash>(boost::make_tuple(code_id, 0, vm_version));
186 if(!codeobject) //should be impossible right?
187 return nullptr;
188
189 std::vector<wrapped_fd> fds_to_pass;
190 fds_to_pass.emplace_back(memfd_for_bytearray(codeobject->code));
191
192 write_message_with_fds(_compile_monitor_write_socket, compile_wasm_message{ {code_id, vm_version} }, fds_to_pass);
194 SYS_ASSERT(success, wasm_execution_error, "failed to read response from monitor process");
195 SYS_ASSERT(std::holds_alternative<wasm_compilation_result_message>(message), wasm_execution_error, "unexpected response from monitor process");
196
197 wasm_compilation_result_message result = std::get<wasm_compilation_result_message>(message);
198 SYS_ASSERT(std::holds_alternative<code_descriptor>(result.result), wasm_execution_error, "failed to compile wasm");
199
200 check_eviction_threshold(result.cache_free_bytes);
201
202 return &*_cache_index.push_front(std::move(std::get<code_descriptor>(result.result))).first;
203}
const ObjectType * find(CompatibleKey &&key) const
void check_eviction_threshold(size_t free_bytes)
RUNTIME_API Runtime::ObjectInstance * find(const std::string &name, const IR::ObjectType &type)
bool write_message_with_fds(boost::asio::local::datagram_protocol::socket &s, const eosvmoc_message &message, const std::vector< wrapped_fd > &fds=std::vector< wrapped_fd >())
wrapped_fd memfd_for_bytearray(const T &bytes)
Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: