diff --git a/lib/LiveUpdate/liveupdate.hpp b/lib/LiveUpdate/liveupdate.hpp index 6ad9057138..9fde77a839 100644 --- a/lib/LiveUpdate/liveupdate.hpp +++ b/lib/LiveUpdate/liveupdate.hpp @@ -53,7 +53,7 @@ struct LiveUpdate // Register a function to be called when serialization phase begins // Internally it will be stored as its own partition and can be restored using // the same @key value during the resume process - static void register_serialization_callback(std::string key, storage_func); + static void register_partition(std::string key, storage_func); // Start a live update process, storing all user-defined data // If no storage functions are registered no state will be saved @@ -76,7 +76,9 @@ struct LiveUpdate static bool is_resumable(void* location); // Restore existing state for a partition named @key. - static void resume(std::string key, resume_func handler); + // Returns false if there was no such partition + // Can throw lots of standard exceptions + static bool resume(std::string key, resume_func handler); // When explicitly resuming from heap, heap overrun checks are disabled static void resume_from_heap(void* location, std::string key, resume_func); diff --git a/lib/LiveUpdate/partition.cpp b/lib/LiveUpdate/partition.cpp index 90c26a33ff..0bb92f667d 100644 --- a/lib/LiveUpdate/partition.cpp +++ b/lib/LiveUpdate/partition.cpp @@ -59,7 +59,7 @@ int storage_header::find_partition(const char* key) throw std::runtime_error("Invalid CRC in partition '" + std::string(key) + "'"); } } - throw std::out_of_range("Could not find partition named " + std::string(key)); + return -1; } void storage_header::finish_partition(int p) { diff --git a/lib/LiveUpdate/resume.cpp b/lib/LiveUpdate/resume.cpp index 75bbbb7fad..c0d61ca469 100644 --- a/lib/LiveUpdate/resume.cpp +++ b/lib/LiveUpdate/resume.cpp @@ -34,7 +34,7 @@ extern char* heap_end; namespace liu { -static void resume_begin(storage_header&, std::string, LiveUpdate::resume_func); +static bool resume_begin(storage_header&, std::string, LiveUpdate::resume_func); bool LiveUpdate::is_resumable() { @@ -45,17 +45,17 @@ bool LiveUpdate::is_resumable(void* location) return ((storage_header*) location)->validate(); } -static void resume_helper(void* location, std::string key, LiveUpdate::resume_func func) +static bool resume_helper(void* location, std::string key, LiveUpdate::resume_func func) { // check if an update has occurred if (!LiveUpdate::is_resumable(location)) - throw std::runtime_error("Trying to resume from invalid storage area"); + return false; LPRINT("* Restoring data...\n"); // restore connections etc. - resume_begin(*(storage_header*) location, key.c_str(), func); + return resume_begin(*(storage_header*) location, key.c_str(), func); } -void LiveUpdate::resume(std::string key, resume_func func) +bool LiveUpdate::resume(std::string key, resume_func func) { void* location = OS::liveupdate_storage_area(); /// memory sanity check @@ -65,19 +65,20 @@ void LiveUpdate::resume(std::string key, resume_func func) (long int) (heap_end - (char*) location)); throw std::runtime_error("LiveUpdate storage area inside heap"); } - resume_helper(location, std::move(key), func); + return resume_helper(location, std::move(key), func); } void LiveUpdate::resume_from_heap(void* location, std::string key, LiveUpdate::resume_func func) { resume_helper(location, std::move(key), func); } -void resume_begin(storage_header& storage, std::string key, LiveUpdate::resume_func func) +bool resume_begin(storage_header& storage, std::string key, LiveUpdate::resume_func func) { if (key.empty()) throw std::length_error("LiveUpdate partition key cannot be an empty string"); int p = storage.find_partition(key.c_str()); + if (p == -1) return false; LPRINT("* Resuming from partition %d at %p from %p\n", p, storage.begin(p), &storage); @@ -92,6 +93,7 @@ void resume_begin(storage_header& storage, std::string key, LiveUpdate::resume_f storage.zero_partition(p); // if there are no more partitions, clear everything storage.try_zero(); + return true; } /// struct Restore diff --git a/lib/LiveUpdate/update.cpp b/lib/LiveUpdate/update.cpp index fc4ff4df3c..4f4e3b6ffb 100644 --- a/lib/LiveUpdate/update.cpp +++ b/lib/LiveUpdate/update.cpp @@ -36,9 +36,8 @@ static const int SECT_SIZE = 512; static const int ELF_MINIMUM = 164; - -extern "C" -void solo5_exec(const char*, size_t); +// hotswapping functions +extern "C" void solo5_exec(const char*, size_t); static void* HOTSWAP_AREA = (void*) 0x8000; extern "C" void hotswap(const char*, int, char*, uintptr_t, void*); extern "C" char __hotswap_length; @@ -61,7 +60,7 @@ static size_t update_store_data(void* location, const buffer_t*); // serialization callbacks static std::unordered_map storage_callbacks; -void LiveUpdate::register_serialization_callback(std::string key, storage_func callback) +void LiveUpdate::register_partition(std::string key, storage_func callback) { auto it = storage_callbacks.find(key); if (it == storage_callbacks.end()) @@ -86,7 +85,7 @@ inline bool validate_header(const Class* hdr) void LiveUpdate::exec(const buffer_t& blob, std::string key, storage_func func) { - if (func != nullptr) register_serialization_callback(key, func); + if (func != nullptr) LiveUpdate::register_partition(key, func); LiveUpdate::exec(blob); } diff --git a/lib/uplink/ws_uplink.cpp b/lib/uplink/ws_uplink.cpp index a34867608c..d19487fd03 100644 --- a/lib/uplink/ws_uplink.cpp +++ b/lib/uplink/ws_uplink.cpp @@ -47,7 +47,7 @@ namespace uplink { { OS::add_stdout({this, &WS_uplink::send_log}); - liu::LiveUpdate::register_serialization_callback("uplink", {this, &WS_uplink::store}); + liu::LiveUpdate::register_partition("uplink", {this, &WS_uplink::store}); read_config(); CHECK(config_.reboot, "Reboot on panic"); diff --git a/test/kernel/integration/LiveUpdate/service.cpp b/test/kernel/integration/LiveUpdate/service.cpp index c8d4fcb5b4..0ef1a44e48 100644 --- a/test/kernel/integration/LiveUpdate/service.cpp +++ b/test/kernel/integration/LiveUpdate/service.cpp @@ -31,5 +31,7 @@ void Service::start() { auto& inet = net::Super_stack::get(0); setup_liveupdate_server(inet, 666, func); + // signal test.py that the server is up + printf("Ready to receive binary blob\n"); } } diff --git a/test/kernel/integration/LiveUpdate/test.py b/test/kernel/integration/LiveUpdate/test.py index 0bb15c4698..8ea8e1b8a9 100755 --- a/test/kernel/integration/LiveUpdate/test.py +++ b/test/kernel/integration/LiveUpdate/test.py @@ -4,7 +4,7 @@ import socket includeos_src = os.environ.get('INCLUDEOS_SRC', - os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))).split('/test')[0]) + os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))).split('/test')[0]) sys.path.insert(0,includeos_src) from vmrunner import vmrunner diff --git a/test/kernel/integration/LiveUpdate/test_boot.cpp b/test/kernel/integration/LiveUpdate/test_boot.cpp index eb961835be..b940e22464 100644 --- a/test/kernel/integration/LiveUpdate/test_boot.cpp +++ b/test/kernel/integration/LiveUpdate/test_boot.cpp @@ -28,17 +28,15 @@ static void boot_resume_all(Restore& thing) LiveUpdate::storage_func begin_test_boot() { - try { - LiveUpdate::resume("test", boot_resume_all); - // if we are here, - // resume() must have succeeded + if (LiveUpdate::resume("test", boot_resume_all)) + { if (timestamps.size() >= 30) { // calculate median by sorting std::sort(timestamps.begin(), timestamps.end()); auto median = timestamps[timestamps.size()/2]; // show information - printf("Median boot time over %lu samples: %llu micros\n", + printf("Median boot time over %lu samples: %ld micros\n", timestamps.size(), median); /* for (auto& stamp : timestamps) { @@ -53,9 +51,6 @@ LiveUpdate::storage_func begin_test_boot() LiveUpdate::exec(bloberino, "test", boot_save); } } - catch (std::exception& e) { - printf("Ready to receive binary blob\n"); - } // wait for update return boot_save; }