Skip to content

Commit

Permalink
Fix bug: use instance variable instead of class variable in ConfigDBC…
Browse files Browse the repository at this point in the history
…onnector (sonic-net#99)

And add instance method `serialize_key` using instance variable.
  • Loading branch information
qiluo-msft authored Dec 30, 2020
1 parent 6e42d58 commit fa760c4
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions src/swsssdk/configdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
class ConfigDBConnector(SonicV2Connector):

INIT_INDICATOR = 'CONFIG_DB_INITIALIZED'
TABLE_NAME_SEPARATOR = '|'
KEY_SEPARATOR = '|'

def __init__(self, decode_responses=True, **kwargs):
# By default, connect to Redis through TCP, which does not requires root.
Expand All @@ -49,19 +47,26 @@ def __init__(self, decode_responses=True, **kwargs):
'namespace' is implicitly passed to the parent SonicV2Connector class.
"""
super(ConfigDBConnector, self).__init__(**kwargs)
# Trick: to achieve static/instance method "overload", we must use initize the function in ctor
# ref: https://stackoverflow.com/a/28766809/2514803
self.serialize_key = self._serialize_key
self.deserialize_key = self._deserialize_key

self.TABLE_NAME_SEPARATOR = '|'
self.KEY_SEPARATOR = '|'
self.handlers = {}

def __wait_for_db_init(self):
client = self.get_redis_client(self.db_name)
pubsub = client.pubsub()
initialized = client.get(self.INIT_INDICATOR)
initialized = client.get(ConfigDBConnector.INIT_INDICATOR)
if not initialized:
pattern = "__keyspace@{}__:{}".format(self.get_dbid(self.db_name), self.INIT_INDICATOR)
pattern = "__keyspace@{}__:{}".format(self.get_dbid(self.db_name), ConfigDBConnector.INIT_INDICATOR)
pubsub.psubscribe(pattern)
for item in pubsub.listen():
if item['type'] == 'pmessage':
key = item['channel'].split(':', 1)[1]
if key == self.INIT_INDICATOR:
if key == ConfigDBConnector.INIT_INDICATOR:
initialized = client.get(self.INIT_INDICATOR)
if initialized:
break
Expand Down Expand Up @@ -151,21 +156,30 @@ def typed_to_raw(self, typed_data):
raw_data[key] = str(value)
return raw_data

# Note: we could not use a class variable for KEY_SEPARATOR, but original dependent code is using
# these static functions. So we implement both static and instance functions with the same name.
# The static function will behave according to ConfigDB separators.
@staticmethod
def serialize_key(key):
def serialize_key(key, separator='|'):
if type(key) is tuple:
return ConfigDBConnector.KEY_SEPARATOR.join(key)
return separator.join(key)
else:
return str(key)

def _serialize_key(self, key):
return ConfigDBConnector.serialize_key(key, self.KEY_SEPARATOR)

@staticmethod
def deserialize_key(key):
tokens = key.split(ConfigDBConnector.KEY_SEPARATOR)
def deserialize_key(key, separator='|'):
tokens = key.split(separator)
if len(tokens) > 1:
return tuple(tokens)
else:
return key

def _deserialize_key(self, key):
return ConfigDBConnector.deserialize_key(key, self.KEY_SEPARATOR)

def set_entry(self, table, key, data):
"""Write a table entry to config db.
Remove extra fields in the db which are not in the data.
Expand Down Expand Up @@ -276,7 +290,6 @@ def delete_table(self, table):
client = self.get_redis_client(self.db_name)
pattern = '{}{}*'.format(table.upper(), self.TABLE_NAME_SEPARATOR)
keys = client.keys(pattern)
data = {}
for key in keys:
client.delete(key)

Expand Down

0 comments on commit fa760c4

Please sign in to comment.