|
12 | 12 | from irods.collection import iRODSCollection |
13 | 13 | from irods.data_object import ( |
14 | 14 | iRODSDataObject, iRODSDataObjectFileRaw, chunks, irods_dirname, irods_basename) |
| 15 | +import irods.client_configuration as client_config |
15 | 16 | import irods.keywords as kw |
16 | 17 | import irods.parallel as parallel |
17 | 18 | from irods.parallel import deferred_call |
|
20 | 21 | import json |
21 | 22 | import logging |
22 | 23 |
|
| 24 | + |
| 25 | + |
| 26 | +def call___del__if_exists(super_): |
| 27 | + """ |
| 28 | + Utility method to call __del__ if it exists anywhere in superclasses' MRO (method |
| 29 | + resolution order). |
| 30 | + """ |
| 31 | + next_finalizer_in_MRO = getattr(super_,'__del__',None) |
| 32 | + if next_finalizer_in_MRO: |
| 33 | + next_finalizer_in_MRO() |
| 34 | + |
| 35 | +class ManagedBufferedRandom(io.BufferedRandom): |
| 36 | + |
| 37 | + def __init__(self,*a,**kwd): |
| 38 | + # Help ensure proper teardown sequence by storing a reference to the session, |
| 39 | + # if provided via keyword '_session'. |
| 40 | + self._iRODS_session = kwd.pop('_session',None) |
| 41 | + super(ManagedBufferedRandom,self).__init__(*a,**kwd) |
| 42 | + import irods.session |
| 43 | + with irods.session._fds_lock: |
| 44 | + irods.session._fds[self] = None |
| 45 | + |
| 46 | + def __del__(self): |
| 47 | + if not self.closed: |
| 48 | + self.close() |
| 49 | + call___del__if_exists(super(ManagedBufferedRandom,self)) |
| 50 | + |
23 | 51 | MAXIMUM_SINGLE_THREADED_TRANSFER_SIZE = 32 * ( 1024 ** 2) |
24 | 52 |
|
25 | 53 | DEFAULT_NUMBER_OF_THREADS = 0 # Defaults for reasonable number of threads -- optimized to be |
@@ -298,9 +326,14 @@ def open_with_FileRaw(self, *arg, **kw_options): |
298 | 326 | kw.RESC_HIER_STR_KW |
299 | 327 | )) |
300 | 328 |
|
301 | | - |
302 | | - def open(self, path, mode, create = True, finalize_on_close = True, returned_values = None, allow_redirect = True, **options): |
303 | | - |
| 329 | + def open(self, path, mode, |
| 330 | + create = True, # (Dis-)allow object creation. |
| 331 | + finalize_on_close = True, # For PRC internal use. |
| 332 | + auto_close = client_config.getter('data_objects','auto_close'), # The default value will be a lambda returning the |
| 333 | + # global setting. Use True or False as an override. |
| 334 | + returned_values = None, # Used to update session reference, for forging more conns to same host, in irods.parallel.io_main |
| 335 | + allow_redirect = True, # This may be set to False to disallow the client redirect-to-resource. |
| 336 | + **options): |
304 | 337 | _raw_fd_holder = options.get('_raw_fd_holder',[]) |
305 | 338 | # If no keywords are used that would influence the server as to the choice of a storage resource, |
306 | 339 | # then use the default resource in the client configuration. |
@@ -395,8 +428,16 @@ def make_FileOpenRequest(**extra_opts): |
395 | 428 | raw.session = directed_sess |
396 | 429 |
|
397 | 430 | (_raw_fd_holder).append(raw) |
398 | | - return io.BufferedRandom(raw) |
399 | 431 |
|
| 432 | + if callable(auto_close): |
| 433 | + # Use case: auto_close has defaulted to the irods.configuration getter. |
| 434 | + # access entry in irods.configuration |
| 435 | + auto_close = auto_close() |
| 436 | + |
| 437 | + if auto_close: |
| 438 | + return ManagedBufferedRandom(raw, _session = self.sess) |
| 439 | + |
| 440 | + return io.BufferedRandom(raw) |
400 | 441 |
|
401 | 442 | def trim(self, path, **options): |
402 | 443 |
|
|
0 commit comments