Skip to content

Commit 0809d23

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>
1 parent 274ec71 commit 0809d23

File tree

4 files changed

+59
-4
lines changed

4 files changed

+59
-4
lines changed

config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,16 @@ config.NSFS_LOW_FREE_SPACE_MB_UNLEASH = 10 * 1024;
946946
// operations safely.
947947
config.NSFS_LOW_FREE_SPACE_PERCENT_UNLEASH = 0.10;
948948

949+
// NSFS_GLACIER_GET_FORCE_EXPIRE if set to true then any restored item in the GLACIER
950+
// storage class will expire as soon as first GET request is received for it or
951+
// if the previous restore time has exceed, whichever is the earlier.
952+
config.NSFS_GLACIER_FORCE_EXPIRE_ON_GET = false;
953+
954+
// NSFS_GLACIER_MIGRATE_LOG_THRESHOLD controls that how big the migration log file should be
955+
// Once this size is exceeded, migrate calls are supposed to kick in regardless of configured
956+
// interval
957+
config.NSFS_GLACIER_MIGRATE_LOG_THRESHOLD = 50 * 1024;
958+
949959
// anonymous account name
950960
config.ANONYMOUS_ACCOUNT_NAME = 'anonymous';
951961

src/manage_nsfs/manage_nsfs_glacier.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ async function process_migrations() {
2020

2121
if (
2222
await backend.low_free_space() ||
23-
await time_exceeded(fs_context, config.NSFS_GLACIER_MIGRATE_INTERVAL, Glacier.MIGRATE_TIMESTAMP_FILE)
23+
await time_exceeded(fs_context, config.NSFS_GLACIER_MIGRATE_INTERVAL, Glacier.MIGRATE_TIMESTAMP_FILE) ||
24+
await migrate_log_exceeds_threshold()
2425
) {
2526
await run_glacier_migrations(fs_context, backend);
2627
const timestamp_file_path = path.join(config.NSFS_GLACIER_LOGS_DIR, Glacier.MIGRATE_TIMESTAMP_FILE);
@@ -115,6 +116,20 @@ async function time_exceeded(fs_context, interval, timestamp_file) {
115116
return false;
116117
}
117118

119+
/**
120+
* migrate_log_exceeds_threshold returns true if the underlying backend
121+
* decides that the migrate log size has exceeded the given size threshold.
122+
* @param {number} [threshold]
123+
* @returns {Promise<boolean>}
124+
*/
125+
async function migrate_log_exceeds_threshold(threshold = config.NSFS_GLACIER_MIGRATE_LOG_THRESHOLD) {
126+
const log = new PersistentLogger(config.NSFS_GLACIER_LOGS_DIR, Glacier.MIGRATE_WAL_NAME, { locking: null });
127+
await log._open();
128+
129+
const { size } = await log.fh.stat(log.fs_context);
130+
return size > threshold;
131+
}
132+
118133
/**
119134
* run_glacier_operations takes a log_namespace and a callback and executes the
120135
* callback on each log file in that namespace. It will also generate a failure

src/sdk/namespace_fs.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,8 @@ class NamespaceFS {
11511151
}
11521152
}
11531153

1154+
await this._glacier_force_expire_on_get(fs_context, file_path, file, stat);
1155+
11541156
await file.close(fs_context);
11551157
file = null;
11561158
object_sdk.throw_if_aborted();
@@ -3539,6 +3541,30 @@ class NamespaceFS {
35393541
return Math.max(in_bytes, free_from_percentage);
35403542
}
35413543

3544+
/**
3545+
* _glacier_force_expire_on_get expires a object if the object has storage
3546+
* class set to GLACIER and NooBaa is configured for forced get based
3547+
* eviction
3548+
* @param {nb.NativeFSContext} fs_context
3549+
* @param {string} file_path
3550+
* @param {nb.NativeFile} file
3551+
* @param {nb.NativeFSStats} stat
3552+
*/
3553+
async _glacier_force_expire_on_get(fs_context, file_path, file, stat) {
3554+
if (!config.NSFS_GLACIER_FORCE_EXPIRE_ON_GET) return;
3555+
3556+
const storage_class = s3_utils.parse_storage_class(stat.xattr[Glacier.STORAGE_CLASS_XATTR]);
3557+
if (storage_class !== s3_utils.STORAGE_CLASS_GLACIER) return;
3558+
3559+
// Remove all the restore related xattrs
3560+
await file.replacexattr(fs_context, {
3561+
// Set date to 1970-01-01 to force expiry
3562+
[Glacier.XATTR_RESTORE_EXPIRY]: new Date(0).toISOString()
3563+
}, Glacier.XATTR_RESTORE_REQUEST);
3564+
3565+
await this.append_to_migrate_wal(file_path);
3566+
}
3567+
35423568
async append_to_migrate_wal(entry) {
35433569
if (!config.NSFS_GLACIER_LOGS_ENABLED) return;
35443570

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)