From 2be4d4204c6cb3a591be070e5d6a15a54070fc6c Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 26 Apr 2023 10:20:53 +1000 Subject: [PATCH] Allow RenameFile to overwrite existing files --- src/database/database.cpp | 2 +- src/database/env_esp.cpp | 296 ++++++++++++++++--------------- src/database/include/env_esp.hpp | 4 +- src/main/main.cpp | 18 +- 4 files changed, 164 insertions(+), 156 deletions(-) diff --git a/src/database/database.cpp b/src/database/database.cpp index 7cfd0581..558f63ce 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -23,7 +23,7 @@ auto Database::Open() -> cpp::result { auto status = leveldb::DB::Open(options, "/.db", &db); if (!status.ok()) { delete cache; - ESP_LOGE("DB", "failed to open db"); + ESP_LOGE("DB", "failed to open db, status %s", status.ToString().c_str()); return cpp::fail(FAILED_TO_OPEN); } diff --git a/src/database/env_esp.cpp b/src/database/env_esp.cpp index e525900d..45129a36 100644 --- a/src/database/env_esp.cpp +++ b/src/database/env_esp.cpp @@ -230,7 +230,6 @@ class EspFileLock : public FileLock { const std::string filename_; }; - class EspLogger final : public Logger { public: explicit EspLogger(FIL file) : file_(file) {} @@ -247,8 +246,8 @@ class EspLogger final : public Logger { snprintf(output, bytes_needed, format, args_copy); #pragma GCC diagnostic pop va_end(args_copy); - ESP_LOGV("LEVELDB", "%s", output); - //f_puts(output, &file_); + ESP_LOGI("LEVELDB", "%s", output); + // f_puts(output, &file_); free(reinterpret_cast(output)); } @@ -256,190 +255,197 @@ class EspLogger final : public Logger { FIL file_; }; - EspEnv::~EspEnv() { - ESP_LOGE("LEVELDB", "EspEnv singleton destroyed. Unsupported behavior!"); - } - - Status EspEnv::NewSequentialFile(const std::string& filename, - SequentialFile** result) { - FIL file; - FRESULT res = f_open(&file, filename.c_str(), FA_READ); - if (res != FR_OK) { - *result = nullptr; - return EspError(filename, res); - } +EspEnv::~EspEnv() { + ESP_LOGE("LEVELDB", "EspEnv singleton destroyed. Unsupported behavior!"); +} - *result = new EspSequentialFile(filename, file); - return Status::OK(); +Status EspEnv::NewSequentialFile(const std::string& filename, + SequentialFile** result) { + FIL file; + FRESULT res = f_open(&file, filename.c_str(), FA_READ); + if (res != FR_OK) { + *result = nullptr; + return EspError(filename, res); } - Status EspEnv::NewRandomAccessFile(const std::string& filename, - RandomAccessFile** result) { - // EspRandomAccessFile doesn't try to open the file until it's needed, so - // we need to first ensure the file exists to handle the NotFound case - // correctly. - FILINFO info; - FRESULT res = f_stat(filename.c_str(), &info); - if (res != FR_OK) { - *result = nullptr; - return EspError(filename, res); - } + *result = new EspSequentialFile(filename, file); + return Status::OK(); +} - *result = new EspRandomAccessFile(filename); - return Status::OK(); +Status EspEnv::NewRandomAccessFile(const std::string& filename, + RandomAccessFile** result) { + // EspRandomAccessFile doesn't try to open the file until it's needed, so + // we need to first ensure the file exists to handle the NotFound case + // correctly. + FILINFO info; + FRESULT res = f_stat(filename.c_str(), &info); + if (res != FR_OK) { + *result = nullptr; + return EspError(filename, res); } - Status EspEnv::NewWritableFile(const std::string& filename, - WritableFile** result) { - FIL file; - FRESULT res = f_open(&file, filename.c_str(), FA_WRITE | FA_CREATE_ALWAYS); - if (res != FR_OK) { - *result = nullptr; - return EspError(filename, res); - } + *result = new EspRandomAccessFile(filename); + return Status::OK(); +} - *result = new EspWritableFile(filename, file); - return Status::OK(); +Status EspEnv::NewWritableFile(const std::string& filename, + WritableFile** result) { + FIL file; + FRESULT res = f_open(&file, filename.c_str(), FA_WRITE | FA_CREATE_ALWAYS); + if (res != FR_OK) { + *result = nullptr; + return EspError(filename, res); } - Status EspEnv::NewAppendableFile(const std::string& filename, - WritableFile** result) { - FIL file; - FRESULT res = f_open(&file, filename.c_str(), FA_WRITE | FA_OPEN_APPEND); - if (res != FR_OK) { - *result = nullptr; - return EspError(filename, res); - } + *result = new EspWritableFile(filename, file); + return Status::OK(); +} - *result = new EspWritableFile(filename, file); - return Status::OK(); +Status EspEnv::NewAppendableFile(const std::string& filename, + WritableFile** result) { + FIL file; + FRESULT res = f_open(&file, filename.c_str(), FA_WRITE | FA_OPEN_APPEND); + if (res != FR_OK) { + *result = nullptr; + return EspError(filename, res); } - bool EspEnv::FileExists(const std::string& filename) { - FILINFO info; - return f_stat(filename.c_str(), &info) == FR_OK; - } + *result = new EspWritableFile(filename, file); + return Status::OK(); +} - Status EspEnv::GetChildren(const std::string& directory_path, - std::vector* result) { - result->clear(); +bool EspEnv::FileExists(const std::string& filename) { + FILINFO info; + return f_stat(filename.c_str(), &info) == FR_OK; +} - FF_DIR dir; - FRESULT res = f_opendir(&dir, directory_path.c_str()); - if (res != FR_OK) { - return EspError(directory_path, res); - } +Status EspEnv::GetChildren(const std::string& directory_path, + std::vector* result) { + result->clear(); - FILINFO info; - for (;;) { - res = f_readdir(&dir, &info); - if (res != FR_OK) { - return EspError(directory_path, res); - } - if (info.fname[0] == 0) { - break; - } - result->emplace_back(info.fname); - } + FF_DIR dir; + FRESULT res = f_opendir(&dir, directory_path.c_str()); + if (res != FR_OK) { + return EspError(directory_path, res); + } - res = f_closedir(&dir); + FILINFO info; + for (;;) { + res = f_readdir(&dir, &info); if (res != FR_OK) { return EspError(directory_path, res); } - - return Status::OK(); + if (info.fname[0] == 0) { + break; + } + result->emplace_back(info.fname); } - Status EspEnv::RemoveFile(const std::string& filename) { - FRESULT res = f_unlink(filename.c_str()); - if (res != FR_OK) { - return EspError(filename, res); - } - return Status::OK(); + res = f_closedir(&dir); + if (res != FR_OK) { + return EspError(directory_path, res); } - Status EspEnv::CreateDir(const std::string& dirname) { - FRESULT res = f_mkdir(dirname.c_str()); - if (res != FR_OK) { - return EspError(dirname, res); - } - return Status::OK(); + return Status::OK(); +} + +Status EspEnv::RemoveFile(const std::string& filename) { + FRESULT res = f_unlink(filename.c_str()); + if (res != FR_OK) { + return EspError(filename, res); } + return Status::OK(); +} - Status EspEnv::RemoveDir(const std::string& dirname) { - return RemoveFile(dirname); +Status EspEnv::CreateDir(const std::string& dirname) { + FRESULT res = f_mkdir(dirname.c_str()); + if (res != FR_OK) { + return EspError(dirname, res); } + return Status::OK(); +} - Status EspEnv::GetFileSize(const std::string& filename, uint64_t* size) { - FILINFO info; - FRESULT res = f_stat(filename.c_str(), &info); - if (res != FR_OK) { - *size = 0; - return EspError(filename, res); - } - *size = info.fsize; - return Status::OK(); +Status EspEnv::RemoveDir(const std::string& dirname) { + return RemoveFile(dirname); +} + +Status EspEnv::GetFileSize(const std::string& filename, uint64_t* size) { + FILINFO info; + FRESULT res = f_stat(filename.c_str(), &info); + if (res != FR_OK) { + *size = 0; + return EspError(filename, res); } + *size = info.fsize; + return Status::OK(); +} - Status EspEnv::RenameFile(const std::string& from, const std::string& to) { - FRESULT res = f_rename(from.c_str(), to.c_str()); - if (res != FR_OK) { - return EspError(from, res); +Status EspEnv::RenameFile(const std::string& from, const std::string& to) { + // Match the POSIX behaviour of replacing any existing file. + if (FileExists(to)) { + Status s = RemoveFile(to); + if (!s.ok()) { + return s; } - return Status::OK(); } + FRESULT res = f_rename(from.c_str(), to.c_str()); + if (res != FR_OK) { + return EspError(from, res); + } + return Status::OK(); +} - Status EspEnv::LockFile(const std::string& filename, FileLock** lock) { - *lock = nullptr; - - if (!locks_.Insert(filename)) { - return Status::IOError("lock " + filename, "already held by process"); - } +Status EspEnv::LockFile(const std::string& filename, FileLock** lock) { + *lock = nullptr; - *lock = new EspFileLock(filename); - return Status::OK(); + if (!locks_.Insert(filename)) { + return Status::IOError("lock " + filename, "already held by process"); } - Status EspEnv::UnlockFile(FileLock* lock) { - EspFileLock* posix_file_lock = static_cast(lock); - locks_.Remove(posix_file_lock->filename()); - delete posix_file_lock; - return Status::OK(); - } + *lock = new EspFileLock(filename); + return Status::OK(); +} - void EspEnv::StartThread(void (*thread_main)(void* thread_main_arg), - void* thread_main_arg) { - std::thread new_thread(thread_main, thread_main_arg); - new_thread.detach(); - } +Status EspEnv::UnlockFile(FileLock* lock) { + EspFileLock* posix_file_lock = static_cast(lock); + locks_.Remove(posix_file_lock->filename()); + delete posix_file_lock; + return Status::OK(); +} - Status EspEnv::GetTestDirectory(std::string* result) { - CreateDir("/tmp"); - *result = "/tmp"; - return Status::OK(); - } +void EspEnv::StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) { + std::thread new_thread(thread_main, thread_main_arg); + new_thread.detach(); +} - Status EspEnv::NewLogger(const std::string& filename, Logger** result) { - FIL file; - FRESULT res = f_open(&file, filename.c_str(), FA_WRITE | FA_OPEN_APPEND); - if (res != FR_OK) { - *result = nullptr; - return EspError(filename, res); - } +Status EspEnv::GetTestDirectory(std::string* result) { + CreateDir("/tmp"); + *result = "/tmp"; + return Status::OK(); +} - *result = new EspLogger(file); - return Status::OK(); +Status EspEnv::NewLogger(const std::string& filename, Logger** result) { + FIL file; + FRESULT res = f_open(&file, filename.c_str(), FA_WRITE | FA_OPEN_APPEND); + if (res != FR_OK) { + *result = nullptr; + return EspError(filename, res); } - uint64_t EspEnv::NowMicros() { - struct timeval tv_now; - gettimeofday(&tv_now, NULL); - return (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec; - } + *result = new EspLogger(file); + return Status::OK(); +} - void EspEnv::SleepForMicroseconds(int micros) { - vTaskDelay(pdMS_TO_TICKS(micros / 1000)); - } +uint64_t EspEnv::NowMicros() { + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + return (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec; +} + +void EspEnv::SleepForMicroseconds(int micros) { + vTaskDelay(pdMS_TO_TICKS(micros / 1000)); +} extern "C" void BackgroundThreadEntryPoint(EspEnv* env) { env->BackgroundThreadMain(); diff --git a/src/database/include/env_esp.hpp b/src/database/include/env_esp.hpp index c9b3fbc8..b8819b05 100644 --- a/src/database/include/env_esp.hpp +++ b/src/database/include/env_esp.hpp @@ -111,7 +111,7 @@ class EspEnv : public leveldb::Env { InMemoryLockTable locks_; // Thread-safe. }; -} // namespace leveldb +} // namespace leveldb namespace database { @@ -149,4 +149,4 @@ class SingletonEnv { env_storage_; }; -} // namespace database +} // namespace database diff --git a/src/main/main.cpp b/src/main/main.cpp index 4fb355e2..d58b07b6 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -37,15 +37,17 @@ static const char* TAG = "MAIN"; -void db_main(void *whatever) { +void db_main(void* whatever) { ESP_LOGI(TAG, "Init database"); + std::unique_ptr db; auto db_res = database::Database::Open(); if (db_res.has_error()) { - ESP_LOGE(TAG, "Failed!"); + ESP_LOGE(TAG, "database failed :("); + } else { + db.reset(db_res.value()); + ESP_LOGI(TAG, "database good :)"); } - std::unique_ptr db(db_res.value()); - ESP_LOGI(TAG, "database good :)"); vTaskDelay(pdMS_TO_TICKS(10000)); vTaskDelete(NULL); @@ -79,9 +81,10 @@ extern "C" void app_main(void) { ESP_LOGI(TAG, "Launch database task"); std::size_t db_stack_size = 256 * 1024; StaticTask_t database_task_buffer = {}; - StackType_t *database_stack = - reinterpret_cast(heap_caps_malloc(db_stack_size, MALLOC_CAP_SPIRAM)); - xTaskCreateStatic(&db_main, "LEVELDB", db_stack_size, NULL, 1, database_stack, &database_task_buffer); + StackType_t* database_stack = reinterpret_cast( + heap_caps_malloc(db_stack_size, MALLOC_CAP_SPIRAM)); + xTaskCreateStatic(&db_main, "LEVELDB", db_stack_size, NULL, 1, database_stack, + &database_task_buffer); ESP_LOGI(TAG, "Init touch wheel"); std::shared_ptr touchwheel = @@ -115,4 +118,3 @@ extern "C" void app_main(void) { vTaskDelay(pdMS_TO_TICKS(100)); } } -