1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 """Parameter Server Cache"""
34
35
36 import threading
37 from rosgraph.names import GLOBALNS, SEP
38
40 """
41 Cache of values on the parameter server. Implementation
42 is just a thread-safe dictionary.
43 """
44
46 self.lock = threading.Lock()
47 self.d = None
48 self.notifier = None
49
50
52 with self.lock:
53
54 if key == GLOBALNS:
55 raise KeyError("cannot delete root of parameter tree")
56 elif self.d is None:
57 raise KeyError(key)
58 else:
59
60 namespaces = [x for x in key.split(SEP) if x]
61
62 value_key = namespaces[-1]
63 namespaces = namespaces[:-1]
64 d = self.d
65
66 for ns in namespaces:
67 if type(d) != dict or ns not in d:
68 raise KeyError(key)
69 else:
70 d = d[ns]
71
72 if value_key not in d:
73 raise KeyError(key)
74 else:
75 del d[value_key]
76
78 """
79 Notifier implements any parameter subscription logic. The
80 notifier should be a function that takes in a key and value
81 that represents a parameter update. Notifier is called under
82 lock and thus must not implement any lengthy computation.
83 """
84 self.notifier = notifier
85
87 """
88 Update the value of the parameter in the cache
89 @param key: parameter key
90 @type key: str
91 @param value: parameter value
92 @type value: str
93 @raise: KeyError if key is not already in the cache.
94 """
95 with self.lock:
96
97 namespaces = [x for x in key.split(SEP) if x]
98
99 d = self.d
100 if d is None:
101 raise KeyError(key)
102 value_key = namespaces[-1]
103 namespaces = namespaces[:-1]
104
105 for ns in namespaces:
106 if ns not in d:
107 raise KeyError(key)
108 else:
109 d = d[ns]
110
111 if value_key not in d:
112 raise KeyError(key)
113
114 d[value_key] = value
115 if self.notifier is not None:
116 self.notifier(key, value)
117
118 - def set(self, key, value):
119 """
120 Set the value of the parameter in the cache. This is a
121 prerequisite of calling update().
122 @param key: parameter key
123 @type key: str
124 @param value: parameter value
125 @type value: str
126 """
127 with self.lock:
128
129 if key == GLOBALNS:
130 if type(value) != dict:
131 raise TypeError("cannot set root of parameter tree to "
132 "non-dictionary")
133 self.d = value
134 else:
135 namespaces = [x for x in key.split(SEP) if x]
136
137 value_key = namespaces[-1]
138 namespaces = namespaces[:-1]
139 if self.d is None:
140 self.d = {}
141 d = self.d
142
143 for ns in namespaces:
144 if ns not in d:
145 new_d = {}
146 d[ns] = new_d
147 d = new_d
148 else:
149 val = d[ns]
150
151 if type(val) != dict:
152 d[ns] = val = {}
153 d = val
154
155 d[value_key] = value
156
157 - def get(self, key):
158 """
159 @param key: parameter key
160 @type key: str
161 @return: Current value for parameter
162 @raise: KeyError
163 """
164 with self.lock:
165
166 if self.d is None:
167 raise KeyError(key)
168 val = self.d
169 if key != GLOBALNS:
170
171 namespaces = [x for x in key.split(SEP) if x]
172 for ns in namespaces:
173 if not type(val) == dict:
174 raise KeyError(val)
175 val = val[ns]
176 if isinstance(val, dict) and not val:
177 raise KeyError(key)
178 return val
179
180 _param_server_cache = None
189