1 # Copyright (c) 2019 AT&T Intellectual Property.
2 # Copyright (c) 2018-2019 Nokia.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 # This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 # platform project (RICP).
22 """The module provides fake implementation of Shared Data Layer (SDL) database backend interface."""
24 from typing import (Dict, Set, List, Union)
25 from ricsdl.configuration import _Configuration
26 from .dbbackend_abc import DbBackendAbc
27 from .dbbackend_abc import DbBackendLockAbc
30 class FakeDictBackend(DbBackendAbc):
32 A class providing fake implementation of database backend of Shared Data Layer (SDL).
33 This class does not provide working database solution, this class can be used in testing
34 purposes only. Implementation does not provide shared database resource, SDL client sees
35 only its local local 'fake' database, which is a simple Python dictionary. Also keys are
36 stored in database under the same namespace.
39 configuration (_Configuration): SDL configuration, containing credentials to connect to
40 Redis database backend.
42 def __init__(self, configuration: _Configuration) -> None:
45 self._configuration = configuration
57 def set(self, ns: str, data_map: Dict[str, bytes]) -> None:
58 self._db.update(data_map.copy())
60 def set_if(self, ns: str, key: str, old_data: bytes, new_data: bytes) -> bool:
61 if key not in self._db:
63 db_data = self._db[key]
64 if db_data == old_data:
65 self._db[key] = new_data
69 def set_if_not_exists(self, ns: str, key: str, data: bytes) -> bool:
70 if key not in self._db:
75 def get(self, ns: str, keys: List[str]) -> Dict[str, bytes]:
82 def find_keys(self, ns: str, key_pattern: str) -> List[str]:
85 if fnmatch.fnmatch(k, key_pattern):
89 def find_and_get(self, ns: str, key_pattern: str) -> Dict[str, bytes]:
91 for key, val in self._db.items():
92 if fnmatch.fnmatch(key, key_pattern):
96 def remove(self, ns: str, keys: List[str]) -> None:
98 self._db.pop(key, None)
100 def remove_if(self, ns: str, key: str, data: bytes) -> bool:
102 db_data = self._db[key]
108 def add_member(self, ns: str, group: str, members: Set[bytes]) -> None:
109 if group in self._db:
110 self._db[group] = self._db[group] | members.copy()
112 self._db[group] = members.copy()
114 def remove_member(self, ns: str, group: str, members: Set[bytes]) -> None:
115 if group not in self._db:
117 for member in members:
118 self._db[group].discard(member)
120 def remove_group(self, ns: str, group: str) -> None:
121 self._db.pop(group, None)
123 def get_members(self, ns: str, group: str) -> Set[bytes]:
124 return self._db.get(group, set())
126 def is_member(self, ns: str, group: str, member: bytes) -> bool:
127 if group not in self._db:
129 if member in self._db[group]:
133 def group_size(self, ns: str, group: str) -> int:
134 if group not in self._db:
136 return len(self._db[group])
139 class FakeDictBackendLock(DbBackendLockAbc):
141 A class providing fake implementation of database backend lock of Shared Data Layer (SDL).
142 This class does not provide working database solution, this class can be used in testing
143 purposes only. Implementation does not provide shared database resource, SDL client sees
144 only its local local 'fake' database, which is a simple Python dictionary. Also keys are
145 stored in database under the same namespace.
147 ns (str): Namespace under which this lock is targeted.
148 name (str): Lock name, identifies the lock key in a Redis database backend.
149 expiration (int, float): Lock expiration time after which the lock is removed if it hasn't
150 been released earlier by a 'release' method.
151 redis_backend (FakeBackend): Database backend object containing fake databese connection.
154 def __init__(self, ns: str, name: str, expiration: Union[int, float],
155 redis_backend: FakeDictBackend) -> None:
156 super().__init__(ns, name)
159 self._lock_name = name
160 self._lock_expiration = expiration
161 self.redis_backend = redis_backend
166 "lock DB type": "FAKE DB",
167 "lock namespace": self._ns,
168 "lock name": self._lock_name,
169 "lock status": self._lock_status_to_string()
173 def acquire(self, retry_interval: Union[int, float] = 0.1,
174 retry_timeout: Union[int, float] = 10) -> bool:
180 def release(self) -> None:
183 def refresh(self) -> None:
186 def get_validity_time(self) -> Union[int, float]:
187 return self._lock_expiration
189 def _lock_status_to_string(self) -> str: