def get_children(self, path, watch=None, include_data=False): self.verify() if not isinstance(path, six.string_types): raise TypeError("path must be a string") def clean_path(p): return p.strip("/") path = utils.normpath(path) with self.storage.lock: if path not in self.storage: raise k_exceptions.NoNodeError("Node %s does not exist" % (path)) paths = self.storage.get_children(path) if watch: with self._watches_lock: self._child_watchers[path].append(watch) if include_data: children_with_data = [] for (child_path, data) in six.iteritems(paths): child_path = clean_path(child_path[len(path):]) children_with_data.append((child_path, data)) return children_with_data else: children = [] for child_path in six.iterkeys(paths): child_path = clean_path(child_path[len(path):]) children.append(child_path) return children
def create(self, path, value=b"", sequence=False, ephemeral=False, session_id=None): def sequence_iter(path, parent_path): for i in itertools.count(0): sequence_id = self._sequences.get(parent_path, 0) if sequence_id == SEQ_ROLLOVER: self._sequences[parent_path] = SEQ_ROLLOVER_TO else: self._sequences[parent_path] = sequence_id + 1 yield path + '%010d' % (sequence_id) parent_path, _node_name = os.path.split(path) with self.lock: if sequence: for possible_path in sequence_iter(path, parent_path): if possible_path not in self: path = possible_path break parents = sorted(six.iterkeys(self.get_parents(path))) if parent_path not in self: if sequence: self._sequences.pop(parent_path, None) raise k_exceptions.NoNodeError( "Parent node %s does not exist" % (parent_path)) if ephemeral and not session_id: raise k_exceptions.SystemZookeeperError("Ephemeral node %s can" " not be created" " without a session" " id" % path) if path in self: raise k_exceptions.NodeExistsError("Node %s already" " exists" % (path)) for parent_path in reversed(parents): if self._paths[parent_path]['ephemeral']: raise k_exceptions.NoChildrenForEphemeralsError( "Parent %s is ephemeral" % parent_path) path_data = { # Kazoo clients expect in milliseconds 'created_on': utils.millitime(), 'updated_on': utils.millitime(), 'version': 0, # Not supported for now... 'aversion': -1, 'cversion': -1, 'data': value, } if ephemeral: path_data['ephemeral_owner'] = session_id path_data['ephemeral'] = True else: path_data['ephemeral'] = False self._paths[path] = path_data return (True, parents, path)
def get(self, path, watch=None): self.verify() if not isinstance(path, six.string_types): raise TypeError("path must be a string") path = utils.normpath(path) try: (data, znode) = self.storage.get(path) except KeyError: raise k_exceptions.NoNodeError("Node %s does not exist" % (path)) if watch: with self._watches_lock: self._data_watchers[path].append(watch) return (data, znode)
def test_update_no_node_error(self, mock_create_node_path, mock_create_node): # The first time _create_node() is called, we raise the exception. # After that we just return True so that we can pretent like the # subsequent calls in _create() work fine. mock_create_node.side_effect = [exceptions.NoNodeError('Snap'), True] self.reg._update_state(True) # The create_node_path method should be executed once. mock_create_node_path.assert_called_once_with() # The create_node method should be executed twice. mock_create_node.assert_called_twice_with()
def delete(self, path, version=-1, recursive=False): if not isinstance(path, six.string_types): raise TypeError("path must be a string") data_watches = [] child_watches = [] path = utils.normpath(path) with self.storage.lock: if path not in self.storage: raise k_exceptions.NoNodeError("Node %s does not exist" % (path)) path_version = self.storage[path]['version'] if version != -1 and path_version != version: raise k_exceptions.BadVersionError("Version mismatch" " (%s != %s)" % (version, path_version)) if recursive: paths = [path] children = self.storage.get_children(path, only_direct=False) for child_path in six.iterkeys(children): paths.append(child_path) else: children = self.storage.get_children(path, only_direct=False) if children: raise k_exceptions.NotEmptyError("Path %s is not-empty" " (%s children exist)" % (path, len(children))) paths = [path] paths = list(reversed(sorted(set(paths)))) with self.storage.transaction(): for path in paths: self.storage.pop(path) parents = [] for path in paths: parents.extend(self.storage.get_parents(path)) parents = list(reversed(sorted(set(parents)))) for path in parents: event = k_states.WatchedEvent( type=k_states.EventType.DELETED, state=k_states.KeeperState.CONNECTED, path=path) child_watches.append(([path], event)) for path in paths: event = k_states.WatchedEvent( type=k_states.EventType.DELETED, state=k_states.KeeperState.CONNECTED, path=path) data_watches.append(([path], event)) return (True, data_watches, child_watches)
def set(self, path, value, version=-1): if not isinstance(path, six.string_types): raise TypeError("path must be a string") if not isinstance(value, six.binary_type): raise TypeError("value must be a byte string") if not isinstance(version, int): raise TypeError("version must be an int") path = utils.normpath(path) try: stat = self.storage.set(path, value, version=version) except KeyError: raise k_exceptions.NoNodeError("Node %s does not exist" % (path)) data_watches = [] child_watches = [] event = k_states.WatchedEvent(type=k_states.EventType.CHANGED, state=k_states.KeeperState.CONNECTED, path=path) data_watches.append(([path], event)) return (stat, data_watches, child_watches)
def commit(self): self._check_tx_state() self._client.verify() with try_txn_lock(self._lock): self._check_tx_state() # Delay all watch firing until we are sure that it succeeded. results = [] child_watches = [] data_watches = [] try: with self._storage.transaction(): for op in self.operations: result = op() results.append(result[0]) data_watches.extend(result[1]) child_watches.extend(result[2]) except StopTransaction as e: for i in range(0, len(results)): results[i] = k_exceptions.RolledBackError() if isinstance(e, StopTransactionBadVersion): results.append(k_exceptions.BadVersionError()) if isinstance(e, StopTransactionNoExists): results.append(k_exceptions.NoNodeError()) while len(results) != len(self.operations): results.append(k_exceptions.RuntimeInconsistency()) except (NotImplementedError, AttributeError, RuntimeError, ValueError, TypeError, k_exceptions.ConnectionClosedError, k_exceptions.SessionExpiredError): # Allow all these errors to bubble up. six.reraise(*sys.exc_info()) except Exception as e: for i in range(0, len(results)): results[i] = k_exceptions.RolledBackError() results.append(e) while len(results) != len(self.operations): results.append(k_exceptions.RuntimeInconsistency()) else: self._storage.inform(self._client, child_watches, data_watches) self.committed = True return results