blob: f8f2efc91e22f36e11774b082d30446b058f7fd1 [file] [log] [blame]
Tommy Carpenter21f659c2020-02-26 14:12:54 -05001# ==================================================================================
2# Copyright (c) 2020 Nokia
3# Copyright (c) 2020 AT&T Intellectual Property.
4#
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
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
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# ==================================================================================
17
Lott, Christopher (cl778h)61270902020-05-06 09:23:55 -040018"""
19sdl functionality
20"""
Tommy Carpenter21f659c2020-02-26 14:12:54 -050021
22import msgpack
23from ricsdl.syncstorage import SyncStorage
24
25
26class SDLWrapper:
27 """
28 This is a wrapper around the SDL Python interface.
29
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040030 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 seperate instantiable object so it can be used outside of xapps
34 too. One could argue this get moved into *sdl itself*.
Tommy Carpenter21f659c2020-02-26 14:12:54 -050035
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040036 We currently use msgpack for binary (de)serialization:
37 https://msgpack.org/index.html
Tommy Carpenter21f659c2020-02-26 14:12:54 -050038 """
39
40 def __init__(self, use_fake_sdl=False):
41 """
42 init
43
44 Parameters
45 ----------
46 use_fake_sdl: bool
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040047 if this is True (default: False), then SDLs "fake dict
48 backend" is used, which is very useful for testing since
49 it allows you to use SDL without any SDL or Redis deployed at
50 all. This can be used while developing your xapp, and also
51 for monkeypatching during unit testing (e.g., the xapp
52 framework unit tests do this).
Tommy Carpenter21f659c2020-02-26 14:12:54 -050053 """
54 if use_fake_sdl:
55 self._sdl = SyncStorage(fake_db_backend="dict")
56 else:
57 self._sdl = SyncStorage()
58
59 def set(self, ns, key, value, usemsgpack=True):
60 """
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040061 sets a key
Tommy Carpenter21f659c2020-02-26 14:12:54 -050062
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040063 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
68 this. So we go with True as the very first user of this, a1, does
69 this. I'm open to changing this default to False later with
70 evidence.
Tommy Carpenter21f659c2020-02-26 14:12:54 -050071
72 Parameters
73 ----------
74 ns: string
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040075 the sdl namespace
Tommy Carpenter21f659c2020-02-26 14:12:54 -050076 key: string
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040077 the sdl key
Tommy Carpenter21f659c2020-02-26 14:12:54 -050078 value:
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040079 if usemsgpack is True, value can be anything serializable by msgpack
80 if usemsgpack is False, value must be bytes
Tommy Carpenter21f659c2020-02-26 14:12:54 -050081 usemsgpack: boolean (optional)
Lott, Christopher (cl778h)bbc90282020-05-07 08:39:49 -040082 determines whether the value is serialized using msgpack
Tommy Carpenter21f659c2020-02-26 14:12:54 -050083 """
84 if usemsgpack:
85 self._sdl.set(ns, {key: msgpack.packb(value, use_bin_type=True)})
86 else:
87 self._sdl.set(ns, {key: value})
88
89 def get(self, ns, key, usemsgpack=True):
90 """
91 get a key
92
93 Parameters
94 ----------
95 ns: string
96 the sdl namespace
97 key: string
98 the sdl key
99 usemsgpack: boolean (optional)
100 if usemsgpack is True, the value is deserialized using msgpack
101 if usemsgpack is False, the value is returned as raw bytes
102
103 Returns
104 -------
105 None (if not exist) or see above; depends on usemsgpack
106 """
107 ret_dict = self._sdl.get(ns, {key})
108 if key in ret_dict:
109 if usemsgpack:
110 return msgpack.unpackb(ret_dict[key], raw=False)
111 return ret_dict[key]
112
113 return None
114
115 def find_and_get(self, ns, prefix, usemsgpack=True):
116 """
117 get all k v pairs that start with prefix
118
119 Parameters
120 ----------
121 ns: string
122 the sdl namespace
123 key: string
124 the sdl key
125 prefix: string
126 the prefix
127 usemsgpack: boolean (optional)
128 if usemsgpack is True, the value returned is a dict where each value has been deserialized using msgpack
129 if usemsgpack is False, the value returned is as a dict mapping keys to raw bytes
130
131 Returns
132 -------
133 {} (if no keys match) or see above; depends on usemsgpack
134 """
135
136 # note: SDL "*" usage is inconsistent with real python regex, where it would be ".*"
137 ret_dict = self._sdl.find_and_get(ns, "{0}*".format(prefix))
138 if usemsgpack:
139 return {k: msgpack.unpackb(v, raw=False) for k, v in ret_dict.items()}
140 return ret_dict
141
142 def delete(self, ns, key):
143 """
144 delete a key
145
146 Parameters
147 ----------
148 ns: string
149 the sdl namespace
150 key: string
151 the sdl key
152 """
153 self._sdl.remove(ns, {key})
154
155 def healthcheck(self):
156 """
157 checks if the sdl connection is healthy
158
159 Returns
160 -------
161 bool
162 """
163 return self._sdl.is_active()