@@ -62,6 +62,7 @@ const XATTR_PART_ETAG = XATTR_NOOBAA_INTERNAL_PREFIX + 'part_etag';
62
62
const XATTR_VERSION_ID = XATTR_NOOBAA_INTERNAL_PREFIX + 'version_id' ;
63
63
const XATTR_DELETE_MARKER = XATTR_NOOBAA_INTERNAL_PREFIX + 'delete_marker' ;
64
64
const XATTR_DIR_CONTENT = XATTR_NOOBAA_INTERNAL_PREFIX + 'dir_content' ;
65
+ const XATTR_NON_CURRENT_TIMESTASMP = XATTR_NOOBAA_INTERNAL_PREFIX + 'non_current_timestamp' ;
65
66
const XATTR_TAG = XATTR_NOOBAA_INTERNAL_PREFIX + 'tag.' ;
66
67
const HIDDEN_VERSIONS_PATH = '.versions' ;
67
68
const NULL_VERSION_ID = 'null' ;
@@ -1399,10 +1400,10 @@ class NamespaceFS {
1399
1400
fs_xattr = this . _assign_md5_to_fs_xattr ( digest , fs_xattr ) ;
1400
1401
}
1401
1402
if ( part_upload ) {
1402
- fs_xattr = await this . _assign_part_props_to_fs_xattr ( fs_context , params . size , digest , offset , fs_xattr ) ;
1403
+ fs_xattr = this . _assign_part_props_to_fs_xattr ( params . size , digest , offset , fs_xattr ) ;
1403
1404
}
1404
1405
if ( ! part_upload && ( this . _is_versioning_enabled ( ) || this . _is_versioning_suspended ( ) ) ) {
1405
- fs_xattr = await this . _assign_versions_to_fs_xattr ( stat , fs_xattr , undefined ) ;
1406
+ fs_xattr = this . _assign_versions_to_fs_xattr ( stat , fs_xattr , undefined ) ;
1406
1407
}
1407
1408
if ( ! part_upload && params . storage_class ) {
1408
1409
fs_xattr = Object . assign ( fs_xattr || { } , {
@@ -1556,6 +1557,7 @@ class NamespaceFS {
1556
1557
await native_fs_utils . _make_path_dirs ( versioned_path , fs_context ) ;
1557
1558
await native_fs_utils . safe_move ( fs_context , latest_ver_path , versioned_path , latest_ver_info ,
1558
1559
gpfs_options ?. move_to_versions , bucket_tmp_dir_path ) ;
1560
+ await this . _set_non_current_timestamp_on_past_version ( fs_context , versioned_path ) ;
1559
1561
}
1560
1562
if ( is_dir_content ) {
1561
1563
await this . _move_directory_content_xattr_to_versioned_file ( fs_context , key , versioned_path , latest_ver_path ) ;
@@ -1597,17 +1599,19 @@ class NamespaceFS {
1597
1599
const directory_stat = await native_fs_utils . stat_ignore_enoent ( fs_context , latest_version_dir_path ) ;
1598
1600
const is_disabled_dir_content = directory_stat && directory_stat . xattr && directory_stat . xattr [ XATTR_DIR_CONTENT ] ;
1599
1601
if ( is_disabled_dir_content ) {
1602
+ let xattr = filter_fs_xattr ( directory_stat . xattr ) ;
1603
+ xattr = this . _assign_non_current_timestamp_xattr ( xattr ) ;
1600
1604
if ( this . _is_versioning_enabled ( ) ) {
1601
1605
dbg . log1 ( 'NamespaceFS._move_to_dest_version latest object is a directory object with attributes on the directory. move the xattr to the new .version file' ) ;
1602
1606
if ( versioned_path ) {
1603
- await this . set_fs_xattr_op ( fs_context , versioned_path , filter_fs_xattr ( directory_stat . xattr ) , undefined ) ;
1607
+ await this . set_fs_xattr_op ( fs_context , versioned_path , xattr , undefined ) ;
1604
1608
} else {
1605
1609
//if no versioned_path, then we have empty content dir. need to create new .folder file
1606
1610
//this scenario happens only after moving from disabled to enabled mode or after upgrade. version-id is always null
1607
1611
versioned_path = this . _get_version_path ( key , NULL_VERSION_ID , true ) ;
1608
1612
await native_fs_utils . _make_path_dirs ( versioned_path , fs_context ) ;
1609
1613
//in case of empty directory object .folder of the latest doesn't exist. use 'w' to create it if its missing
1610
- await this . set_fs_xattr_op ( fs_context , versioned_path , filter_fs_xattr ( directory_stat . xattr ) , undefined , "w" ) ;
1614
+ await this . set_fs_xattr_op ( fs_context , versioned_path , xattr , undefined , 'w' ) ;
1611
1615
}
1612
1616
}
1613
1617
await this . _clear_user_xattr ( fs_context , latest_version_dir_path , XATTR_USER_PREFIX ) ;
@@ -2384,17 +2388,30 @@ class NamespaceFS {
2384
2388
return fs_xattr ;
2385
2389
}
2386
2390
2387
- async _assign_versions_to_fs_xattr ( new_ver_stat , fs_xattr , delete_marker ) {
2391
+ /**
2392
+ * _assign_versions_to_fs_xattr assigns version related xattrs to the file
2393
+ * 1. assign version_id xattr
2394
+ * 2. if delete_marker -
2395
+ * 2.1. assigns delete_marker xattr
2396
+ * 2.2. assigns non_current_timestamp xattr - on the current structure - delete marker is under .versions/
2397
+ * @param {nb.NativeFSStats } new_ver_stat
2398
+ * @param {nb.NativeFSXattr } fs_xattr
2399
+ * @param {Boolean } [delete_marker]
2400
+ * @returns {nb.NativeFSXattr }
2401
+ */
2402
+ _assign_versions_to_fs_xattr ( new_ver_stat , fs_xattr , delete_marker = undefined ) {
2388
2403
fs_xattr = Object . assign ( fs_xattr || { } , {
2389
2404
[ XATTR_VERSION_ID ] : this . _get_version_id_by_mode ( new_ver_stat )
2390
2405
} ) ;
2391
2406
2392
- if ( delete_marker ) fs_xattr [ XATTR_DELETE_MARKER ] = delete_marker ;
2393
-
2407
+ if ( delete_marker ) {
2408
+ fs_xattr [ XATTR_DELETE_MARKER ] = String ( delete_marker ) ;
2409
+ fs_xattr = this . _assign_non_current_timestamp_xattr ( fs_xattr ) ;
2410
+ }
2394
2411
return fs_xattr ;
2395
2412
}
2396
2413
2397
- async _assign_part_props_to_fs_xattr ( fs_context , size , digest , offset , fs_xattr ) {
2414
+ _assign_part_props_to_fs_xattr ( size , digest , offset , fs_xattr ) {
2398
2415
fs_xattr = Object . assign ( fs_xattr || { } , {
2399
2416
[ XATTR_PART_SIZE ] : size ,
2400
2417
[ XATTR_PART_OFFSET ] : offset ,
@@ -2404,6 +2421,39 @@ class NamespaceFS {
2404
2421
return fs_xattr ;
2405
2422
}
2406
2423
2424
+ /**
2425
+ * _assign_non_current_timestamp_xattr assigns non current timestamp xattr to file xattr
2426
+ * @param {nb.NativeFSXattr } fs_xattr
2427
+ * @returns {nb.NativeFSXattr }
2428
+ */
2429
+ _assign_non_current_timestamp_xattr ( fs_xattr = { } ) {
2430
+ fs_xattr = Object . assign ( fs_xattr , {
2431
+ [ XATTR_NON_CURRENT_TIMESTASMP ] : String ( Date . now ( ) )
2432
+ } ) ;
2433
+ return fs_xattr ;
2434
+ }
2435
+
2436
+ /**
2437
+ * _set_non_current_timestamp_on_past_version sets non current timestamp on past version - used as a hint for lifecycle process
2438
+ * @param {nb.NativeFSContext } fs_context
2439
+ * @param {String } versioned_path
2440
+ * @returns {Promise<Void> }
2441
+ */
2442
+ async _set_non_current_timestamp_on_past_version ( fs_context , versioned_path ) {
2443
+ const xattr = this . _assign_non_current_timestamp_xattr ( ) ;
2444
+ await this . set_fs_xattr_op ( fs_context , versioned_path , xattr ) ;
2445
+ }
2446
+
2447
+ /**
2448
+ * _unset_non_current_timestamp_on_past_version unsets non current timestamp on past version - used as a hint for lifecycle process
2449
+ * @param {nb.NativeFSContext } fs_context
2450
+ * @param {String } versioned_path
2451
+ * @returns {Promise<Void> }
2452
+ */
2453
+ async _unset_non_current_timestamp_on_past_version ( fs_context , versioned_path ) {
2454
+ await this . _clear_user_xattr ( fs_context , versioned_path , XATTR_NON_CURRENT_TIMESTASMP ) ;
2455
+ }
2456
+
2407
2457
/**
2408
2458
*
2409
2459
* @param {* } fs_context - fs context object
@@ -3191,6 +3241,8 @@ class NamespaceFS {
3191
3241
const bucket_tmp_dir_path = this . get_bucket_tmpdir_full_path ( ) ;
3192
3242
await native_fs_utils . safe_move_posix ( fs_context , max_past_ver_info . path , latest_ver_path ,
3193
3243
max_past_ver_info , bucket_tmp_dir_path ) ;
3244
+ // TODO - catch error if no such xattr
3245
+ await this . _unset_non_current_timestamp_on_past_version ( fs_context , latest_ver_path ) ;
3194
3246
break ;
3195
3247
} catch ( err ) {
3196
3248
dbg . warn ( `NamespaceFS: _promote_version_to_latest failed error: retries=${ retries } ` , err ) ;
@@ -3249,8 +3301,9 @@ class NamespaceFS {
3249
3301
const bucket_tmp_dir_path = this . get_bucket_tmpdir_full_path ( ) ;
3250
3302
if ( this . _is_versioning_enabled ( ) || suspended_and_latest_is_not_null ) {
3251
3303
await native_fs_utils . _make_path_dirs ( versioned_path , fs_context ) ;
3252
- await native_fs_utils . safe_move_posix ( fs_context , latest_ver_path , versioned_path , latest_ver_info ,
3304
+ await native_fs_utils . safe_move_posix ( fs_context , latest_ver_path , versioned_path , latest_ver_info ,
3253
3305
bucket_tmp_dir_path ) ;
3306
+ await this . _set_non_current_timestamp_on_past_version ( fs_context , versioned_path ) ;
3254
3307
if ( suspended_and_latest_is_not_null ) {
3255
3308
// remove a version (or delete marker) with null version ID from .versions/ (if exists)
3256
3309
await this . _delete_null_version_from_versions_directory ( params . key , fs_context ) ;
@@ -3333,7 +3386,7 @@ class NamespaceFS {
3333
3386
}
3334
3387
const file_path = this . _get_version_path ( params . key , delete_marker_version_id , is_dir ) ;
3335
3388
3336
- const fs_xattr = await this . _assign_versions_to_fs_xattr ( stat , undefined , true ) ;
3389
+ const fs_xattr = this . _assign_versions_to_fs_xattr ( stat , undefined , true ) ;
3337
3390
if ( fs_xattr ) await upload_params . target_file . replacexattr ( fs_context , fs_xattr ) ;
3338
3391
// create .version in case we don't have it yet
3339
3392
await native_fs_utils . _make_path_dirs ( file_path , fs_context ) ;
0 commit comments