Пример #1
0
 def load_from(self, filename=None):
     """Start with a blank in memory registry, and load from the given filename"""
     if filename == None: filename = DeviceRegistry.DEFAULT_FILENAME
     # Create a new in memory store, effectively removing any existing in memory device class instances
     #TODO: Not good if there are routes to those class instances?
     self.store = KVS(filename) #TODO: later we might make it possible to load_from multiple files
     self.store.load(filename, Devices.DeviceFactory.get_device_from_name)
Пример #2
0
 def test_keys(self):
     """Get out all keys of the kvs"""
     kvs = KVS()
     kvs["tv1"] = TV(1)
     kvs["tv2"] = TV(2)
     kvs["tv3"] = TV(3)
     print(kvs.keys())
Пример #3
0
 def test_keys(self):
     """Get out all keys of the kvs"""
     kvs = KVS()
     kvs["tv1"] = TV(1)
     kvs["tv2"] = TV(2)
     kvs["tv3"] = TV(3)
     print(kvs.keys())
Пример #4
0
    def test_write(self):
        """Write an in memory KVS to a file"""
        remove_file(self.KVS_FILENAME)
        kvs = KVS()
        kvs["tv1"] = TV(1)
        kvs.write(self.KVS_FILENAME)

        show_file(self.KVS_FILENAME)
Пример #5
0
    def __init__(self):
        self.api = SublimeSocketAPI(self)
        self.kvs = KVS()

        self.transfer = None
        self.reserveRestart = None

        self.onConnectedTriggers = []
Пример #6
0
    def test_ADD_factory(self):
        #NOTE: This is an under the bonnet test of parsing an ADD record from the file
        obj = {"type": "TV", "id": 1234}
        kvs = KVS(self.KVS_FILENAME)
        kvs.ADD("tv1", obj, create_fn=FACTORY.get)

        # expected result: object described as a kvp becomes a configured object instance in store
        print(kvs.store)
Пример #7
0
    def test_write(self):
        """Write an in memory KVS to a file"""
        remove_file(self.KVS_FILENAME)
        kvs = KVS()
        kvs["tv1"] = TV(1)
        kvs.write(self.KVS_FILENAME)

        show_file(self.KVS_FILENAME)
Пример #8
0
    def test_IGN(self):
        #NOTE: This is an under the bonnet test of parsing an IGN record from the file
        obj = {"type": "TV", "id": 1234}
        kvs = KVS(self.KVS_FILENAME)
        kvs.IGN("tv1", obj)

        # expected result: no change to the in memory data structures
        print(kvs.store)
Пример #9
0
    def test_ADD_nofactory(self):
        #NOTE: This is an under the bonnet test of parsing an ADD record from the file

        # No factory callback provided, use ADD parse action
        obj = {"type": "MIHO005", "id": 1234}
        kvs = KVS(self.KVS_FILENAME)
        kvs.ADD("tv1", obj)

        # expected result: object described as a kvp becomes a kvp in the store if no factory callback
        print(kvs.store)
Пример #10
0
 def test_size(self):
     """How big is the kvs"""
     kvs = KVS()
     kvs["tv1"] = TV(1)
     print(len(kvs))
     kvs["tv2"] = TV(2)
     print(len(kvs))
Пример #11
0
    def test_change(self):
        """Change the value associated with an existing key"""
        kvs = KVS()
        kvs["tv1"] = TV(1)
        kvs["tv1"] = TV(111)  # change it

        print(kvs.store)
Пример #12
0
    def test_add(self):
        """Add an object into the kvs store"""
        kvs = KVS()

        kvs["tv1"] = TV(1)
        kvs["tv2"] = TV(2)

        print(kvs.store)
Пример #13
0
	def __init__(self):
		self.api = SublimeSocketAPI(self)
		self.kvs = KVS()

		self.transfer = None
		self.reserveRestart = None

		self.onConnectedTriggers = []
Пример #14
0
    def test_add(self):
        """Add a new record to a persisted KVS"""
        remove_file(self.KVS_FILENAME)
        kvs = KVS(self.KVS_FILENAME)

        kvs["tv1"] = TV(1)

        print(kvs.store)
        show_file(self.KVS_FILENAME)
Пример #15
0
    def test_change(self):
        """Change an existing record in a persisted KVS"""
        remove_file(self.KVS_FILENAME)
        kvs = KVS(self.KVS_FILENAME)

        kvs["tv1"] = TV(1)
        show_file(self.KVS_FILENAME)

        kvs["tv1"] = TV(2)
        show_file(self.KVS_FILENAME)
Пример #16
0
    def test_DEL(self):
        #NOTE: This is an under the bonnet test of parsing a DEL record from the file

        #NOTE: This is an under the bonnet test of parsing an IGN record from the file
        obj = {"type": "TV", "id": 1234}
        kvs = KVS(self.KVS_FILENAME)
        kvs.ADD("tv1", obj)
        kvs.DEL("tv1", obj)

        # expected result: record is deleted from in memory store
        print(kvs.store)

        try:
            kvs.DEL("tv1", obj)
            self.fail("Did not get expected KeyError")
        except KeyError:
            pass  # expected
        # expected result: error if it was not in the store in the first place
        print(kvs.store)
Пример #17
0
    def test_delete(self):
        """Delete an existing key in the store, and a missing key for error"""
        kvs = KVS()
        kvs["tv1"] = TV(1)
        del kvs["tv1"]
        print(kvs.store)

        try:
            del kvs["tv1"]  # expect error
            self.fail("Did not get expected KeyError exception")
        except KeyError:
            pass  # expected
Пример #18
0
    def test_not_persistable(self):
        class NPC():
            pass

        remove_file(self.KVS_FILENAME)
        kvs = KVS(self.KVS_FILENAME)

        try:
            kvs["npc"] = NPC()  # should throw NotPersistableError
            self.fail("Did not get expected NotPersistableError")
        except NotPersistableError:
            pass  # expected
Пример #19
0
    def test_load_process(self):
        """Load and process a file with lots of records in it"""
        CONTENTS = """\
ADD tv
type=TV
id=1

IGN fan
type=TV
id=2

DEL tv

ADD fridge
type=TV
id=99
"""
        write_file(self.KVS_FILENAME, CONTENTS)

        kvs = KVS(self.KVS_FILENAME)
        kvs.load(create_fn=FACTORY.get)

        print(kvs.store)
Пример #20
0
    def test_load_process(self):
        """Load and process a file with lots of records in it"""
        CONTENTS = """\
ADD tv
type=TV
id=1

IGN fan
type=TV
id=2

DEL tv

ADD fridge
type=TV
id=99
"""
        write_file(self.KVS_FILENAME, CONTENTS)

        kvs = KVS(self.KVS_FILENAME)
        kvs.load(create_fn=FACTORY.get)

        print(kvs.store)
Пример #21
0
    def test_delete(self):
        """Delete an existing key from the persistent version"""

        remove_file(self.KVS_FILENAME)
        kvs = KVS(self.KVS_FILENAME)

        kvs["tv1"] = TV(1)
        kvs["tv2"] = TV(2)
        kvs["tv3"] = TV(3)
        kvs["tv4"] = TV(4)

        show_file(self.KVS_FILENAME)

        del kvs["tv1"]
Пример #22
0
    def test_load_cache(self):
        """Load record from a kvs file into the kvs cache"""
        # create a file to test against
        remove_file(self.KVS_FILENAME)
        kvs = KVS()
        kvs["tv1"] = TV(1)
        kvs.write(self.KVS_FILENAME)

        kvs = KVS()  # clear it out again

        # load the file
        kvs.load(self.KVS_FILENAME)

        # check the state of the kvs memory
        print(kvs.store)

        # check state of the kvs file at end
        show_file(self.KVS_FILENAME)
Пример #23
0
    def test_load_cache(self):
        """Load record from a kvs file into the kvs cache"""
        # create a file to test against
        remove_file(self.KVS_FILENAME)
        kvs = KVS()
        kvs["tv1"] = TV(1)
        kvs.write(self.KVS_FILENAME)

        kvs = KVS() # clear it out again

        # load the file
        kvs.load(self.KVS_FILENAME)

        # check the state of the kvs memory
        print(kvs.store)

        # check state of the kvs file at end
        show_file(self.KVS_FILENAME)
Пример #24
0
###################
#preparation phase#
###################

with open('config.json') as d:
    config = json.load(d)

#Total number of servers
n_servers = config["servers"]
#Total number of tolerated failures
f_servers = (n_servers - 1) / 3

kvsArray = {}
for i in range(0, n_servers):
    c = config['KVS_IPs'][i]
    kvsArray[i] = KVS(c['ip'], c['port'])

##################
#       API      #
##################


#write method - writes the value under the key in a majority (2*f+1) of the KVS
#in order to provide fault tolerance
def write(key, value):
    responses = 0
    i = 0

    while responses < (f_servers * 2 + 1) and i < n_servers:
        try:
            kvsArray[i].write(key, value)
Пример #25
0
 def test_get(self):
     """Get the object associated with a key in the store"""
     kvs = KVS()
     kvs["tv1"] = TV(1)
     t = kvs["tv1"]
     print(t)
Пример #26
0
class DeviceRegistry(): # this is actions, so is this the 'RegistRAR'??
    """A persistent registry for device class instance configurations"""

    DEFAULT_FILENAME = "registry.kvs"

    def __init__(self, filename=None):
        ##print("***Opening DeviceRegistry")
        self.store = KVS(filename)
        self.fsk_router = None

    def set_fsk_router(self, fsk_router):
        self.fsk_router = fsk_router

    def load_from(self, filename=None):
        """Start with a blank in memory registry, and load from the given filename"""
        if filename == None: filename = DeviceRegistry.DEFAULT_FILENAME
        # Create a new in memory store, effectively removing any existing in memory device class instances
        #TODO: Not good if there are routes to those class instances?
        self.store = KVS(filename) #TODO: later we might make it possible to load_from multiple files
        self.store.load(filename, Devices.DeviceFactory.get_device_from_name)

    def load_into(self, context):
        """auto-create variables in the provided context, for all persisted registry entries"""
        if context == None:
            raise ValueError("Must provide a context to hold new variables")

        for name in self.store.keys():
            c = self.get(name)
            # This creates a variable inside the context of this name, points to class instance
            setattr(context, name, c)

    def add(self, device, name):
        """Add a device class instance to the registry, with a friendly name"""
        self.store[name] = device

    def get(self, name): # -> Device
        """Get the description for a device class from the store, and construct a class instance"""
        c = self.store[name]

        if self.fsk_router != None:
            if c.can_send(): # if can transmit, we can receive from it
                if isinstance(c, Devices.MiHomeDevice):
                    print("Adding rx route for transmit enabled device %s" % c)
                    address = (c.manufacturer_id, c.product_id, c.device_id)
                    self.fsk_router.add(address, c)
        return c

    def rename(self, old_name, new_name):
        """Rename a device in the registry"""
        c = self.store[old_name] # get the class instance
        self.delete(old_name) # remove from memory and from any disk version
        self.add(c, new_name) # Add the same class back, but with the new name
        #Note: If rx routes are defined, they will still be correct,
        # because they wire directly to the device class instance

    def delete(self, name):
        """Delete the named class instance"""
        del self.store[name]

    def list(self):
        """List the registry in a vaguely printable format, mostly for debug"""
        print("REGISTERED DEVICES:")
        for k in self.store.keys():
            print("  %s -> %s" % (k, self.store[k]))

    def size(self):
        """How many entries are there in the registry?"""
        return self.store.size()

    def devices(self):
        """A generator/iterator that can be used to get a list of device instances"""

        # Python2 and Python3 safe
        for k in self.store.keys():
            device = self.store[k]
            yield device

        # first get a list of all devices, in case the registry changes while iterating
        ##devices = self.store.keys()

        # now 'generate' one per call
        ##i = 0
        ##while i < len(devices):
        ##    k = devices[i]
        ##    device = self.store[k]
        ##    yield device
        ##    i += 1

    def names(self):
        """A generator/iterator that can be used to get a list of device names"""
        # first get a list of all devices, in case the registry changes while iterating
        devices = list(self.store.keys())

        # now 'generate' one per call
        i = 0
        while i < len(devices):
            k = devices[i]
            yield k
            i += 1
Пример #27
0
 def __init__(self, filename=None):
     ##print("***Opening DeviceRegistry")
     self.store = KVS(filename)
     self.fsk_router = None
Пример #28
0
 def test_create_blank(self):
     """Create a blank kvs, not bound to any external file"""
     kvs = KVS()
Пример #29
0
class SublimeSocketServer:
    def __init__(self):
        self.api = SublimeSocketAPI(self)
        self.kvs = KVS()

        self.transfer = None
        self.reserveRestart = None

        self.onConnectedTriggers = []

    # control server self.

    def resetServer(self):
        self.refreshKVS()
        self.teardownTransfer()

    def teardownServer(self):
        self.resetServer()
        # teardowned will call.

    def refreshKVS(self):
        self.clearAllKeysAndValues()

    def transferTeardowned(self, message):
        self.api.editorAPI.printMessage(message + "\n")
        self.api.editorAPI.statusMessage(message)

        self.transfer = None

        # run when restert reserved.
        if self.reserveRestart:
            self.setupTransfer(*self.reserveRestart)

            self.spinupTransfer()
            self.reserveRestart = None

    def transferNoticed(self, message):
        self.api.editorAPI.printMessage(message)

    def transferSpinupFailed(self, message):
        self.api.editorAPI.printMessage(message)
        self.api.editorAPI.statusMessage(message)

    def transferSpinupped(self, message):
        self.api.editorAPI.printMessage(message)
        self.api.editorAPI.statusMessage(message)

        # react to renew
        self.onTransferRenew()

    def transferConnected(self, clientId):
        if self.onConnectedTriggers:
            for funcDict in self.onConnectedTriggers:
                for _, func in funcDict.items():
                    func()
        self.onConnectedTriggers = []

    # main API data incoming method.
    def transferInputted(self, data, clientId):
        apiData = data.split(SublimeSocketAPISettings.SSAPI_DEFINE_DELIM, 1)[1]

        def runInMainThread():
            self.api.parse(apiData, clientId)

        self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0)

    def showTransferInfo(self):
        if self.transfer:
            return self.transfer.info()

        else:
            return "no transfer running."

    # control transfer.

    def setupTransfer(self, transferMethod, params):
        if self.transfer:
            message = "SublimeSocket already running." + self.transfer.info()
            self.api.editorAPI.printMessage(message + "\n")
            self.api.editorAPI.statusMessage(message)

        else:
            if transferMethod in SublimeSocketAPISettings.TRANSFER_METHODS:

                for case in PythonSwitch(transferMethod):
                    if case(SublimeSocketAPISettings.WEBSOCKET_SERVER):
                        self.transfer = WSServer(self)
                        self.transfer.setup(params)
                        break

        self.currentTransferMethod = transferMethod

    def spinupTransfer(self):
        if self.transfer:
            self.transfer.spinup()

    def restartTransfer(self):
        if self.transfer:
            # reserve restart
            self.reserveRestart = self.transfer.currentArgs()
            self.teardownTransfer()
        else:
            self.transferSpinupFailed("no transfer running.")

    def teardownTransfer(self):
        if self.transfer:
            self.transfer.teardown()
        else:
            self.transferTeardowned("no transfer running.")

    def appendOnConnectedTriggers(self, func):
        for addedFunctionDict in self.onConnectedTriggers:
            if func.__name__ in addedFunctionDict.keys():
                print("duplicate trigger:" + str(func))
                return

        self.onConnectedTriggers.append({func.__name__: func})

    # message series

    def sendMessage(self, targetId, message):
        return self.transfer.sendMessage(targetId, message)

    def broadcastMessage(self, targetIds, message):
        return self.transfer.broadcastMessage(targetIds, message)

    # purge
    def purgeConnection(self, targetId):
        self.transfer.purgeConnection(targetId)

    # other series

    def onTransferRenew(self):
        def runInMainThread():
            settingCommands = self.api.editorAPI.loadSettings(
                "onTransferRenew")
            for command in settingCommands:
                self.api.runAPI(command, None)

        self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0)

    # KVS bridge series

    def clearAllKeysAndValues(self):
        self.kvs.clear()

    def showAllKeysAndValues(self):
        everything = self.kvs.getAll()
        print("everything", everything)

    # views and KVS
    def viewsDict(self):
        viewsDict = self.kvs.get(SublimeSocketAPISettings.DICT_VIEWS)

        if viewsDict:
            return viewsDict

        return {}

    def updateViewsDict(self, viewsDict):
        self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_VIEWS, viewsDict)

    # regions and KVS
    def storeRegion(self, path, identity, line, regionFrom, regionTo, message):
        regionsDict = self.regionsDict()

        if path in regionsDict:
            if identity in regionsDict[path]:
                pass
            else:
                regionsDict[path][identity] = {}
                regionsDict[path][identity][
                    SublimeSocketAPISettings.REGION_LINE] = line
                regionsDict[path][identity][
                    SublimeSocketAPISettings.REGION_FROM] = regionFrom
                regionsDict[path][identity][
                    SublimeSocketAPISettings.REGION_TO] = regionTo
                regionsDict[path][identity][
                    SublimeSocketAPISettings.REGION_MESSAGES] = []
        else:
            regionsDict[path] = {}
            regionsDict[path][identity] = {}
            regionsDict[path][identity][
                SublimeSocketAPISettings.REGION_LINE] = line
            regionsDict[path][identity][
                SublimeSocketAPISettings.REGION_FROM] = regionFrom
            regionsDict[path][identity][
                SublimeSocketAPISettings.REGION_TO] = regionTo
            regionsDict[path][identity][
                SublimeSocketAPISettings.REGION_MESSAGES] = []

        if not message in regionsDict[path][identity][
                SublimeSocketAPISettings.REGION_MESSAGES]:
            regionsDict[path][identity][
                SublimeSocketAPISettings.REGION_MESSAGES].insert(0, message)

            self.updateRegionsDict(regionsDict)

    def regionsDict(self):
        regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS)

        if regionsDict:
            return regionsDict

        return {}

    def updateRegionsDict(self, regionsDict):
        self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REGIONS,
                             regionsDict)

    def selectingRegionIds(self, path):
        regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS)

        if path in regionsDict:
            selectingRegionIds = [
                regionId
                for regionId, regionDatas in regionsDict[path].items()
                if SublimeSocketAPISettings.REGION_ISSELECTING in regionDatas
                and regionDatas[
                    SublimeSocketAPISettings.REGION_ISSELECTING] == 1
            ]

            return selectingRegionIds

        return []

    def updateSelectingRegionIdsAndResetOthers(self, path, selectingRegionIds):
        regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS)

        if path in regionsDict:
            regions = regionsDict[path]
            allRegionIds = list(regions)

            unselectedRegionIds = set(allRegionIds) - set(selectingRegionIds)

            for selectingRegionId in selectingRegionIds:
                regions[selectingRegionId][
                    SublimeSocketAPISettings.REGION_ISSELECTING] = 1

            for unselectdRegionid in unselectedRegionIds:
                regions[unselectdRegionid][
                    SublimeSocketAPISettings.REGION_ISSELECTING] = 0

    # reactor and KVS
    def reactorsDict(self):
        reactorsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REACTORS)
        if reactorsDict:
            return reactorsDict

        return {}

    def updateReactorsDict(self, reactorsDict):
        self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORS,
                             reactorsDict)

    # reactorsLog and KVS
    def reactorsLogDict(self):
        reactorsLogDict = self.kvs.get(
            SublimeSocketAPISettings.DICT_REACTORSLOG)

        if reactorsLogDict:
            return reactorsLogDict

        return {}

    def updateReactorsLogDict(self, reactorsLogDict):
        self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORSLOG,
                             reactorsLogDict)

    # completions and KVS
    def completionsDict(self):
        completionsDict = self.kvs.get(
            SublimeSocketAPISettings.DICT_COMPLETIONS)
        if completionsDict:
            return completionsDict

        return {}

    def deleteCompletion(self, identity):
        completionsDict = self.kvs.get(
            SublimeSocketAPISettings.DICT_COMPLETIONS)
        del completionsDict[identity]
        self.updateCompletionsDict(completionsDict)

    def updateCompletionsDict(self, completionsDict):
        self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_COMPLETIONS,
                             completionsDict)

    # filters and KVS
    def filtersDict(self):
        filtersDict = self.kvs.get(SublimeSocketAPISettings.DICT_FILTERS)

        if filtersDict:
            return filtersDict

        return {}

    def updateFiltersDict(self, filtersDict):
        self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_FILTERS,
                             filtersDict)
Пример #30
0
class DeviceRegistry():  # this is actions, so is this the 'RegistRAR'??
    """A persistent registry for device class instance configurations"""

    DEFAULT_FILENAME = "registry.kvs"

    def __init__(self, filename=None):
        ##print("***Opening DeviceRegistry")
        self.store = KVS(filename)
        self.fsk_router = None

    def set_fsk_router(self, fsk_router):
        self.fsk_router = fsk_router

    def load_from(self, filename=None):
        """Start with a blank in memory registry, and load from the given filename"""
        if filename == None: filename = DeviceRegistry.DEFAULT_FILENAME
        # Create a new in memory store, effectively removing any existing in memory device class instances
        #TODO: Not good if there are routes to those class instances?
        self.store = KVS(
            filename
        )  #TODO: later we might make it possible to load_from multiple files
        self.store.load(filename, Devices.DeviceFactory.get_device_from_name)

    def load_into(self, context):
        """auto-create variables in the provided context, for all persisted registry entries"""
        if context == None:
            raise ValueError("Must provide a context to hold new variables")

        for name in self.store.keys():
            c = self.get(name)
            # This creates a variable inside the context of this name, points to class instance
            setattr(context, name, c)

    def add(self, device, name):
        """Add a device class instance to the registry, with a friendly name"""
        self.store[name] = device

    def get(self, name):  # -> Device
        """Get the description for a device class from the store, and construct a class instance"""
        c = self.store[name]

        if self.fsk_router != None:
            if c.can_send():  # if can transmit, we can receive from it
                if isinstance(c, Devices.MiHomeDevice):
                    #print("Adding rx route for transmit enabled device %s" % c)
                    address = (c.manufacturer_id, c.product_id, c.device_id)
                    self.fsk_router.add(address, c)
        return c

    def rename(self, old_name, new_name):
        """Rename a device in the registry"""
        c = self.store[old_name]  # get the class instance
        self.delete(old_name)  # remove from memory and from any disk version
        self.add(c, new_name)  # Add the same class back, but with the new name
        #Note: If rx routes are defined, they will still be correct,
        # because they wire directly to the device class instance

    def delete(self, name):
        """Delete the named class instance"""
        del self.store[name]

    def list(self):
        """List the registry in a vaguely printable format, mostly for debug"""
        print("REGISTERED DEVICES:")
        for k in self.store.keys():
            print("  %s -> %s" % (k, self.store[k]))

    def size(self):
        """How many entries are there in the registry?"""
        return self.store.size()

    def devices(self):
        """A generator/iterator that can be used to get a list of device instances"""

        # Python2 and Python3 safe
        for k in self.store.keys():
            device = self.store[k]
            yield device

        # first get a list of all devices, in case the registry changes while iterating
        ##devices = self.store.keys()

        # now 'generate' one per call
        ##i = 0
        ##while i < len(devices):
        ##    k = devices[i]
        ##    device = self.store[k]
        ##    yield device
        ##    i += 1

    def names(self):
        """A generator/iterator that can be used to get a list of device names"""
        # first get a list of all devices, in case the registry changes while iterating
        devices = list(self.store.keys())

        # now 'generate' one per call
        i = 0
        while i < len(devices):
            k = devices[i]
            yield k
            i += 1
