Add python shareddatalayer API and public exceptions.

Added synchronous API functions:
* To read, write and remove from SDL storage.
* To read, write and remove from SDL group.
* To acquire, release and control an SDL lock entry.

Defined a set of SDL exceptions what SDL python implementation
will raise when there happens an error either in SDL or in
the backend database (Redis) what SDL utilizes.

Change-Id: Iaf0f4b3052d2cf189feadf2eb506b7e9a8463409
Signed-off-by: Timo Tietavainen <timo.tietavainen@nokia.com>
diff --git a/sdl/__init__.py b/sdl/__init__.py
new file mode 100644
index 0000000..224904c
--- /dev/null
+++ b/sdl/__init__.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2019 AT&T Intellectual Property.
+# Copyright (c) 2018-2019 Nokia.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Shareddatalayer library."""
diff --git a/sdl/exceptions.py b/sdl/exceptions.py
new file mode 100644
index 0000000..2f3c16d
--- /dev/null
+++ b/sdl/exceptions.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2019 AT&T Intellectual Property.
+# Copyright (c) 2018-2019 Nokia.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"Exceptions raised by the shareddatalayer."
+
+class SdlTypeError(TypeError):
+    """
+    Exception for passing a function argument of wrong type.
+    It is likely that the same request will fail repeatedly. It is advised to investigate the exact
+    reason for the failure from the logs.
+    """
+    pass
+
+class SdlException(Exception):
+    """Base exception class for shareddatalayer exceptions."""
+    pass
+
+class NotConnected(SdlException):
+    """
+    Exception for not being connected to the database backend.
+    Shareddatalayer is not connected to the backend data storage and therefore could not deliver the
+    request to the backend data storage. Data in the backend data storage has not been altered.
+    Client is advised to try the operation again later.
+    """
+    pass
+
+class BackendError(SdlException):
+    """
+    Exception for request processing failure.
+    In case of a write type request, data in the backend data storage may or may not have been
+    altered. Client is advised to try the operation again later.
+    """
+    pass
+
+class RejectedByBackend(SdlException):
+    """
+    Exception for shareddatalayer rejecting the request.
+    Backend data storage rejected the request. In case of a write type request, data in the backend
+    data storage may or may not have been altered. It is likely that the same request will fail
+    repeatedly. It is advised to investigate the exact reason for the failure from the logs.
+    """
+    pass
diff --git a/sdl/syncstorage_abc.py b/sdl/syncstorage_abc.py
new file mode 100644
index 0000000..3622285
--- /dev/null
+++ b/sdl/syncstorage_abc.py
@@ -0,0 +1,634 @@
+# Copyright (c) 2019 AT&T Intellectual Property.
+# Copyright (c) 2018-2019 Nokia.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""The module provides synchronous shareddatalayer interface."""
+from typing import (Dict, Set, List, Union)
+from abc import ABC, abstractmethod
+
+
+__all__ = [
+    'SyncStorageAbc',
+    'SyncLockAbc'
+]
+
+
+class SyncLockAbc(ABC):
+    """
+    An abstract synchronous lock class providing a shared, distributed locking mechanism, which can
+    be utilized by clients to be able to operate with a shared resource in a mutually exclusive way.
+
+    A lock instance is created per namespace and it is identified by its `name` within a
+    namespace.
+
+    A concrete implementation subclass 'SyncLock' derives from this abstract class.
+
+    Args:
+        ns (str): Namespace under which this lock is targeted.
+        name (str): Lock name, identifies the lock key in shared data layer storage.
+        expiration (int, float): Lock expiration time after which the lock is removed if it hasn't
+                                 been released earlier by a 'release' method.
+
+    """
+    def __init__(self, ns: str, name: str, expiration: Union[int, float]) -> None:
+        super().__init__()
+        self._ns = ns
+        self._name = name
+        self._expiration = expiration
+
+    def __enter__(self, *args, **kwargs):
+        self.acquire(*args, **kwargs)
+        return self
+
+    def __exit__(self, exception_type, exception_value, traceback):
+        self.release()
+
+    def acquire(self, retry_interval: Union[int, float] = 0.1,
+                retry_timeout: Union[int, float] = 10) -> bool:
+        """
+        Acquire a shared, distributed lock atomically.
+
+        A lock can be used as a mutual exclusion locking entry for a shared resources.
+
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            retry_interval (int, float): Lock acquiring retry interval in seconds. Supports both
+                                         integer and float numbers.
+            retry_timeout (int, float): Lock acquiring timeout after which retries are stopped and
+                                        error status is returned. Supports both integer and float
+                                        numbers.
+
+        Returns:
+            bool: True for successful lock acquiring, false otherwise.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    def release(self) -> None:
+        """
+        Release a lock atomically.
+
+        Release the already acquired lock.
+
+        Exceptions thrown are all derived from SdlException base class. Client can catch only that
+        exception if separate handling for different shareddatalayer error situations is not
+        needed.
+
+        Args:
+            None
+
+        Returns:
+            None
+
+        Raises:
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    def refresh(self) -> None:
+        """
+        Refresh the remaining validity time of the existing lock back to an initial value.
+
+        Exceptions thrown are all derived from SdlException base class. Client can catch only that
+        exception if separate handling for different shareddatalayer error situations is not
+        needed.
+
+        Args:
+            None
+
+        Returns:
+            None
+
+        Raises:
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    def get_validity_time(self) -> Union[int, float]:
+        """
+        Get atomically the remaining validity time of the lock in seconds.
+
+        Return atomically time in seconds until the lock expires.
+
+        Exceptions thrown are all derived from SdlException base class. Client can catch only that
+        exception if separate handling for different shareddatalayer error situations is not
+        needed.
+
+        Args:
+            None
+
+        Returns:
+            (int, float): Validity time of the lock in seconds.
+
+        Raises:
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+class SyncStorageAbc(ABC):
+    """
+    An abstract class providing synchronous access to shared data layer storage.
+
+    This class provides synchronous access to all the namespaces in shared data layer storage.
+    Data can be written, read and removed based on keys known to clients. Keys are unique within
+    a namespace, namespace identifier is passed as a parameter to all the operations.
+
+    A concrete implementation subclass 'SyncStorage' derives from this abstract class.
+    """
+
+    @abstractmethod
+    def set(self, ns: str, data_map: Dict[str, bytes]) -> None:
+        """
+        Write data to shared data layer storage.
+
+        Writing is done atomically, i.e. either all succeeds, or all fails.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            data_map (dict of str: bytes): Data to be written.
+
+        Returns:
+            None
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def set_if(self, ns: str, key: str, old_data: bytes, new_data: bytes) -> bool:
+        """
+        Conditionally modify the value of a key if the current value in data storage matches the
+        user's last known value.
+
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            key (str): Key for which data modification will be executed.
+            old_data (bytes): Last known data.
+            new_data (bytes): Data to be written.
+
+        Returns:
+            bool: True for successful modification, false if the user's last known data did not
+                  match the current value in data storage.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def set_if_not_exists(self, ns: str, key: str, data: bytes) -> bool:
+        """
+        Write data to shared data layer storage if key does not exist.
+
+        Conditionally set the value of a key. If key already exists, then its value is not
+        modified. Checking the key existence and potential set operation is done as a one atomic
+        operation.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            key (str): Key to be set.
+            data (bytes): Data to be written.
+
+        Returns:
+            bool: True if key didn't exist yet and set operation was executed, false if key already
+                  existed and thus its value was left untouched.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def get(self, ns: str, keys: Union[str, Set[str]]) -> Dict[str, bytes]:
+        """
+        Read data from shared data layer storage.
+
+        Only those entries that are found will be returned.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            keys (str or set of str): One or multiple keys to be read.
+
+        Returns:
+            (dict of str: bytes): A dictionary mapping of a key to the read data from the storage.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def find_keys(self, ns: str, key_prefix: str) -> List[str]:
+        """
+        Find all keys matching search pattern under the namespace.
+
+        No prior knowledge about the keys in the given namespace exists, thus operation is not
+        guaranteed to be atomic or isolated.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            key_prefix (str): Only keys starting with given keyPrefix are returned. Passing empty
+                              string as keyPrefix will return all the keys.
+
+        Returns:
+            (list of str): A list of found keys.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def find_and_get(self, ns: str, key_prefix: str, atomic: bool) -> Dict[str, bytes]:
+        """
+        Find keys and get their respective data from shared data layer storage.
+
+        Only those entries that are matching prefix will be returned.
+        NOTE: In atomic action, if the prefix produces huge number of matches, that can have
+        a severe impact on system performance, due to DB is blocked for long time.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            key_prefix (str): Only keys starting with given keyPrefix are returned. Passing empty
+                              string as keyPrefix will return all the keys.
+            atomic (bool): True to find keys and get their respective data in one atomic operation,
+                           false to find keys and get their respective data non-atomically.
+
+        Returns:
+            (dict of str: bytes): A dictionary mapping of a key to the read data from the storage.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def remove(self, ns: str, keys: Union[str, Set[str]]) -> None:
+        """
+        Remove data from shared data layer storage. Existing keys are removed.
+
+        Removing is done atomically, i.e. either all succeeds, or all fails.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            keys (str or set of str): One key or multiple keys, which data is to be removed.
+
+        Returns:
+            None
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def remove_if(self, ns: str, key: str, data: bytes) -> bool:
+        """
+        Conditionally remove data from shared data layer storage if the current data value matches
+        the user's last known value.
+
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            key (str): Key, which data is to be removed.
+            data (bytes): Last known value of data
+
+        Returns:
+            bool: True if successful removal, false if the user's last known data did not match the
+                  current value in data storage.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def remove_all(self, ns: str) -> None:
+        """
+        Remove all keys under the namespace.
+
+        No prior knowledge about the keys in the given namespace exists, thus operation is not
+        guaranteed to be atomic or isolated.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+
+        Returns:
+            None
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def add_member(self, ns: str, group: str, members: Union[bytes, Set[bytes]]) -> None:
+        """
+        Add new members to a shared data layer group under the namespace.
+
+        Shared data layer groups are identified by their name, which is a key in storage. Shared
+        data layer groups are unordered collections of members where each member is unique. If
+        a member to be added is already a member of the group, its addition is silently ignored. If
+        the group does not exist, it is created, and specified members are added to the group.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            group (str): Group name.
+            members (bytes or set of bytes): One or multiple members to be added.
+
+        Returns:
+            None
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def remove_member(self, ns: str, group: str, members: Union[bytes, Set[bytes]]) -> None:
+        """
+        Remove members from a shared data layer group.
+
+        Shared data layer groups are unordered collections of members where each member is unique.
+        If a member to be removed does not exist in the group, its removal is silently ignored. If
+        a group does not exist, it is treated as an empty group and hence members removal is
+        silently ignored.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            group (str): Group name.
+            members (bytes or set of bytes): One or multiple members to be removed.
+
+        Returns:
+            None
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def remove_group(self, ns: str, group: str) -> None:
+        """
+        Remove a shared data layer group along with its members.
+
+        Shared data layer groups are unordered collections of members where each member is unique.
+        If a group to be removed does not exist, its removal is silently ignored.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            group (str): Group name to be removed.
+
+        Returns:
+            None
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def get_members(self, ns: str, group: str) -> Set[bytes]:
+        """
+        Get all the members of a shared data layer group.
+
+        Shared data layer groups are unordered collections of members where each member is unique.
+        If the group does not exist, empty set is returned.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            group (str): Group name of which members are to be returned.
+
+        Returns:
+            (set of bytes): A set of the members of the group.
+            None
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def is_member(self, ns: str, group: str, member: bytes) -> bool:
+        """
+        Validate if a given member is in the shared data layer group.
+
+        Shared data layer groups are unordered collections of members where each member is unique.
+        If the group does not exist, false is returned.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            group (str): Group name of which member existence is to be validated.
+            member (bytes): A member, which existence is to be validated.
+
+        Returns:
+            bool: True if member was in the group, false otherwise.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def group_size(self, ns: str, group: str) -> int:
+        """
+        Return the number of members in a group.
+
+        Shared data layer groups are unordered collections of members where each member is unique.
+        If the group does not exist, value 0 is returned.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            group (str): Group name of which members count is queried.
+
+        Returns:
+            int: Number of members in a group.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass
+
+
+    @abstractmethod
+    def get_lock_resource(self, ns: str, resource: str,
+                          expiration: Union[int, float]) -> SyncLockAbc:
+        """
+        Return a lock resource for shared data layer.
+
+        A lock resource instance is created per namespace and it is identified by its `name` within
+        a namespace. A `get_lock_resource` returns a lock resource instance, it does not acquire
+        a lock. Lock resource provides lock handling methods such as acquiring a lock, extend
+        expiration time and releasing a lock.
+        All the exceptions except SdlTypeError are derived from SdlException base class. Client
+        can catch only that exception if separate handling for different shareddatalayer error
+        situations is not needed. Exception SdlTypeError is derived from build-in TypeError and it
+        indicates misuse of the SDL API.
+
+        Args:
+            ns (str): Namespace under which this operation is targeted.
+            resource (str): Resource is used within namespace as a key for a lock entry in
+                            shareddatalayer.
+            expiration (int, float): Expiration time of a lock
+
+        Returns:
+            SyncLockAbc: Lock resource instance.
+
+        Raises:
+            SdlTypeError: If function's argument is of an inappropriate type.
+            NotConnected: If shareddatalayer is not connected to the backend data storage.
+            RejectedByBackend: If backend data storage rejects the request.
+            BackendError: If the backend data storage fails to process the request.
+        """
+        pass