def async_write(self, var_names, var_ids, values, trans_id): """ Async read data by the variable name. Args: var_names: Variable name list. var_ids: Variable id list in integer. values: Variable data. trans_id: Transaction id. Returns: Status code. """ if (not isinstance(var_names, list)) or (not isinstance(var_ids, list)) \ or (not isinstance(values, list)): raise ValueError('Names, ids, values need to be list.') indexes = [] for var_id in var_ids: for index, item in enumerate(self.vars): if item.tag_id == var_id: indexes.append(index) break if not indexes: return flow_var = FlowVar(names=var_names, indexes=indexes, values=values, op_mode=GoOperation.OP_ASYNC_WRITE, op_results=[], trans_id=trans_id) self.in_queue.put(flow_var)
def refresh_worker(self): """ Overrides the base method. """ names = [] indexes = [] op_results = [] for i, var in enumerate(self.vars): names.append(var.name) indexes.append(i) op_results.append(GoStatus.S_OK) inc = 1 while self.refreshing: values = list() values.append(str(inc)) if (inc // 10) % 2: values.append(True) else: values.append(False) values.append(inc * 1.0) values.append(inc / 2.0) values.append(None) values.append(self.sim_5) flow_var = FlowVar(names, indexes, values, GoOperation.OP_REFRESH, op_results, -1) self.out_queue.put(flow_var) inc += 1 if inc > 10000: inc = 1 time.sleep(0.1)
def async_read_by_id(self, tag_ids, trans_id, callback_func): """ Async read date by the tag id. Args: tag_ids: Tag id list. If the list is empty, nothing done. trans_id: Unique transaction id. callback_func: Call back function. Raises: ValueError. """ if not isinstance(tag_ids, list): raise ValueError('tag_id is not list.') if (trans_id is None) or (callback_func is None): raise ValueError('trans_id or callback is None.') if not tag_ids: return for caller_info in self.callers: if caller_info.key == trans_id: raise ValueError('Caller existed.') caller_info = CallerInfo(key=trans_id, callback_func=callback_func, tag_ids=tag_ids) with self.caller_lock: self.callers.append(caller_info) tag_ids_copy = tag_ids[:] flow_var = FlowVar(names=None, indexes=tag_ids_copy, values=None, op_mode=GoOperation.OP_ASYNC_READ, op_results=None, trans_id=hash(caller_info)) self.request_queue.put(flow_var)
def update_main_from_secondary(self): """ Routine for update the main cache from the secondary cache. If a main entry is 'empty' or 'dummy', the operation jumps to the next entry update. """ while self.keep_updating: if self.debug: print('update secondary -> main...') for i in range(self.main.reserved_size): if (self.main.slots[i].name is not None) or \ (self.main.slots[i].name != hashtable.GO_DUMMY_KEY): self.main.slots[i].prim_value = self.secondary[i].value self.main.slots[i].time = time.time() for caller_info in self.subscribers: values = [] op_results = [] indexes = caller_info.tag_ids[:] for index in indexes: values.append(self.main.slots[index].prim_value) op_results.append(self.main.slots[index].error) flow_var = FlowVar(names=None, indexes=indexes, values=values, op_mode=GoOperation.OP_REFRESH, op_results=op_results, trans_id=hash(caller_info)) try: self.reply_queue.put_nowait(flow_var) except QueueFull: if self.debug: print('update_main_from_secondary(): OP_REFRESH - reply_queue full.') time.sleep(self.update_interval)
def write_completed(self, tag_ids, op_results, trans_id): """ Notify the service by devices putting the tag data back. Push the tag results into the reply queue. Args: tag_ids: Tag id list. op_results: Tag operation result list. trans_id: Transaction id. """ if not isinstance(tag_ids, list): raise ValueError('tag_ids is not a list.') if not isinstance(op_results, list): raise ValueError('op_results is not a list.') flow_var = FlowVar(names=None, indexes=tag_ids, values=None, op_mode=GoOperation.OP_ASYNC_WRITE, op_results=op_results, trans_id=trans_id) self.reply_queue.put(flow_var)
def request_dispatch_worker(self): """ Request queue dispatch worker. """ for flow_var in self.request_queue: if GoOperation.OP_ASYNC_READ == flow_var.op_mode: values = [] op_results = [] for tag_id in flow_var.indexes: values.append(self.main.slots[tag_id].prim_value) op_results.append(self.main.slots[tag_id].error) flow_var.values = values flow_var.op_results = op_results self.reply_queue.put(flow_var) elif GoOperation.OP_ASYNC_WRITE == flow_var.op_mode: var_grp = {} none_provider_indexes = [] for var_index, value in zip(flow_var.indexes, flow_var.values): provider = self.main.slots[var_index].provider if provider is None: none_provider_indexes.append(var_index) continue if provider in var_grp: var_grp[provider][0].append(var_index) var_grp[provider][1].append(value) else: var_grp[provider] = ([var_index], [value]) if none_provider_indexes: op_results = [GoStatus.S_INVALID_PROVIDER] * len(none_provider_indexes) none_flow_var = FlowVar(names=None, indexes=none_provider_indexes, values=None, op_mode=GoOperation.OP_ASYNC_WRITE, op_results=op_results, trans_id=flow_var.trans_id) self.reply_queue.put(none_flow_var) for key, content in var_grp.items(): key.async_write([], content[0], content[1], flow_var.trans_id) else: raise ValueError('Unexpected operation mode')
def async_write_by_id(self, tag_ids, tag_values, trans_id, callback_func): """ Async write tags by the tag id. Args: tag_ids: Tag id in list. If it is empty, nothing done. tag_values: Tag value in list. trans_id: Unique transaction id. callback_func: Callback function. Raises: ValueError Returns: """ if not isinstance(tag_ids, list): raise ValueError('tag_ids is not list') if not isinstance(tag_values, list): raise ValueError('tag_values is not list') if trans_id is None or callback_func is None: raise ValueError('trans_id or callback_func is None') if not tag_ids: return for caller_info in self.callers: if caller_info.key == trans_id: raise ValueError('Caller existed.') caller_info = CallerInfo(key=trans_id, callback_func=callback_func, tag_ids=tag_ids[:]) with self.caller_lock: self.callers.append(caller_info) tag_ids_copy = tag_ids[:] flow_var = FlowVar(names=None, indexes=tag_ids_copy, values=tag_values, op_mode=GoOperation.OP_ASYNC_WRITE, op_results=None, trans_id=hash(caller_info)) self.request_queue.put(flow_var)