Allow RenameFile to overwrite existing files

custom
jacqueline 2 years ago
parent 7972bd4567
commit 2be4d4204c
  1. 2
      src/database/database.cpp
  2. 296
      src/database/env_esp.cpp
  3. 4
      src/database/include/env_esp.hpp
  4. 18
      src/main/main.cpp

@ -23,7 +23,7 @@ auto Database::Open() -> cpp::result<Database*, DatabaseError> {
auto status = leveldb::DB::Open(options, "/.db", &db); auto status = leveldb::DB::Open(options, "/.db", &db);
if (!status.ok()) { if (!status.ok()) {
delete cache; 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); return cpp::fail(FAILED_TO_OPEN);
} }

@ -230,7 +230,6 @@ class EspFileLock : public FileLock {
const std::string filename_; const std::string filename_;
}; };
class EspLogger final : public Logger { class EspLogger final : public Logger {
public: public:
explicit EspLogger(FIL file) : file_(file) {} explicit EspLogger(FIL file) : file_(file) {}
@ -247,8 +246,8 @@ class EspLogger final : public Logger {
snprintf(output, bytes_needed, format, args_copy); snprintf(output, bytes_needed, format, args_copy);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
va_end(args_copy); va_end(args_copy);
ESP_LOGV("LEVELDB", "%s", output); ESP_LOGI("LEVELDB", "%s", output);
//f_puts(output, &file_); // f_puts(output, &file_);
free(reinterpret_cast<void*>(output)); free(reinterpret_cast<void*>(output));
} }
@ -256,190 +255,197 @@ class EspLogger final : public Logger {
FIL file_; FIL file_;
}; };
EspEnv::~EspEnv() { EspEnv::~EspEnv() {
ESP_LOGE("LEVELDB", "EspEnv singleton destroyed. Unsupported behavior!"); 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);
}
*result = new EspSequentialFile(filename, file); Status EspEnv::NewSequentialFile(const std::string& filename,
return Status::OK(); 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, *result = new EspSequentialFile(filename, file);
RandomAccessFile** result) { return Status::OK();
// 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 EspRandomAccessFile(filename); Status EspEnv::NewRandomAccessFile(const std::string& filename,
return Status::OK(); 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, *result = new EspRandomAccessFile(filename);
WritableFile** result) { return Status::OK();
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 EspWritableFile(filename, file); Status EspEnv::NewWritableFile(const std::string& filename,
return Status::OK(); 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, *result = new EspWritableFile(filename, file);
WritableFile** result) { return Status::OK();
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); Status EspEnv::NewAppendableFile(const std::string& filename,
return Status::OK(); 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) { *result = new EspWritableFile(filename, file);
FILINFO info; return Status::OK();
return f_stat(filename.c_str(), &info) == FR_OK; }
}
Status EspEnv::GetChildren(const std::string& directory_path, bool EspEnv::FileExists(const std::string& filename) {
std::vector<std::string>* result) { FILINFO info;
result->clear(); return f_stat(filename.c_str(), &info) == FR_OK;
}
FF_DIR dir; Status EspEnv::GetChildren(const std::string& directory_path,
FRESULT res = f_opendir(&dir, directory_path.c_str()); std::vector<std::string>* result) {
if (res != FR_OK) { result->clear();
return EspError(directory_path, res);
}
FILINFO info; FF_DIR dir;
for (;;) { FRESULT res = f_opendir(&dir, directory_path.c_str());
res = f_readdir(&dir, &info); if (res != FR_OK) {
if (res != FR_OK) { return EspError(directory_path, res);
return EspError(directory_path, res); }
}
if (info.fname[0] == 0) {
break;
}
result->emplace_back(info.fname);
}
res = f_closedir(&dir); FILINFO info;
for (;;) {
res = f_readdir(&dir, &info);
if (res != FR_OK) { if (res != FR_OK) {
return EspError(directory_path, res); return EspError(directory_path, res);
} }
if (info.fname[0] == 0) {
return Status::OK(); break;
}
result->emplace_back(info.fname);
} }
Status EspEnv::RemoveFile(const std::string& filename) { res = f_closedir(&dir);
FRESULT res = f_unlink(filename.c_str()); if (res != FR_OK) {
if (res != FR_OK) { return EspError(directory_path, res);
return EspError(filename, res);
}
return Status::OK();
} }
Status EspEnv::CreateDir(const std::string& dirname) { return Status::OK();
FRESULT res = f_mkdir(dirname.c_str()); }
if (res != FR_OK) {
return EspError(dirname, res); Status EspEnv::RemoveFile(const std::string& filename) {
} FRESULT res = f_unlink(filename.c_str());
return Status::OK(); if (res != FR_OK) {
return EspError(filename, res);
} }
return Status::OK();
}
Status EspEnv::RemoveDir(const std::string& dirname) { Status EspEnv::CreateDir(const std::string& dirname) {
return RemoveFile(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) { Status EspEnv::RemoveDir(const std::string& dirname) {
FILINFO info; return RemoveFile(dirname);
FRESULT res = f_stat(filename.c_str(), &info); }
if (res != FR_OK) {
*size = 0; Status EspEnv::GetFileSize(const std::string& filename, uint64_t* size) {
return EspError(filename, res); FILINFO info;
} FRESULT res = f_stat(filename.c_str(), &info);
*size = info.fsize; if (res != FR_OK) {
return Status::OK(); *size = 0;
return EspError(filename, res);
} }
*size = info.fsize;
return Status::OK();
}
Status EspEnv::RenameFile(const std::string& from, const std::string& to) { Status EspEnv::RenameFile(const std::string& from, const std::string& to) {
FRESULT res = f_rename(from.c_str(), to.c_str()); // Match the POSIX behaviour of replacing any existing file.
if (res != FR_OK) { if (FileExists(to)) {
return EspError(from, res); 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) { Status EspEnv::LockFile(const std::string& filename, FileLock** lock) {
*lock = nullptr; *lock = nullptr;
if (!locks_.Insert(filename)) {
return Status::IOError("lock " + filename, "already held by process");
}
*lock = new EspFileLock(filename); if (!locks_.Insert(filename)) {
return Status::OK(); return Status::IOError("lock " + filename, "already held by process");
} }
Status EspEnv::UnlockFile(FileLock* lock) { *lock = new EspFileLock(filename);
EspFileLock* posix_file_lock = static_cast<EspFileLock*>(lock); return Status::OK();
locks_.Remove(posix_file_lock->filename()); }
delete posix_file_lock;
return Status::OK();
}
void EspEnv::StartThread(void (*thread_main)(void* thread_main_arg), Status EspEnv::UnlockFile(FileLock* lock) {
void* thread_main_arg) { EspFileLock* posix_file_lock = static_cast<EspFileLock*>(lock);
std::thread new_thread(thread_main, thread_main_arg); locks_.Remove(posix_file_lock->filename());
new_thread.detach(); delete posix_file_lock;
} return Status::OK();
}
Status EspEnv::GetTestDirectory(std::string* result) { void EspEnv::StartThread(void (*thread_main)(void* thread_main_arg),
CreateDir("/tmp"); void* thread_main_arg) {
*result = "/tmp"; std::thread new_thread(thread_main, thread_main_arg);
return Status::OK(); new_thread.detach();
} }
Status EspEnv::NewLogger(const std::string& filename, Logger** result) { Status EspEnv::GetTestDirectory(std::string* result) {
FIL file; CreateDir("/tmp");
FRESULT res = f_open(&file, filename.c_str(), FA_WRITE | FA_OPEN_APPEND); *result = "/tmp";
if (res != FR_OK) { return Status::OK();
*result = nullptr; }
return EspError(filename, res);
}
*result = new EspLogger(file); Status EspEnv::NewLogger(const std::string& filename, Logger** result) {
return Status::OK(); 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() { *result = new EspLogger(file);
struct timeval tv_now; return Status::OK();
gettimeofday(&tv_now, NULL); }
return (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;
}
void EspEnv::SleepForMicroseconds(int micros) { uint64_t EspEnv::NowMicros() {
vTaskDelay(pdMS_TO_TICKS(micros / 1000)); 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) { extern "C" void BackgroundThreadEntryPoint(EspEnv* env) {
env->BackgroundThreadMain(); env->BackgroundThreadMain();

@ -111,7 +111,7 @@ class EspEnv : public leveldb::Env {
InMemoryLockTable locks_; // Thread-safe. InMemoryLockTable locks_; // Thread-safe.
}; };
} // namespace leveldb } // namespace leveldb
namespace database { namespace database {
@ -149,4 +149,4 @@ class SingletonEnv {
env_storage_; env_storage_;
}; };
} // namespace database } // namespace database

@ -37,15 +37,17 @@
static const char* TAG = "MAIN"; static const char* TAG = "MAIN";
void db_main(void *whatever) { void db_main(void* whatever) {
ESP_LOGI(TAG, "Init database"); ESP_LOGI(TAG, "Init database");
std::unique_ptr<database::Database> db;
auto db_res = database::Database::Open(); auto db_res = database::Database::Open();
if (db_res.has_error()) { 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<database::Database> db(db_res.value());
ESP_LOGI(TAG, "database good :)");
vTaskDelay(pdMS_TO_TICKS(10000)); vTaskDelay(pdMS_TO_TICKS(10000));
vTaskDelete(NULL); vTaskDelete(NULL);
@ -79,9 +81,10 @@ extern "C" void app_main(void) {
ESP_LOGI(TAG, "Launch database task"); ESP_LOGI(TAG, "Launch database task");
std::size_t db_stack_size = 256 * 1024; std::size_t db_stack_size = 256 * 1024;
StaticTask_t database_task_buffer = {}; StaticTask_t database_task_buffer = {};
StackType_t *database_stack = StackType_t* database_stack = reinterpret_cast<StackType_t*>(
reinterpret_cast<StackType_t*>(heap_caps_malloc(db_stack_size, MALLOC_CAP_SPIRAM)); heap_caps_malloc(db_stack_size, MALLOC_CAP_SPIRAM));
xTaskCreateStatic(&db_main, "LEVELDB", db_stack_size, NULL, 1, database_stack, &database_task_buffer); xTaskCreateStatic(&db_main, "LEVELDB", db_stack_size, NULL, 1, database_stack,
&database_task_buffer);
ESP_LOGI(TAG, "Init touch wheel"); ESP_LOGI(TAG, "Init touch wheel");
std::shared_ptr<drivers::TouchWheel> touchwheel = std::shared_ptr<drivers::TouchWheel> touchwheel =
@ -115,4 +118,3 @@ extern "C" void app_main(void) {
vTaskDelay(pdMS_TO_TICKS(100)); vTaskDelay(pdMS_TO_TICKS(100));
} }
} }

Loading…
Cancel
Save