Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
415
Issues
415
List
Boards
Labels
Service Desk
Milestones
Merge Requests
65
Merge Requests
65
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
ISC Open Source Projects
Kea
Commits
417beb8b
Commit
417beb8b
authored
Aug 28, 2018
by
Marcin Siodelski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[
#28
] Added libkea-cb library.
parent
e3f3adaf
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1827 additions
and
1 deletion
+1827
-1
configure.ac
configure.ac
+2
-0
src/lib/Makefile.am
src/lib/Makefile.am
+1
-1
src/lib/config_backend/Makefile.am
src/lib/config_backend/Makefile.am
+29
-0
src/lib/config_backend/base_config_backend.h
src/lib/config_backend/base_config_backend.h
+35
-0
src/lib/config_backend/base_config_backend_mgr.h
src/lib/config_backend/base_config_backend_mgr.h
+95
-0
src/lib/config_backend/base_config_backend_pool.cc
src/lib/config_backend/base_config_backend_pool.cc
+153
-0
src/lib/config_backend/base_config_backend_pool.h
src/lib/config_backend/base_config_backend_pool.h
+586
-0
src/lib/config_backend/config_backend_mgr.h
src/lib/config_backend/config_backend_mgr.h
+23
-0
src/lib/config_backend/tests/Makefile.am
src/lib/config_backend/tests/Makefile.am
+38
-0
src/lib/config_backend/tests/config_backend_mgr_unittest.cc
src/lib/config_backend/tests/config_backend_mgr_unittest.cc
+461
-0
src/lib/config_backend/tests/config_backend_selector_unittest.cc
.../config_backend/tests/config_backend_selector_unittest.cc
+159
-0
src/lib/config_backend/tests/libcb_unittests
src/lib/config_backend/tests/libcb_unittests
+210
-0
src/lib/config_backend/tests/run_unittests.cc
src/lib/config_backend/tests/run_unittests.cc
+19
-0
src/lib/database/db_exceptions.h
src/lib/database/db_exceptions.h
+16
-0
No files found.
configure.ac
View file @
417beb8b
...
...
@@ -1534,6 +1534,8 @@ AC_CONFIG_FILES([Makefile
src/lib/config/tests/Makefile
src/lib/config/tests/data_def_unittests_config.h
src/lib/config/tests/testdata/Makefile
src/lib/config_backend/Makefile
src/lib/config_backend/tests/Makefile
src/lib/cryptolink/Makefile
src/lib/cryptolink/tests/Makefile
src/lib/database/Makefile
...
...
src/lib/Makefile.am
View file @
417beb8b
...
...
@@ -13,7 +13,7 @@ if HAVE_CQL
SUBDIRS
+=
cql
endif
SUBDIRS
+=
testutils hooks dhcp config stats
SUBDIRS
+=
config_backend
testutils hooks dhcp config stats
if
HAVE_SYSREPO
SUBDIRS
+=
yang
...
...
src/lib/config_backend/Makefile.am
0 → 100644
View file @
417beb8b
SUBDIRS
=
.
tests
AM_CPPFLAGS
=
-I
$(top_srcdir)
/src/lib
-I
$(top_builddir)
/src/lib
AM_CPPFLAGS
+=
$(BOOST_INCLUDES)
AM_CXXFLAGS
=
$(KEA_CXXFLAGS)
lib_LTLIBRARIES
=
libkea-cb.la
libkea_cb_la_SOURCES
=
base_config_backend.h
libkea_cb_la_SOURCES
+=
base_config_backend_mgr.h
libkea_cb_la_SOURCES
+=
base_config_backend_pool.cc base_config_backend_pool.h
libkea_cb_la_LIBADD
=
$(top_builddir)
/src/lib/database/libkea-database.la
libkea_cb_la_LIBADD
=
$(top_builddir)
/src/lib/util/libkea-util.la
libkea_cb_la_LIBADD
+=
$(top_builddir)
/src/lib/asiolink/libkea-asiolink.la
libkea_cb_la_LIBADD
+=
$(top_builddir)
/src/lib/exceptions/libkea-exceptions.la
libkea_cb_la_LIBADD
+=
$(BOOST_LIBS)
libkea_cb_la_LDFLAGS
=
-no-undefined
-version-info
0:0:0
# The message file should be in the distribution.
#EXTRA_DIST = config_backend.dox
CLEANFILES
=
*
.gcno
*
.gcda
# Specify the headers for copying into the installation directory tree.
#libkea_cb_includedir = $(pkgincludedir)/config
#libkea_cb_include_HEADERS =
src/lib/config_backend/base_config_backend.h
0 → 100644
View file @
417beb8b
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef BASE_CONFIG_BACKEND_H
#define BASE_CONFIG_BACKEND_H
#include <boost/shared_ptr.hpp>
#include <string>
namespace
isc
{
namespace
cb
{
class
BaseConfigBackend
{
public:
virtual
~
BaseConfigBackend
()
{
}
virtual
std
::
string
getType
()
const
=
0
;
virtual
std
::
string
getHost
()
const
=
0
;
virtual
uint16_t
getPort
()
const
=
0
;
};
typedef
boost
::
shared_ptr
<
BaseConfigBackend
>
BaseConfigBackendPtr
;
}
// end of namespace isc::cb
}
// end of namespace isc
#endif // BASE_CONFIG_BACKEND_H
src/lib/config_backend/base_config_backend_mgr.h
0 → 100644
View file @
417beb8b
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef BASE_CONFIG_BACKEND_MGR_H
#define BASE_CONFIG_BACKEND_MGR_H
#include <database/database_connection.h>
#include <config_backend/base_config_backend.h>
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
#include <functional>
#include <map>
#include <string>
namespace
isc
{
namespace
cb
{
template
<
typename
ConfigBackendPoolType
>
class
BaseConfigBackendMgr
{
public:
typedef
boost
::
shared_ptr
<
ConfigBackendPoolType
>
ConfigBackendPoolPtr
;
typedef
std
::
function
<
typename
ConfigBackendPoolType
::
ConfigBackendTypePtr
(
const
db
::
DatabaseConnection
::
ParameterMap
&
)
>
Factory
;
BaseConfigBackendMgr
()
:
factories_
(),
backends_
(
new
ConfigBackendPoolType
())
{
}
bool
registerBackendFactory
(
const
std
::
string
&
db_type
,
const
Factory
&
factory
)
{
if
(
factories_
.
count
(
db_type
))
{
return
(
false
);
}
factories_
.
insert
(
std
::
make_pair
(
db_type
,
factory
));
return
(
true
);
}
void
addBackend
(
const
std
::
string
&
dbaccess
)
{
// Parse the access string and create a redacted string for logging.
db
::
DatabaseConnection
::
ParameterMap
parameters
=
db
::
DatabaseConnection
::
parse
(
dbaccess
);
// Get the database type and open the corresponding database
db
::
DatabaseConnection
::
ParameterMap
::
iterator
it
=
parameters
.
find
(
"type"
);
if
(
it
==
parameters
.
end
())
{
isc_throw
(
InvalidParameter
,
"Host database configuration does not "
"contain the 'type' keyword"
);
}
std
::
string
db_type
=
it
->
second
;
auto
index
=
factories_
.
find
(
db_type
);
// No match?
if
(
index
==
factories_
.
end
())
{
isc_throw
(
db
::
InvalidType
,
"The type of host backend: '"
<<
db_type
<<
"' is not currently supported"
);
}
// Call the factory and push the pointer on sources.
auto
backend
=
index
->
second
(
parameters
);
if
(
!
backend
)
{
isc_throw
(
Unexpected
,
"Config database "
<<
db_type
<<
" factory returned NULL"
);
}
backends_
->
addBackend
(
backend
);
}
void
delAllBackends
()
{
backends_
->
delAllBackends
();
}
ConfigBackendPoolPtr
getPool
()
const
{
return
(
backends_
);
}
protected:
std
::
map
<
std
::
string
,
Factory
>
factories_
;
ConfigBackendPoolPtr
backends_
;
};
}
// end of namespace isc::cb
}
// end of namespace isc
#endif // BASE_CONFIG_BACKEND_MGR_H
src/lib/config_backend/base_config_backend_pool.cc
0 → 100644
View file @
417beb8b
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config_backend/base_config_backend_pool.h>
#include <exceptions/exceptions.h>
#include <climits>
#include <sstream>
using
namespace
isc
::
data
;
namespace
isc
{
namespace
cb
{
BackendSelector
::
BackendSelector
()
:
backend_type_
(
BackendSelector
::
Type
::
UNSPEC
),
host_
(),
port_
(
0
)
{
}
BackendSelector
::
BackendSelector
(
const
Type
&
backend_type
)
:
backend_type_
(
backend_type
),
host_
(),
port_
(
0
)
{
}
BackendSelector
::
BackendSelector
(
const
std
::
string
&
host
,
const
uint16_t
port
)
:
backend_type_
(
BackendSelector
::
Type
::
UNSPEC
),
host_
(
host
),
port_
(
port
)
{
validate
();
}
BackendSelector
::
BackendSelector
(
const
data
::
ConstElementPtr
&
access_map
)
:
backend_type_
(
BackendSelector
::
Type
::
UNSPEC
),
host_
(),
port_
(
0
)
{
if
(
access_map
->
getType
()
!=
Element
::
map
)
{
isc_throw
(
BadValue
,
"database access information must be a map"
);
}
ConstElementPtr
t
=
access_map
->
get
(
"type"
);
if
(
t
)
{
if
(
t
->
getType
()
!=
Element
::
string
)
{
isc_throw
(
BadValue
,
"'type' parameter must be a string"
);
}
backend_type_
=
stringToBackendType
(
t
->
stringValue
());
}
ConstElementPtr
h
=
access_map
->
get
(
"host"
);
if
(
h
)
{
if
(
h
->
getType
()
!=
Element
::
string
)
{
isc_throw
(
BadValue
,
"'host' parameter must be a string"
);
}
host_
=
h
->
stringValue
();
}
ConstElementPtr
p
=
access_map
->
get
(
"port"
);
if
(
p
)
{
if
((
p
->
getType
()
!=
Element
::
integer
)
||
(
p
->
intValue
()
<
0
)
||
(
p
->
intValue
()
>
std
::
numeric_limits
<
uint16_t
>::
max
()))
{
isc_throw
(
BadValue
,
"'port' parameter must be a number in range from 0 "
"to "
<<
std
::
numeric_limits
<
uint16_t
>::
max
());
}
port_
=
static_cast
<
uint16_t
>
(
p
->
intValue
());
}
validate
();
}
const
BackendSelector
&
BackendSelector
::
BackendSelector
::
UNSPEC
()
{
static
BackendSelector
selector
;
return
(
selector
);
}
bool
BackendSelector
::
amUnspecified
()
const
{
return
((
backend_type_
==
BackendSelector
::
Type
::
UNSPEC
)
&&
(
host_
.
empty
())
&&
(
port_
==
0
));
}
std
::
string
BackendSelector
::
toText
()
const
{
std
::
ostringstream
s
;
if
(
amUnspecified
())
{
s
<<
"unspecified"
;
}
else
{
if
(
backend_type_
!=
BackendSelector
::
Type
::
UNSPEC
)
{
s
<<
"type="
<<
backendTypeToString
(
backend_type_
)
<<
","
;
}
if
(
!
host_
.
empty
())
{
s
<<
"host="
<<
host_
<<
","
;
if
(
port_
>
0
)
{
s
<<
"port="
<<
port_
<<
","
;
}
}
}
std
::
string
text
=
s
.
str
();
if
((
!
text
.
empty
()
&&
(
text
.
back
()
==
','
)))
{
text
.
pop_back
();
}
return
(
text
);
}
BackendSelector
::
Type
BackendSelector
::
stringToBackendType
(
const
std
::
string
&
type
)
{
if
(
type
==
"mysql"
)
{
return
(
BackendSelector
::
Type
::
MYSQL
);
}
else
if
(
type
==
"pgsql"
)
{
return
(
BackendSelector
::
Type
::
PGSQL
);
}
else
if
(
type
==
"cql"
)
{
return
(
BackendSelector
::
Type
::
CQL
);
}
else
{
isc_throw
(
BadValue
,
"unsupported configuration backend type '"
<<
type
<<
"'"
);
}
}
std
::
string
BackendSelector
::
backendTypeToString
(
const
BackendSelector
::
Type
&
type
)
{
switch
(
type
)
{
case
BackendSelector
::
Type
::
MYSQL
:
return
(
"mysql"
);
case
BackendSelector
::
Type
::
PGSQL
:
return
(
"pgsql"
);
case
BackendSelector
::
Type
::
CQL
:
return
(
"cql"
);
default:
;
}
return
(
std
::
string
());
}
void
BackendSelector
::
validate
()
const
{
if
((
port_
!=
0
)
&&
(
host_
.
empty
()))
{
isc_throw
(
BadValue
,
"'host' must be specified along with 'port' parameter"
);
}
}
}
// end of namespace isc::cb
}
// end of namespace isc
src/lib/config_backend/base_config_backend_pool.h
0 → 100644
View file @
417beb8b
This diff is collapsed.
Click to expand it.
src/lib/config_backend/config_backend_mgr.h
0 → 100644
View file @
417beb8b
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CONFIG_BACKEND_MGR_H
#define CONFIG_BACKEND_MGR_H
namespace
isc
{
namespace
cb
{
class
ConfigBackendMgr
{
public:
};
}
// end of namespace isc::cb
}
// end of namespace isc
#endif // CONFIG_BACKEND_MGR_H
src/lib/config_backend/tests/Makefile.am
0 → 100644
View file @
417beb8b
SUBDIRS
=
.
AM_CPPFLAGS
=
-I
$(top_builddir)
/src/lib
-I
$(top_srcdir)
/src/lib
AM_CPPFLAGS
+=
$(BOOST_INCLUDES)
AM_CPPFLAGS
+=
-DTEST_DATA_BUILDDIR
=
\"
$(abs_top_builddir)
/src/lib/config/tests
\"
AM_CXXFLAGS
=
$(KEA_CXXFLAGS)
if
USE_STATIC_LINK
AM_LDFLAGS
=
-static
endif
CLEANFILES
=
*
.gcno
*
.gcda
TESTS_ENVIRONMENT
=
\
$(LIBTOOL)
--mode
=
execute
$(VALGRIND_COMMAND)
TESTS
=
if
HAVE_GTEST
TESTS
+=
libcb_unittests
libcb_unittests_SOURCES
=
config_backend_mgr_unittest.cc
libcb_unittests_SOURCES
+=
config_backend_selector_unittest.cc
libcb_unittests_SOURCES
+=
run_unittests.cc
libcb_unittests_CPPFLAGS
=
$(AM_CPPFLAGS)
$(GTEST_INCLUDES)
libcb_unittests_LDFLAGS
=
$(AM_LDFLAGS)
$(GTEST_LDFLAGS)
libcb_unittests_LDADD
=
$(top_builddir)
/src/lib/database/libkea-database.la
libcb_unittests_LDADD
+=
$(top_builddir)
/src/lib/config_backend/libkea-cb.la
libcb_unittests_LDADD
+=
$(top_builddir)
/src/lib/util/libkea-util.la
libcb_unittests_LDADD
+=
$(top_builddir)
/src/lib/asiolink/libkea-asiolink.la
libcb_unittests_LDADD
+=
$(top_builddir)
/src/lib/exceptions/libkea-exceptions.la
libcb_unittests_LDADD
+=
$(LOG4CPLUS_LIBS)
$(BOOST_LIBS)
$(GTEST_LDADD)
endif
noinst_PROGRAMS
=
$(TESTS)
src/lib/config_backend/tests/config_backend_mgr_unittest.cc
0 → 100644
View file @
417beb8b
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <config_backend/base_config_backend_mgr.h>
#include <config_backend/base_config_backend_pool.h>
#include <config_backend/base_config_backend.h>
#include <database/database_connection.h>
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
#include <list>
#include <string>
#include <utility>
using
namespace
isc
;
using
namespace
isc
::
cb
;
using
namespace
isc
::
db
;
namespace
{
/// @brief Defines list of properties retrieved by @c TestConfigBackend.
///
/// A single property is a name/value pair, where value is an integer.
typedef
std
::
list
<
std
::
pair
<
std
::
string
,
int
>
>
PropertiesList
;
/// @brief Implements configuration backend used in tests.
///
/// @c BaseConfigBackend is an abstract class that must be implemented
/// in order to allow us to test mechanisms implemented in
/// @c BaseConfigBackendMgr and @c BaseConfigBackendPool.
///
/// Normally, a class derived directly from the @c BaseConfigBackend
/// will merely provide an interface for server specific operations,
/// e.g. DHCPv4 specific operations, and the database specific classes
/// will implement this interface. However, for the test purposes it
/// is convenient to implement them here and let the derivations
/// only provide the implementations of the @c getType, @c getHost
/// and @c getPort functions. That way, the logic for adding and
/// retrieving the data from the backend is implemented only once and
/// is common accross all test backends.
///
/// This class provides a logic for managing test data being a collection
/// of name/value pairs, i.e. "properties". It contains a list of
/// properties and the functions for adding the properties, retrieving
/// a single property and retrieving a collection of properties.
class
TestConfigBackend
:
public
BaseConfigBackend
{
public:
/// @brief Retrieves first property having a given name.
///
/// @param property_name Name of the property to be retrieved.
/// @return Value of the property or 0 if property doesn't exist.
virtual
int
getProperty
(
const
std
::
string
&
property_name
)
const
{
for
(
auto
property
:
properties_
)
{
if
(
property
.
first
==
property_name
)
{
return
(
property
.
second
);
}
}
return
(
0
);
}
/// @brief Retrieves all properties having a given name.
///
/// @param property_name Name of the properties to be retrieved.
/// @return List of the properties having a given name. This list is
/// empty if no property was found.
virtual
PropertiesList
getProperties
(
const
std
::
string
&
property_name
)
const
{
PropertiesList
properties
;
for
(
auto
property
:
properties_
)
{
if
(
property
.
first
==
property_name
)
{
properties
.
push_back
(
property
);
}
}
return
(
properties
);
}
/// @brief Retrieves all properties.
///
/// @return List of all properties held in the backend.
virtual
PropertiesList
getAllProperties
()
const
{
return
(
properties_
);
}
/// @brief Creates new property.
///
/// @param new_property Property to be added to the backend.
virtual
void
createProperty
(
const
std
::
pair
<
std
::
string
,
int
>&
new_property
)
{
properties_
.
push_back
(
new_property
);
}
protected:
/// @brief Holds list of properties (simulates database).
PropertiesList
properties_
;
};
/// @brief Shared pointer to the @c TestConfigBackend.
typedef
boost
::
shared_ptr
<
TestConfigBackend
>
TestConfigBackendPtr
;
/// @brief First implementation of the test config backend.
///
/// It simulates being a MySQL backend installed on the
/// "mysql-host" host and running on port 2345.
class
TestConfigBackendImpl1
:
public
TestConfigBackend
{
public:
/// @brief Returns backend type.
///
/// @return "mysql".
virtual
std
::
string
getType
()
const
{
return
(
std
::
string
(
"mysql"
));
}
/// @brief Returns backend host.
///
/// @return "mysql-host".
virtual
std
::
string
getHost
()
const
{
return
(
std
::
string
(
"mysql-host"
));
}
/// @brief Returns backend port.
///
/// @return Port number 2345.
virtual
uint16_t
getPort
()
const
{
return
(
2345
);
}
};
/// @brief Shared pointer to the @c TestConfigBackendImpl1.
typedef
boost
::
shared_ptr
<
TestConfigBackendImpl1
>
TestConfigBackendImpl1Ptr
;
/// @brief Second implementation of the test config backend.
///
/// It simulates being a Postgres backend installed on the
/// "pgsql-host" host and running on port 1234.
class
TestConfigBackendImpl2
:
public
TestConfigBackend
{
public:
/// @brief Returns backend type.
///
/// @return "pgsql".
virtual
std
::
string
getType
()
const
{
return
(
std
::
string
(
"pgsql"
));
}
/// @brief Returns backend host.
///
/// @return "pgsql-host".
virtual
std
::
string
getHost
()
const
{
return
(
std
::
string
(
"pgsql-host"
));
}
/// @brief Returns backend port.
///
/// @return Port number 1234.
virtual
uint16_t
getPort
()
const
{
return
(
1234
);
}
};
/// @brief Shared pointer to the @c TestConfigBackendImpl2.
typedef
boost
::
shared_ptr
<
TestConfigBackendImpl2
>
TestConfigBackendImpl2Ptr
;
/// @brief Implements test pool of configuration backends.
///
/// @c BaseConfigBackendPool template provides mechanics for managing the data
/// stored in multiple backends. Server specific pools must extend this class
/// with methods for managing the data appropriate for the server types.
/// This class provides an example pool implementation for managing the
/// "properties" being name/value pairs. It extends the base class with
/// new methods to retrieve a single property and multiple properties. It
/// also adds a method to create new property. Those methods correspond to
/// the ones implemented in the @c TestConfigBackend, but also each of
/// them includes a "database selector" used to indicate the backend to
/// be used.
class
TestConfigBackendPool
:
public
BaseConfigBackendPool
<
TestConfigBackend
>
{
public:
/// @brief Retrieves a value of the property.
///
/// @param property_name Name of the property which value should be returned.
/// @param selector Backend selector. The default value of the selector
/// is @c UNSPEC which means that the property will be searched in all backends
/// and the first value found will be returned.
virtual
int
getProperty
(
const
std
::
string
&
property_name
,
const
BackendSelector
&
selector
=
BackendSelector
::
UNSPEC
())
const
{
int
property
;
// If the selector is specified, this method will pick the appropriate
// backend and will call getProperty method on this backend. If the
// selector is not specified, this method will iterate over existing
// backends and call getProperty on them. It will return after finding
// the first non-zero value of the property. For example, if the first
// backend contains a non-zero value this value will be returned and
// the value held in the second backend (if any) won't be fetched.
// The template arguments specify the returned value type and the
// argument of the getProperty method.
getPropertyPtrConst
<
int
,
const
std
::
string
&
,
&
TestConfigBackend
::
getProperty
>
(
property
,
property_name
,
selector
);
return
(
property
);
}
/// @brief Retrieves multiple properties.
///
/// @param property_name Name of the properties which should be retrieved.
/// @param selector Backend selector. The default value of the selector
/// is @c UNSPEC which means that the properties will be searched in all
/// backends and the first non-empty list will be returned.
virtual
PropertiesList
getProperties
(
const
std
::
string
&
property_name
,
const
BackendSelector
&
selector
=
BackendSelector
::
UNSPEC
())
const
{
PropertiesList
properties
;
// If the selector is specified, this method will pick the appropriate
// backend and will call getProperties method on this backend. If the
// selector is not specified, this method will iterate over existing
// backends and call getProperties on them. It will return after finding
// the first non-empty list of properties in one of the backends.
// The template arguments specify the type of the list of properties