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

#include <code_cache.hpp>

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

Public Member Functions

 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)
 

Protected Types

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

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

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 39 of file code_cache.hpp.

Member Typedef Documentation

◆ code_cache_index

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> > > > > sysio::chain::eosvmoc::code_cache_base::code_cache_index
protected

Definition at line 62 of file code_cache.hpp.

Constructor & Destructor 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 205 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
local::datagram_protocol::socket _compile_monitor_write_socket
local::datagram_protocol::socket _compile_monitor_read_socket
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)
Here is the call graph for this function:

◆ ~code_cache_base()

sysio::chain::eosvmoc::code_cache_base::~code_cache_base ( )

Definition at line 306 of file code_cache.cpp.

306 {
307 //reopen the code cache in our process
308 struct stat st;
309 if(fstat(_cache_fd, &st))
310 return;
311 char* code_mapping = (char*)mmap(nullptr, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, _cache_fd, 0);
312 if(code_mapping == MAP_FAILED)
313 return;
314
315 allocator_t* allocator = reinterpret_cast<allocator_t*>(code_mapping);
316
317 //serialize out the cache index
320 size_t sz = dssz.tellp();
321
322 char* p = nullptr;
323 while(_cache_index.size()) {
324 p = (char*)allocator->allocate(sz);
325 if(p != nullptr)
326 break;
327 //in theory, there could be too little free space avaiable to store the cache index
328 //try to free up some space
329 for(unsigned int i = 0; i < 25 && _cache_index.size(); ++i) {
330 allocator->deallocate(code_mapping + _cache_index.back().code_begin);
331 allocator->deallocate(code_mapping + _cache_index.back().initdata_begin);
332 _cache_index.pop_back();
333 }
334 }
335
336 if(p) {
339
340 uintptr_t ptr_offset = p-code_mapping;
341 *((uintptr_t*)(code_mapping+descriptor_ptr_from_file_start)) = ptr_offset;
342 }
343 else
344 *((uintptr_t*)(code_mapping+descriptor_ptr_from_file_start)) = 0;
345
346 msync(code_mapping, allocator->get_size(), MS_SYNC);
347 munmap(code_mapping, allocator->get_size());
350
351}
const mie::Vuint & p
Definition bn.cpp:27
void serialize_cache_index(fc::datastream< T > &ds)
void close(T *e, websocketpp::connection_hdl hdl)
_W64 unsigned int uintptr_t
Definition stdint.h:165
Here is the call graph for this function:

Member Function Documentation

◆ check_eviction_threshold()

void sysio::chain::eosvmoc::code_cache_base::check_eviction_threshold ( size_t free_bytes)
protected

Definition at line 380 of file code_cache.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fd()

const int & sysio::chain::eosvmoc::code_cache_base::fd ( ) const
inline

Definition at line 44 of file code_cache.hpp.

44{ return _cache_fd; }
Here is the caller graph for this function:

◆ free_code()

void sysio::chain::eosvmoc::code_cache_base::free_code ( const digest_type & code_id,
const uint8_t & vm_version )

Definition at line 353 of file code_cache.cpp.

353 {
354 code_cache_index::index<by_hash>::type::iterator it = _cache_index.get<by_hash>().find(boost::make_tuple(code_id, vm_version));
355 if(it != _cache_index.get<by_hash>().end()) {
356 write_message_with_fds(_compile_monitor_write_socket, evict_wasms_message{ {*it} });
357 _cache_index.get<by_hash>().erase(it);
358 }
359
360 //if it's in the queued list, erase it
361 _queued_compiles.erase({code_id, vm_version});
362
363 //however, if it's currently being compiled there is no way to cancel the compile,
364 //so instead set a poison boolean that indicates not to insert the code in to the cache
365 //once the compile is complete
366 const std::unordered_map<code_tuple, bool>::iterator compiling_it = _outstanding_compiles_and_poison.find({code_id, vm_version});
367 if(compiling_it != _outstanding_compiles_and_poison.end())
368 compiling_it->second = true;
369}
std::unordered_set< code_tuple > _queued_compiles
std::unordered_map< code_tuple, bool > _outstanding_compiles_and_poison
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 >())
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_eviction_round()

void sysio::chain::eosvmoc::code_cache_base::run_eviction_round ( )
protected

Definition at line 371 of file code_cache.cpp.

371 {
372 evict_wasms_message evict_msg;
373 for(unsigned int i = 0; i < 25 && _cache_index.size() > 1; ++i) {
374 evict_msg.codes.emplace_back(_cache_index.back());
375 _cache_index.pop_back();
376 }
378}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ serialize_cache_index()

template<typename T >
void sysio::chain::eosvmoc::code_cache_base::serialize_cache_index ( fc::datastream< T > & ds)
protected

Definition at line 299 of file code_cache.cpp.

299 {
300 unsigned entries = _cache_index.size();
301 fc::raw::pack(ds, entries);
302 for(const code_descriptor& cd : _cache_index)
303 fc::raw::pack(ds, cd);
304}
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_on_disk_region_dirty()

void sysio::chain::eosvmoc::code_cache_base::set_on_disk_region_dirty ( bool dirty)
protected

Definition at line 289 of file code_cache.cpp.

289 {
290 bip::file_mapping dirty_mapping(_cache_file_path.generic_string().c_str(), bip::read_write);
291 bip::mapped_region dirty_region(dirty_mapping, bip::read_write);
292
293 *((char*)dirty_region.get_address()+header_dirty_bit_offset_from_file_start) = dirty;
294 if(dirty_region.flush(0, 0, false) == false)
295 elog("Syncing code cache failed");
296}
bool dirty
Definition code_cache.cpp:1
#define elog(FORMAT,...)
Definition logger.hpp:130
Here is the caller graph for this function:

Member Data Documentation

◆ _cache_fd

int sysio::chain::eosvmoc::code_cache_base::_cache_fd
protected

Definition at line 68 of file code_cache.hpp.

◆ _cache_file_path

bfs::path sysio::chain::eosvmoc::code_cache_base::_cache_file_path
protected

Definition at line 67 of file code_cache.hpp.

◆ _cache_index

code_cache_index sysio::chain::eosvmoc::code_cache_base::_cache_index
protected

Definition at line 63 of file code_cache.hpp.

◆ _compile_monitor_read_socket

local::datagram_protocol::socket sysio::chain::eosvmoc::code_cache_base::_compile_monitor_read_socket {_ctx}
protected

Definition at line 72 of file code_cache.hpp.

◆ _compile_monitor_write_socket

local::datagram_protocol::socket sysio::chain::eosvmoc::code_cache_base::_compile_monitor_write_socket {_ctx}
protected

Definition at line 71 of file code_cache.hpp.

71{_ctx};

◆ _ctx

io_context sysio::chain::eosvmoc::code_cache_base::_ctx
protected

Definition at line 70 of file code_cache.hpp.

◆ _db

const chainbase::database& sysio::chain::eosvmoc::code_cache_base::_db
protected

Definition at line 65 of file code_cache.hpp.

◆ _free_bytes_eviction_threshold

size_t sysio::chain::eosvmoc::code_cache_base::_free_bytes_eviction_threshold
protected

Definition at line 79 of file code_cache.hpp.

◆ _outstanding_compiles_and_poison

std::unordered_map<code_tuple, bool> sysio::chain::eosvmoc::code_cache_base::_outstanding_compiles_and_poison
protected

Definition at line 77 of file code_cache.hpp.

◆ _queued_compiles

std::unordered_set<code_tuple> sysio::chain::eosvmoc::code_cache_base::_queued_compiles
protected

Definition at line 76 of file code_cache.hpp.


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