Skip to content

Commit 3e2d2e2

Browse files
set permission for kvs file
- set permission for kvs file Fixes #99
1 parent 1b3590e commit 3e2d2e2

File tree

7 files changed

+129
-57
lines changed

7 files changed

+129
-57
lines changed

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"files.associations": {
3+
"*.rst": "cpp"
4+
}
5+
}

src/cpp/src/kvs.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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)*/
401432
score::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);

src/cpp/src/kvs.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class Kvs final {
157157
* IMPORTANT: Instead of using the Kvs::open method directly, it is recommended to use the KvsBuilder class.
158158
*
159159
*/
160-
static score::Result<Kvs> open(const InstanceId& instance_id, OpenNeedDefaults need_defaults, OpenNeedKvs need_kvs, const std::string&& dir);
160+
static score::Result<Kvs> open(const InstanceId& instance_id, OpenNeedDefaults need_defaults, OpenNeedKvs need_kvs, const std::string&& dir, score::os::Stat::Mode storage_mode);
161161

162162
/**
163163
* @brief Sets whether the key-value store should flush its contents to
@@ -383,12 +383,14 @@ class Kvs final {
383383

384384
/* Logging */
385385
std::unique_ptr<score::mw::log::Logger> logger;
386+
score::os::Stat::Mode storage_mode_;
386387

387388
/* Private Methods */
388389
score::ResultBlank snapshot_rotate();
389390
score::Result<std::unordered_map<std::string, KvsValue>> parse_json_data(const std::string& data);
390391
score::Result<std::unordered_map<std::string, KvsValue>> open_json(const score::filesystem::Path& prefix, OpenJsonNeedFile need_file);
391392
score::ResultBlank write_json_data(const std::string& buf);
393+
score::Result<bool> create_file_if_not_exist(const std::string& path);
392394

393395
};
394396

src/cpp/src/kvsbuilder.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ KvsBuilder::KvsBuilder(const InstanceId& instance_id)
2020
, need_defaults(false)
2121
, need_kvs(false)
2222
, directory("./data_folder/") /* Default Directory */
23+
, 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 */
2324
{}
2425

2526
KvsBuilder& KvsBuilder::need_defaults_flag(bool flag) {
@@ -37,6 +38,10 @@ KvsBuilder& KvsBuilder::dir(std::string&& dir_path) {
3738
return *this;
3839
}
3940

41+
KvsBuilder& KvsBuilder::storage_mode(score::os::Stat::Mode mode) {
42+
storage_mode_ = mode;
43+
return *this;
44+
}
4045

4146
score::Result<Kvs> KvsBuilder::build() {
4247
score::Result<Kvs> result = score::MakeUnexpected(ErrorCode::UnmappedError);
@@ -50,7 +55,8 @@ score::Result<Kvs> KvsBuilder::build() {
5055
instance_id,
5156
need_defaults ? OpenNeedDefaults::Required : OpenNeedDefaults::Optional,
5257
need_kvs ? OpenNeedKvs::Required : OpenNeedKvs::Optional,
53-
std::move(directory)
58+
std::move(directory),
59+
storage_mode_
5460
);
5561

5662
return result;

src/cpp/src/kvsbuilder.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ class KvsBuilder final {
8787
*/
8888
KvsBuilder& dir(std::string&& dir_path);
8989

90+
/**
91+
* @brief Specify the storage mode for the KVS files.
92+
* @param mode The storage mode to use (storage file permissions).
93+
* @return Reference to this builder (for chaining).
94+
*/
95+
KvsBuilder& storage_mode(score::os::Stat::Mode mode);
96+
9097
/**
9198
* @brief Builds and opens the Kvs instance with the configured options.
9299
*
@@ -101,6 +108,7 @@ class KvsBuilder final {
101108
bool need_defaults; ///< Whether default values are required
102109
bool need_kvs; ///< Whether an existing KVS is required
103110
std::string directory; ///< Directory where to store the KVS Files
111+
score::os::Stat::Mode storage_mode_; ///< Storage mode for the KVS files
104112
};
105113

106114
} /* namespace score::mw::per::kvs */

0 commit comments

Comments
 (0)