1 # ==================================================================================
2 # Copyright (c) 2020 Nokia
3 # Copyright (c) 2020 AT&T Intellectual Property.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 # ==================================================================================
23 from ricsdl.syncstorage import SyncStorage
28 This is a wrapper around the SDL Python interface.
30 We do not embed the below directly in the Xapp classes because
31 this SDL wrapper is useful for other python apps, for example A1
32 Mediator uses this verbatim. Therefore, we leave this here as a
33 separate object so it can be used outside of xapps.
35 This class optionally uses msgpack for binary (de)serialization:
36 see https://msgpack.org/index.html
39 def __init__(self, use_fake_sdl=False):
45 use_fake_sdl: bool (optional, default False)
46 if this is True, then use SDL's in-memory backend,
47 which is very useful for testing since it allows use
48 of SDL without a running SDL or Redis instance.
49 This can be used while developing an xapp and also
50 for monkeypatching during unit testing; e.g., the xapp
51 framework unit tests do this.
54 self._sdl = SyncStorage(fake_db_backend="dict")
56 self._sdl = SyncStorage()
58 def set(self, ns, key, value, usemsgpack=True):
60 Stores a key-value pair,
61 optionally serializing the value to bytes using msgpack.
63 TODO: discuss whether usemsgpack should *default* to True or
64 False here. This seems like a usage statistic question (that we
65 don't have enough data for yet). Are more uses for an xapp to
66 write/read their own data, or will more xapps end up reading data
67 written by some other thing? I think it's too early to know.
76 Object or byte array to store. See the `usemsgpack` parameter.
77 usemsgpack: boolean (optional, default is True)
78 Determines whether the value is serialized using msgpack before storing.
79 If usemsgpack is True, the msgpack function `packb` is invoked
80 on the value to yield a byte array that is then sent to SDL.
81 Stated differently, if usemsgpack is True, the value can be anything
82 that is serializable by msgpack.
83 If usemsgpack is False, the value must be bytes.
86 value = msgpack.packb(value, use_bin_type=True)
87 self._sdl.set(ns, {key: value})
89 def get(self, ns, key, usemsgpack=True):
91 Gets the value for the specified namespace and key,
92 optionally deserializing stored bytes using msgpack.
100 usemsgpack: boolean (optional, default is True)
101 If usemsgpack is True, the byte array stored by SDL is deserialized
102 using msgpack to yield the original object that was stored.
103 If usemsgpack is False, the byte array stored by SDL is returned
104 without further processing.
109 See the usemsgpack parameter for an explanation of the returned value type.
110 Answers None if the key is not found.
113 ret_dict = self._sdl.get(ns, {key})
115 result = ret_dict[key]
117 result = msgpack.unpackb(result, raw=False)
120 def find_and_get(self, ns, prefix, usemsgpack=True):
122 Gets all key-value pairs in the specified namespace
123 with keys that start with the specified prefix,
124 optionally deserializing stored bytes using msgpack.
132 usemsgpack: boolean (optional, default is True)
133 If usemsgpack is True, every byte array stored by SDL is deserialized
134 using msgpack to yield the original value that was stored.
135 If usemsgpack is False, every byte array stored by SDL is returned
136 without further processing.
140 Dictionary of key-value pairs
141 Each key has the specified prefix.
142 See the usemsgpack parameter for an explanation of the returned value types.
143 Answers an empty dictionary if no keys matched the prefix.
146 # note: SDL "*" usage is inconsistent with real python regex, where it would be ".*"
147 ret_dict = self._sdl.find_and_get(ns, "{0}*".format(prefix))
149 ret_dict = {k: msgpack.unpackb(v, raw=False) for k, v in ret_dict.items()}
152 def delete(self, ns, key):
154 Deletes the key-value pair with the specified key in the specified namespace.
163 self._sdl.remove(ns, {key})
165 def healthcheck(self):
167 Checks if the sdl connection is healthy.
173 return self._sdl.is_active()