diff --git a/config.js b/config.js index 6ff03cf753..f72c3c69bd 100644 --- a/config.js +++ b/config.js @@ -638,7 +638,7 @@ config.INLINE_MAX_SIZE = 4096; config.OBJECT_SDK_BUCKET_CACHE_EXPIRY_MS = 60000; // Object SDK bucket_namespace_cache allow stat of the config file -config.ALLOW_BUCKET_NS_CACHE_STAT = true; +config.NC_ENABLE_BUCKET_NS_CACHE_STAT_VALIDATION = true; ////////////////////////////// // OPERATOR RELATED // diff --git a/src/sdk/bucketspace_fs.js b/src/sdk/bucketspace_fs.js index 9e678d3100..4ec1cd4099 100644 --- a/src/sdk/bucketspace_fs.js +++ b/src/sdk/bucketspace_fs.js @@ -155,7 +155,7 @@ class BucketSpaceFS extends BucketSpaceSimpleFS { } } } - bucket.stat = await this.stat_bucket(bucket.name.unwrap()); + bucket.stat = await this.stat_bucket_config_file(bucket.name.unwrap()); return bucket; } catch (err) { const rpc_error = translate_error_codes(err, entity_enum.BUCKET); @@ -165,11 +165,28 @@ class BucketSpaceFS extends BucketSpaceSimpleFS { } } + /** + * check_bucket_config will change the bucket_storage_path + * and - TODO: Bucket owner check + * @param {object} bucket + * @returns {Promise} + */ async check_bucket_config(bucket) { const bucket_storage_path = bucket.path; + return this.check_stat_bucket_storage_path(bucket_storage_path); + //TODO: Bucket owner check + } + + /** + * check_stat_bucket_storage_path will return the true + * if there is stat output on the bucket storage path + * (in case the stat throws an error it would return false) + * @param {string} bucket_storage_path + * @returns {Promise} + */ + async check_stat_bucket_storage_path(bucket_storage_path) { try { await nb_native().fs.stat(this.fs_context, bucket_storage_path); - //TODO: Bucket owner check return true; } catch (err) { return false; @@ -177,21 +194,30 @@ class BucketSpaceFS extends BucketSpaceSimpleFS { } /** - * stat_bucket will return the stat output on bucket config file + * stat_bucket_config_file will return the stat output on bucket config file * @param {string} bucket_name * @returns {Promise} */ - async stat_bucket(bucket_name) { - if (config.ALLOW_BUCKET_NS_CACHE_STAT) { + async stat_bucket_config_file(bucket_name) { + if (config.NC_ENABLE_BUCKET_NS_CACHE_STAT_VALIDATION) { try { - const bucket_config_path = this.config_fs.get_bucket_path_by_name(bucket_name); - return nb_native().fs.stat(this.fs_context, bucket_config_path); + return this.config_fs.stat_bucket_config_file(bucket_name); } catch (err) { dbg.log4('stat_bucket got an error', err, 'ignoring...'); } } } + /** + * check_same_stat will return true if both stat outputs are the same + * @param {nb.NativeFSStats} stat1 + * @param {nb.NativeFSStats} stat2 + * @returns {boolean} + */ + check_same_stat(stat1, stat2) { + return stat1.ino === stat2.ino && stat1.mtimeNsBigint === stat2.mtimeNsBigint; + } + //////////// // BUCKET // //////////// diff --git a/src/sdk/config_fs.js b/src/sdk/config_fs.js index 01b6346f74..c7ecac307c 100644 --- a/src/sdk/config_fs.js +++ b/src/sdk/config_fs.js @@ -885,6 +885,17 @@ class ConfigFS { return new_path; } + /** + * stat_bucket_config_file will return the stat output on bucket config file + * please notice that stat might throw an error - you should wrap it with try-catch and handle the error + * @param {string} bucket_name + * @returns {Promise} + */ + stat_bucket_config_file(bucket_name) { + const bucket_config_path = this.get_bucket_path_by_name(bucket_name); + return nb_native().fs.stat(this.fs_context, bucket_config_path); + } + /** * is_bucket_exists returns true if bucket config path exists in config dir * @param {string} bucket_name diff --git a/src/sdk/nb.d.ts b/src/sdk/nb.d.ts index dbd1edf117..c8d94c02e7 100644 --- a/src/sdk/nb.d.ts +++ b/src/sdk/nb.d.ts @@ -824,7 +824,8 @@ interface BucketSpace { read_account_by_access_key({ access_key: string }): Promise; read_bucket_sdk_info({ name: string }): Promise; - stat_bucket({ bucket_name: string }): Promise; // only implemented in bucketspace_fs + stat_bucket_config_file(bucket_name: string): Promise; // only implemented in bucketspace_fs + check_same_stat(current_stat:nb.NativeFSStats, new_stat: nb.NativeFSStats); // only implemented in bucketspace_fs list_buckets(params: object, object_sdk: ObjectSDK): Promise; read_bucket(params: object): Promise; diff --git a/src/sdk/object_sdk.js b/src/sdk/object_sdk.js index fc1a914d4e..6877547b07 100644 --- a/src/sdk/object_sdk.js +++ b/src/sdk/object_sdk.js @@ -287,12 +287,13 @@ class ObjectSDK { async _validate_bucket_namespace(data, params) { const time = Date.now(); // stat check (only in bucketspace FS) - const ns_allow_stat_bucket = Boolean(this._get_bucketspace().stat_bucket); + const bs = this._get_bucketspace(); + const ns_allow_stat_bucket = Boolean(bs.stat_bucket_config_file); if (ns_allow_stat_bucket) { try { - const current_stat = await this._get_bucketspace().stat_bucket(params.name); + const current_stat = await bs.stat_bucket_config_file(params.name); if (current_stat) { - const same_stat = current_stat.ino === data.stat.ino && current_stat.mtimeNsBigint === data.stat.mtimeNsBigint; + const same_stat = bs.check_same_stat(current_stat, data.bucket.stat); if (!same_stat) { // config file of bucket was changed return false; } @@ -322,7 +323,6 @@ class ObjectSDK { * ns: nb.Namespace; * bucket: object; * valid_until: number; - * stat: object; * }} */ _setup_bucket_namespace(bucket) { @@ -345,7 +345,6 @@ class ObjectSDK { ns: namespace_cache, bucket, valid_until: time + config.OBJECT_SDK_BUCKET_CACHE_EXPIRY_MS, - stat: undefined }; } if (this._is_single_namespace(bucket.namespace)) { @@ -360,7 +359,6 @@ class ObjectSDK { ), bucket, valid_until: time + config.OBJECT_SDK_BUCKET_CACHE_EXPIRY_MS, - stat: bucket.stat // will be a value only in NSFS }; } // MERGE NAMESPACE @@ -368,7 +366,6 @@ class ObjectSDK { ns: this._setup_merge_namespace(bucket), bucket, valid_until: time + config.OBJECT_SDK_BUCKET_CACHE_EXPIRY_MS, - stat: undefined }; } @@ -383,7 +380,6 @@ class ObjectSDK { ns: namespace_nb, bucket, valid_until: time + config.OBJECT_SDK_BUCKET_CACHE_EXPIRY_MS, - stat: undefined }; }