Skip to content

Commit 96d9dac

Browse files
committed
add support for expiring objects on GET and run
migrate if migrate log size exceeds. Signed-off-by: Utkarsh Srivastava <srivastavautkarsh8097@gmail.com> (cherry picked from commit 0809d23)
1 parent 4de4be3 commit 96d9dac

File tree

4 files changed

+61
-5
lines changed

4 files changed

+61
-5
lines changed

config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,16 @@ config.NSFS_LOW_FREE_SPACE_MB_UNLEASH = 10 * 1024;
935935
// operations safely.
936936
config.NSFS_LOW_FREE_SPACE_PERCENT_UNLEASH = 0.10;
937937

938+
// NSFS_GLACIER_GET_FORCE_EXPIRE if set to true then any restored item in the GLACIER
939+
// storage class will expire as soon as first GET request is received for it or
940+
// if the previous restore time has exceed, whichever is the earlier.
941+
config.NSFS_GLACIER_FORCE_EXPIRE_ON_GET = false;
942+
943+
// NSFS_GLACIER_MIGRATE_LOG_THRESHOLD controls that how big the migration log file should be
944+
// Once this size is exceeded, migrate calls are supposed to kick in regardless of configured
945+
// interval
946+
config.NSFS_GLACIER_MIGRATE_LOG_THRESHOLD = 50 * 1024;
947+
938948
// anonymous account name
939949
config.ANONYMOUS_ACCOUNT_NAME = 'anonymous';
940950

src/manage_nsfs/manage_nsfs_glacier.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ async function process_migrations() {
1919

2020
if (
2121
await backend.low_free_space() ||
22-
await time_exceeded(fs_context, config.NSFS_GLACIER_MIGRATE_INTERVAL, Glacier.MIGRATE_TIMESTAMP_FILE)
22+
await time_exceeded(fs_context, config.NSFS_GLACIER_MIGRATE_INTERVAL, Glacier.MIGRATE_TIMESTAMP_FILE) ||
23+
await migrate_log_exceeds_threshold()
2324
) {
2425
await run_glacier_migrations(fs_context, backend);
2526
await record_current_time(fs_context, Glacier.MIGRATE_TIMESTAMP_FILE);
@@ -167,6 +168,20 @@ async function record_current_time(fs_context, timestamp_file) {
167168
);
168169
}
169170

171+
/**
172+
* migrate_log_exceeds_threshold returns true if the underlying backend
173+
* decides that the migrate log size has exceeded the given size threshold.
174+
* @param {number} [threshold]
175+
* @returns {Promise<boolean>}
176+
*/
177+
async function migrate_log_exceeds_threshold(threshold = config.NSFS_GLACIER_MIGRATE_LOG_THRESHOLD) {
178+
const log = new PersistentLogger(config.NSFS_GLACIER_LOGS_DIR, Glacier.MIGRATE_WAL_NAME, { locking: null });
179+
await log._open();
180+
181+
const { size } = await log.fh.stat(log.fs_context);
182+
return size > threshold;
183+
}
184+
170185
/**
171186
* run_glacier_operations takes a log_namespace and a callback and executes the
172187
* callback on each log file in that namespace. It will also generate a failure
@@ -231,7 +246,8 @@ async function lock_and_run(fs_context, lockfilename, cb) {
231246
}
232247
}
233248

234-
/** prepare_galcier_fs_context returns a shallow copy of given
249+
/**
250+
* prepare_galcier_fs_context returns a shallow copy of given
235251
* fs_context with backend set to 'GPFS'.
236252
*
237253
* NOTE: The function will throw error if it detects that libgfs

src/sdk/namespace_fs.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,8 @@ class NamespaceFS {
11261126
}
11271127
}
11281128

1129+
await this._glacier_force_expire_on_get(fs_context, file_path, file, stat);
1130+
11291131
await file.close(fs_context);
11301132
file = null;
11311133
object_sdk.throw_if_aborted();
@@ -3386,6 +3388,30 @@ class NamespaceFS {
33863388
return Math.max(in_bytes, free_from_percentage);
33873389
}
33883390

3391+
/**
3392+
* _glacier_force_expire_on_get expires a object if the object has storage
3393+
* class set to GLACIER and NooBaa is configured for forced get based
3394+
* eviction
3395+
* @param {nb.NativeFSContext} fs_context
3396+
* @param {string} file_path
3397+
* @param {nb.NativeFile} file
3398+
* @param {nb.NativeFSStats} stat
3399+
*/
3400+
async _glacier_force_expire_on_get(fs_context, file_path, file, stat) {
3401+
if (!config.NSFS_GLACIER_FORCE_EXPIRE_ON_GET) return;
3402+
3403+
const storage_class = s3_utils.parse_storage_class(stat.xattr[Glacier.STORAGE_CLASS_XATTR]);
3404+
if (storage_class !== s3_utils.STORAGE_CLASS_GLACIER) return;
3405+
3406+
// Remove all the restore related xattrs
3407+
await file.replacexattr(fs_context, {
3408+
// Set date to 1970-01-01 to force expiry
3409+
[Glacier.XATTR_RESTORE_EXPIRY]: new Date(0).toISOString()
3410+
}, Glacier.XATTR_RESTORE_REQUEST);
3411+
3412+
await this.append_to_migrate_wal(file_path);
3413+
}
3414+
33893415
async append_to_migrate_wal(entry) {
33903416
if (!config.NSFS_GLACIER_LOGS_ENABLED) return;
33913417

src/util/file_reader.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ class NewlineReaderFilePathEntry {
1717

1818
class NewlineReader {
1919
/**
20-
* NewlineReader allows to read a file line by line while at max holding one line + 4096 bytes
21-
* in memory.
20+
* Newline character code
21+
*/
22+
static NL_CODE = 10;
23+
24+
/**
25+
* NewlineReader allows to read a file line by line.
2226
* @param {nb.NativeFSContext} fs_context
2327
* @param {string} filepath
2428
* @param {{
@@ -66,7 +70,7 @@ class NewlineReader {
6670
while (!this.eof) {
6771
// extract next line if terminated in current buffer
6872
if (this.start < this.end) {
69-
const term_idx = this.buf.subarray(this.start, this.end).indexOf(10);
73+
const term_idx = this.buf.subarray(this.start, this.end).indexOf(NewlineReader.NL_CODE);
7074
if (term_idx >= 0) {
7175
if (this.overflow_state) {
7276
console.warn('line too long finally terminated:', this.info());

0 commit comments

Comments
 (0)