@@ -38,6 +38,7 @@ Kvs::Kvs()
3838 , parser(std::make_unique<score::json::JsonParser>())
3939 , writer(std::make_unique<score::json::JsonWriter>())
4040 , logger(std::make_unique<score::mw::log::Logger>(" SKVS" ))
41+ , storage_mode_(score::os::Stat::Mode::kReadUser |score::os::Stat::Mode::kWriteUser |score::os::Stat::Mode::kReadGroup |score::os::Stat::Mode::kReadOthers ) /* Default storage mode */
4142{
4243}
4344
@@ -48,6 +49,7 @@ Kvs::Kvs(Kvs&& other) noexcept
4849 , parser(std::move(other.parser)) /* Not absolutely necessary, because a new JSON writer/parser object would also be okay*/
4950 , writer(std::move(other.writer))
5051 , logger(std::move(other.logger))
52+ , storage_mode_(other.storage_mode_)
5153{
5254 {
5355 std::lock_guard<std::mutex> lock (other.kvs_mutex );
@@ -88,6 +90,7 @@ Kvs& Kvs::operator=(Kvs&& other) noexcept
8890 parser = std::move (other.parser );
8991 writer = std::move (other.writer );
9092 logger = std::move (other.logger );
93+ storage_mode_ = other.storage_mode_ ;
9194 }
9295 return *this ;
9396}
@@ -194,7 +197,7 @@ score::Result<std::unordered_map<string, KvsValue>> Kvs::open_json(const score::
194197}
195198
196199/* Open KVS Instance */
197- score::Result<Kvs> Kvs::open (const InstanceId& instance_id, OpenNeedDefaults need_defaults, OpenNeedKvs need_kvs, const std::string&& dir)
200+ score::Result<Kvs> Kvs::open (const InstanceId& instance_id, OpenNeedDefaults need_defaults, OpenNeedKvs need_kvs, const std::string&& dir, score::os::Stat::Mode storage_mode )
198201{
199202 score::Result<Kvs> result = score::MakeUnexpected (ErrorCode::UnmappedError); /* Redundant initialization needed, since Resul<KVS> would call the implicitly-deleted default constructor of KVS */
200203
@@ -221,6 +224,7 @@ score::Result<Kvs> Kvs::open(const InstanceId& instance_id, OpenNeedDefaults nee
221224 kvs.default_values = std::move (default_res.value ());
222225 kvs.filename_prefix = filename_prefix;
223226 kvs.flush_on_exit .store (true , std::memory_order_relaxed);
227+ kvs.storage_mode_ = storage_mode;
224228 kvs.logger ->LogInfo () << " opened KVS: instance '" << instance_id.id << " '" ;
225229 kvs.logger ->LogInfo () << " max snapshot count: " << KVS_MAX_SNAPSHOTS;
226230 result = std::move (kvs);
@@ -397,6 +401,33 @@ score::ResultBlank Kvs::remove_key(const std::string_view key) {
397401 return result;
398402}
399403
404+ score::Result<bool > Kvs::create_file_if_not_exist (const std::string& path)
405+ {
406+ score::Result<bool > result = score::MakeUnexpected (ErrorCode::UnmappedError);
407+ std::unique_lock<std::mutex> lock (kvs_mutex, std::try_to_lock);
408+ if (lock.owns_lock ()) {
409+ auto isFileExist = filesystem->standard ->Exists (path);
410+ if (!isFileExist.value ()) {
411+ std::ofstream out (path, std::ios::binary);
412+ if (out) {
413+ out.close ();
414+ filesystem->standard ->Permissions (path, this ->storage_mode_ );
415+ result = true ;
416+ } else {
417+ logger->LogError () << " Failed to create file '" << path << " '" ;
418+ result = score::MakeUnexpected (ErrorCode::PhysicalStorageFailure);
419+ }
420+ } else {
421+ logger->LogInfo () << " File '" << path << " ' already exists. Skipping creation." ;
422+ result = false ;
423+ }
424+ } else {
425+ result = score::MakeUnexpected (ErrorCode::MutexLockFailed);
426+ }
427+ return result;
428+ }
429+
430+
400431/* Helper Function to write JSON data to a file for flush process (also adds Hash file)*/
401432score::ResultBlank Kvs::write_json_data (const std::string& buf)
402433{
@@ -408,13 +439,32 @@ score::ResultBlank Kvs::write_json_data(const std::string& buf)
408439 if (!create_path_res.has_value ()) {
409440 result = score::MakeUnexpected (ErrorCode::PhysicalStorageFailure);
410441 } else {
442+ auto create_file_res = create_file_if_not_exist (json_path.Native ());
443+ if (!create_file_res) {
444+ logger->LogError () << " Failed to create KVS file '" << json_path << " '" ;
445+ result = score::MakeUnexpected (static_cast <ErrorCode>(*create_file_res.error ()));
446+ } else {
447+ if (create_file_res.value ()) {
448+ logger->LogInfo () << " Created new KVS file '" << json_path << " '" ;
449+ }
450+ }
411451 std::ofstream out (json_path.CStr (), std::ios::binary);
412452 if (!out.write (buf.data (), buf.size ())) {
413453 result = score::MakeUnexpected (ErrorCode::PhysicalStorageFailure);
414454 } else {
415455 /* Write Hash File */
416456 std::array<uint8_t , 4 > hash_bytes = get_hash_bytes (buf);
417457 score::filesystem::Path fn_hash = filename_prefix.Native () + " _0.hash" ;
458+ auto create_hash_file_res = create_file_if_not_exist (fn_hash.Native ());
459+ if (!create_hash_file_res) {
460+ logger->LogError () << " Failed to create KVS hash file '" << fn_hash << " '" ;
461+ result = score::MakeUnexpected (static_cast <ErrorCode>(*create_hash_file_res.error ()));
462+ }
463+ else {
464+ if (create_hash_file_res.value ()) {
465+ logger->LogInfo () << " Created new KVS hash file '" << fn_hash << " '" ;
466+ }
467+ }
418468 std::ofstream hout (fn_hash.CStr (), std::ios::binary);
419469 if (!hout.write (reinterpret_cast <const char *>(hash_bytes.data ()), hash_bytes.size ())) {
420470 result = score::MakeUnexpected (ErrorCode::PhysicalStorageFailure);
0 commit comments