def next_sequence_index(shot_basedir, dt, increment=True): """Return the next sequence index for sequences in the given base directory (i.e. <experiment_shot_storage>/<script_basename>) and the date of the given datetime object, and increment the sequence index atomically on disk if increment=True. If not setting increment=True, then the result is indicative only and may be used by other code at any time. One must increment the sequence index prior to use.""" from labscript_utils.ls_zprocess import Lock from labscript_utils.shared_drive import path_to_agnostic DATE_FORMAT = '%Y-%m-%d' # The file where we store the next sequence index on disk: sequence_index_file = os.path.join(shot_basedir, '.next_sequence_index') # Open with zlock to prevent race conditions with other code: with Lock(path_to_agnostic(sequence_index_file), read_only=not increment): try: with open(sequence_index_file) as f: datestr, sequence_index = json.load(f) if datestr != dt.strftime(DATE_FORMAT): # New day, start from zero again: sequence_index = 0 except (OSError, IOError) as exc: if exc.errno != errno.ENOENT: raise # File doesn't exist yet, start from zero sequence_index = 0 if increment: # Write the new file with the incremented sequence index mkdir_p(os.path.dirname(sequence_index_file)) with open(sequence_index_file, 'w') as f: json.dump([dt.strftime(DATE_FORMAT), sequence_index + 1], f) return sequence_index
def transition_to_buffered(self,h5_file,notify_queue): # Get rid of any "remote values changed" dialog self._changed_widget.hide() self.mode = MODE_TRANSITION_TO_BUFFERED h5_file = path_to_agnostic(h5_file) # transition_to_buffered returns the final values of the run, to update the GUI with at the end of the run: transitioned_called = [self._primary_worker] front_panel_values = self.get_front_panel_values() self._final_values = yield(self.queue_work(self._primary_worker,'_transition_to_buffered',self.device_name,h5_file,front_panel_values,self._force_full_buffered_reprogram)) if self._final_values is not None: for worker in self._secondary_workers: transitioned_called.append(worker) extra_final_values = yield(self.queue_work(worker,'_transition_to_buffered',self.device_name,h5_file,front_panel_values,self.force_full_buffered_reprogram)) if extra_final_values is not None: self._final_values.update(extra_final_values) else: self._final_values = None break # If we get None back, then the worker process did not finish properly if self._final_values is None: notify_queue.put([self.device_name,'fail']) self.abort_transition_to_buffered(transitioned_called) else: if self._supports_smart_programming: self.force_full_buffered_reprogram = False self._ui.button_clear_smart_programming.setEnabled(True) # Tell the queue manager that we're done: self.mode = MODE_BUFFERED notify_queue.put([self.device_name,'success'])
def mainloop(self): # We delete shots in a separate thread so that we don't slow down the queue waiting on # network communication to acquire the lock, while True: try: event = self.event_queue.get() if event == 'close': break elif event == 'shot complete': while len(self.delete_queue) > self.n_shots_to_keep: with self.delete_queue_lock: h5_filepath = self.delete_queue.pop(0) # Acquire a lock on the file so that we don't # delete it whilst someone else has it open: with Lock(path_to_agnostic(h5_filepath)): try: os.unlink(h5_filepath) logger.info("Deleted repeated shot file %s" % h5_filepath) except OSError: logger.exception( "Couldn't delete shot file %s" % h5_filepath) else: raise ValueError(event) except Exception: logger.exception( "Exception in repeated shot deletion loop, ignoring.")
def __init__(self, name, mode=None, driver=None, libver=None, **kwds): if not isinstance(name, h5py._objects.ObjectID): self.zlock = zprocess.locking.Lock(path_to_agnostic(name)) self.zlock.acquire() try: _orig_init(self, name, mode, driver, libver, **kwds) except: if hasattr(self, 'zlock'): self.zlock.release() raise
def transition_to_buffered(self, device_name, h5file, initial_values, fresh): h5file = shared_drive.path_to_agnostic(h5file) if not self.use_zmq: return self.transition_to_buffered_sockets(h5file,self.host, self.port) response = zprocess.zmq_get_raw(self.port, self.host, data=h5file) if response != 'ok': raise Exception('invalid response from server: ' + str(response)) response = zprocess.zmq_get_raw(self.port, self.host, timeout = 10) if response != 'done': raise Exception('invalid response from server: ' + str(response)) return {} # indicates final values of buffered run, we have none
def __init__(self, name, mode=None, driver=None, libver=None, **kwds): if not isinstance(name, h5py._objects.ObjectID): kwargs = {} if _server_supports_readwrite and mode == 'r': kwargs['read_only'] = True self.zlock = zprocess.locking.Lock(path_to_agnostic(name), **kwargs) self.zlock.acquire() try: _orig_init(self, name, mode, driver, libver, **kwds) except: if hasattr(self, 'zlock'): self.zlock.release() raise
def submit_to_blacs(shot_file, host='localhost', timeout=5): """Submit a shot file to BLACS running on the given hostname. Uses port number as saved in labconfig. Returns BLACS's reponse or raises an exception if shot was not added successfully.""" from labscript_utils.labconfig import LabConfig import zprocess from labscript_utils.shared_drive import path_to_agnostic config = LabConfig() port = int(config.get('ports', 'blacs')) data = path_to_agnostic(shot_file) response = zprocess.zmq_get(port, host, data, timeout=timeout) if 'added successfully' not in response: raise Exception(response) return response
def __init__(self, name, mode=None, driver=None, libver=None, **kwds): if not isinstance(name, h5py._objects.ObjectID): kwargs = {} if mode == 'r': kwargs['read_only'] = True # Do not terminate upon SIGTERM while the file is open: self.kill_lock = kill_lock self.kill_lock.acquire() # Ask other zlock users not to open the file while we have it open: self.zlock = Lock(path_to_agnostic(name), **kwargs) self.zlock.acquire() try: _File.__init__(self, name, mode, driver, libver, **kwds) except: if hasattr(self, 'zlock'): self.zlock.release() if hasattr(self, 'kill_lock'): self.kill_lock.release() raise
def NetworkOnlyLock(name): return zprocess.locking.NetworkOnlyLock(path_to_agnostic(name))
def __init__(self, name, mode=None, driver=None, libver=None, **kwds): if not isinstance(name, h5py._objects.ObjectID): self.zlock = zprocess.locking.Lock(path_to_agnostic(name)) self.zlock.acquire() _orig_init(self, name, mode, driver, libver, **kwds)