Skip to content

Commit 9155431

Browse files
committed
YDA-6753: add support for async checksum calculation
1 parent 50e33cc commit 9155431

8 files changed

Lines changed: 66 additions & 59 deletions

File tree

__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from admin import *
3333
from arb import *
3434
from browse import *
35+
from checksums import *
3536
from datacite import *
3637
from folder import *
3738
from groups import *

checksums.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Functions for data object checksums."""
2+
3+
__copyright__ = 'Copyright (c) 2026, Utrecht University'
4+
__license__ = 'GPLv3, see LICENSE'
5+
6+
import irods_types
7+
8+
from util import data_object, log, msi, rule
9+
10+
__all__ = ['rule_verify_checksum']
11+
12+
13+
@rule.make()
14+
def rule_verify_checksum(ctx: rule.Context, path: str) -> None:
15+
"""Verify checksum of a data object, calculate checksum if it doesn't exist.
16+
17+
:param ctx: Combined type of a callback and rei struct
18+
:param path: Path of data object to verify
19+
"""
20+
if data_object.checksum(ctx, path):
21+
options = "verifyChksum="
22+
else:
23+
options = "ChksumAll=++++forceChksum="
24+
25+
try:
26+
msi.data_obj_chksum(ctx, path, options, irods_types.BytesBuf())
27+
checksum = data_object.checksum(ctx, path)
28+
log.write(ctx, f"Verified checksum of <{path}>: {checksum}")
29+
except Exception as e:
30+
log.write(ctx, f"Could not verify checksum of <{path}>: {str(e)}")

policies.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,9 +617,15 @@ def pep_resource_modified_post(ctx: rule.Context,
617617
# Log errors, but continue with revisions.
618618
log.write(ctx, 'rule_meta_modified_post failed: ' + str(e))
619619

620-
# ctx.uuResourceModifiedPostRevision(instance_name, zone, path)
621620
revisions.resource_modified_post_revision(ctx, instance_name, zone, path)
622621

622+
if config.enable_async_checksum:
623+
# Calculate and verify checksum of data object.
624+
ctx.delayExec(
625+
f"<PLUSET>{config.async_checksum_delay_time}s</PLUSET><INST_NAME>irods_rule_engine_plugin-irods_rule_language-instance</INST_NAME>",
626+
f"rule_verify_checksum('{path}')",
627+
"")
628+
623629

624630
@rule.make()
625631
def py_acPostProcForObjRename(ctx: rule.Context, src: str, dst: str) -> None:

rules_uu.cfg.template

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ token_lifetime =
5353
enable_inactivity_notification =
5454
inactivity_cutoff_months =
5555

56+
enable_async_checksum =
57+
async_checksum_delay_time =
58+
5659
async_replication_delay_time =
5760
async_replication_max_rss =
5861
async_revision_delay_time =

tools/verify-checksums.r

Lines changed: 0 additions & 8 deletions
This file was deleted.

util/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ def __repr__(self) -> str:
117117
token_length=0,
118118
token_lifetime=0,
119119
token_expiration_notification=0,
120+
enable_async_checksum=False,
121+
async_checksum_delay_time=0,
120122
async_replication_delay_time=0,
121123
async_replication_max_rss=1000000000,
122124
async_revision_delay_time=0,

util/data_object.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,29 @@ def size(ctx: rule.Context, path: str) -> int | None:
101101
return None
102102

103103

104+
def checksum(ctx: rule.Context, path: str) -> str | None:
105+
"""Get a data object's checksum.
106+
107+
:param ctx: Combined type of a callback and rei struct
108+
:param path: Path to iRODS data object
109+
110+
:returns: Data object's size or None if object is not found
111+
"""
112+
coll_name, data_name = pathutil.chop(path)
113+
coll_name = misc.escape(coll_name)
114+
data_name = misc.escape(data_name)
115+
iter = genquery.Query(
116+
ctx, "DATA_CHECKSUM",
117+
f"COLL_NAME = '{coll_name}' AND DATA_NAME = '{data_name}'",
118+
output=genquery.AS_LIST
119+
)
120+
121+
for row in iter:
122+
return row[0]
123+
124+
return None
125+
126+
104127
def has_replica_with_status(ctx: rule.Context, path: str, statuses: List) -> bool:
105128
"""Check if data object has replica with specified replica statuses.
106129

uuBatch.r

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)