Пример #31
0
 def __init__(self, filename=None):
     ##print("***Opening DeviceRegistry")
     self.store = KVS(filename)
     self.fsk_router = None
Пример #32
0
class SublimeSocketServer:
	def __init__(self):
		self.api = SublimeSocketAPI(self)
		self.kvs = KVS()

		self.transfer = None
		self.reserveRestart = None

		self.onConnectedTriggers = []

	# control server self.

	def resetServer(self):
		self.refreshKVS()
		self.teardownTransfer()

	def teardownServer(self):
		self.resetServer()
		# teardowned will call.
	
	def refreshKVS(self):
		self.clearAllKeysAndValues()

	def transferTeardowned(self, message):
		self.api.editorAPI.printMessage(message + "\n")
		self.api.editorAPI.statusMessage(message)

		self.transfer = None

		# run when restert reserved.
		if self.reserveRestart:
			self.setupTransfer(*self.reserveRestart)

			self.spinupTransfer()
			self.reserveRestart = None

	
	def transferNoticed(self, message):
		self.api.editorAPI.printMessage(message)

	def transferSpinupFailed(self, message):
		self.api.editorAPI.printMessage(message)
		self.api.editorAPI.statusMessage(message)

	def transferSpinupped(self, message):
		self.api.editorAPI.printMessage(message)
		self.api.editorAPI.statusMessage(message)

		# react to renew
		self.onTransferRenew()

	def transferConnected(self, clientId):
		if self.onConnectedTriggers:
			for funcDict in self.onConnectedTriggers:
				for _, func in funcDict.items():
					func()
		self.onConnectedTriggers = []


	# main API data incoming method.
	def transferInputted(self, data, clientId):
		apiData = data.split(SublimeSocketAPISettings.SSAPI_DEFINE_DELIM, 1)[1]
		def runInMainThread():
			self.api.parse(apiData, clientId)
		self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0)
		

	def showTransferInfo(self):
		if self.transfer:
			return self.transfer.info()

		else:
			return "no transfer running."



	# control transfer.

	def setupTransfer(self, transferMethod, params):
		if self.transfer:
			message = "SublimeSocket already running." + self.transfer.info()
			self.api.editorAPI.printMessage(message + "\n")
			self.api.editorAPI.statusMessage(message)
		
		else:
			if transferMethod in SublimeSocketAPISettings.TRANSFER_METHODS:
				
				for case in PythonSwitch(transferMethod):
					if case(SublimeSocketAPISettings.WEBSOCKET_SERVER):
						self.transfer = WSServer(self)
						self.transfer.setup(params)
						break


		self.currentTransferMethod = transferMethod

	def spinupTransfer(self):
		if self.transfer:
			self.transfer.spinup()

	def restartTransfer(self):
		if self.transfer:
			# reserve restart
			self.reserveRestart = self.transfer.currentArgs()
			self.teardownTransfer()
		else:
			self.transferSpinupFailed("no transfer running.")

	def teardownTransfer(self):
		if self.transfer:
			self.transfer.teardown()
		else:
			self.transferTeardowned("no transfer running.")

	def appendOnConnectedTriggers(self, func):
		for addedFunctionDict in self.onConnectedTriggers:
			if func.__name__ in addedFunctionDict.keys():
				print("duplicate trigger:"+str(func))
				return
			
		self.onConnectedTriggers.append({func.__name__:func})

	# message series
	
	def sendMessage(self, targetId, message):
		return self.transfer.sendMessage(targetId, message)

	def broadcastMessage(self, targetIds, message):
		return self.transfer.broadcastMessage(targetIds, message)

	# purge
	def purgeConnection(self, targetId):
		self.transfer.purgeConnection(targetId)


	# other series

	def onTransferRenew(self):
		def runInMainThread () :
			settingCommands = self.api.editorAPI.loadSettings("onTransferRenew")
			for command in settingCommands:
				self.api.runAPI(command, None)

		self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0)






	# KVS bridge series

	def clearAllKeysAndValues(self):
		self.kvs.clear()


	def showAllKeysAndValues(self):
		everything = self.kvs.getAll()
		print("everything", everything)


	# views and KVS
	def viewsDict(self):
		viewsDict = self.kvs.get(SublimeSocketAPISettings.DICT_VIEWS)

		if viewsDict:
			return viewsDict
		
		return {}

	def updateViewsDict(self, viewsDict):
		self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_VIEWS, viewsDict)



	# regions and KVS
	def storeRegion(self, path, identity, line, regionFrom, regionTo, message):
		regionsDict = self.regionsDict()
		
		if path in regionsDict:
			if identity in regionsDict[path]:
				pass
			else:
				regionsDict[path][identity] = {}
				regionsDict[path][identity][SublimeSocketAPISettings.REGION_LINE] = line
				regionsDict[path][identity][SublimeSocketAPISettings.REGION_FROM] = regionFrom
				regionsDict[path][identity][SublimeSocketAPISettings.REGION_TO] = regionTo
				regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES] = []
		else:
			regionsDict[path] = {}
			regionsDict[path][identity] = {}
			regionsDict[path][identity][SublimeSocketAPISettings.REGION_LINE] = line
			regionsDict[path][identity][SublimeSocketAPISettings.REGION_FROM] = regionFrom
			regionsDict[path][identity][SublimeSocketAPISettings.REGION_TO] = regionTo
			regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES] = []

		if not message in regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES]:
			regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES].insert(0, message)
		
			self.updateRegionsDict(regionsDict)

	def regionsDict(self):
		regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS)

		if regionsDict:
			return regionsDict

		return {}

	def updateRegionsDict(self, regionsDict):
		self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REGIONS, regionsDict)

	def selectingRegionIds(self, path):
		regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS)
		
		if path in regionsDict:
			selectingRegionIds = [regionId for regionId, regionDatas in regionsDict[path].items() if SublimeSocketAPISettings.REGION_ISSELECTING in regionDatas and regionDatas[SublimeSocketAPISettings.REGION_ISSELECTING] == 1]
			
			return selectingRegionIds

		return []

	def updateSelectingRegionIdsAndResetOthers(self, path, selectingRegionIds):
		regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS)
		
		if path in regionsDict:
			regions = regionsDict[path]
			allRegionIds = list(regions)
			
			unselectedRegionIds = set(allRegionIds) - set(selectingRegionIds)

			for selectingRegionId in selectingRegionIds:
				regions[selectingRegionId][SublimeSocketAPISettings.REGION_ISSELECTING] = 1
			
			for unselectdRegionid in unselectedRegionIds:
				regions[unselectdRegionid][SublimeSocketAPISettings.REGION_ISSELECTING] = 0

	# reactor and KVS
	def reactorsDict(self):
		reactorsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REACTORS)
		if reactorsDict:
			return reactorsDict

		return {}

	def updateReactorsDict(self, reactorsDict):
		self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORS, reactorsDict)




	# reactorsLog and KVS
	def reactorsLogDict(self):
		reactorsLogDict = self.kvs.get(SublimeSocketAPISettings.DICT_REACTORSLOG)

		if reactorsLogDict:
			return reactorsLogDict

		return {}

	def updateReactorsLogDict(self, reactorsLogDict):
		self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORSLOG, reactorsLogDict)




	# completions and KVS
	def completionsDict(self):
		completionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_COMPLETIONS)
		if completionsDict:
			return completionsDict

		return {}

	def deleteCompletion(self, identity):
		completionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_COMPLETIONS)
		del completionsDict[identity]
		self.updateCompletionsDict(completionsDict)

	def updateCompletionsDict(self, completionsDict):
		self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_COMPLETIONS, completionsDict)



	# filters and KVS
	def filtersDict(self):
		filtersDict = self.kvs.get(SublimeSocketAPISettings.DICT_FILTERS)

		if filtersDict:
			return filtersDict

		return {}

	def updateFiltersDict(self, filtersDict):
		self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_FILTERS, filtersDict)