diff --git a/.travis.yml b/.travis.yml index e317b0c2e..74c87b03a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,12 +40,76 @@ before_install: - wget https://sonarcloud.io/static/cpp/build-wrapper-linux-x86.zip && unzip build-wrapper-linux-x86.zip before_script: - - docker run --name mysql_db -e MYSQL_ROOT_PASSWORD=root -d tangocs/mysql:9.2.2 --sql-mode="" - - CONTAINER=$(docker run --name tango_cs -e TANGO_HOST=127.0.0.1:10000 -e MYSQL_HOST=mysql_db:3306 -e MYSQL_USER=tango -e MYSQL_PASSWORD=tango -e MYSQL_DATABASE=tango --link mysql_db:mysql_db -d tangocs/tango-cs:latest) - - IPADDR=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' $CONTAINER) - - TANGO_HOST=${IPADDR}:10000 + - > + docker run + --rm + --name mysql_db + -e MYSQL_ROOT_PASSWORD=root + -e MYSQL_INITDB_SKIP_TZINFO=1 + -d + tangocs/mysql:9.2.2 + --sql-mode="" + --innodb=OFF + --default-storage-engine=MyISAM + - > + docker run + --rm + --name mysql_db2 + -e MYSQL_ROOT_PASSWORD=root + -e MYSQL_INITDB_SKIP_TZINFO=1 + -d + tangocs/mysql:9.2.2 + --sql-mode="" + --innodb=OFF + --default-storage-engine=MyISAM + - > + docker run + --name tango_cs + -e TANGO_HOST=127.0.0.1:10000 + -e MYSQL_HOST=mysql_db:3306 + -e MYSQL_USER=tango + -e MYSQL_PASSWORD=tango + -e MYSQL_DATABASE=tango + --link mysql_db:mysq_db + -d + tangocs/tango-cs:latest + - > + docker run + --name tango_cs2 + -e TANGO_HOST=127.0.0.1:10000 + -e MYSQL_HOST=mysql_db2:3306 + -e MYSQL_USER=tango + -e MYSQL_PASSWORD=tango + -e MYSQL_DATABASE=tango + --link mysql_db2:mysq_db2 + -d + tangocs/tango-cs:latest + - sleep 5 + - docker ps -a + - docker logs tango_cs + - docker logs tango_cs2 + - TANGO_HOST_IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tango_cs) + - TANGO_HOST_IP2=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tango_cs2) + - TANGO_HOST=${TANGO_HOST_IP}:10000 - docker build --build-arg APP_UID=$(id -u) --build-arg APP_GID=$(id -g) -t cpp_tango .travis/${OS_TYPE} - - docker run --name cpp_tango -e TANGO_HOST=${TANGO_HOST} -e BINTRAY_USER_NAME=tango-ci -e BINTRAY_API_KEY=${CI_BINTRAY_API_KEY} -e COVERALLS_REPO_TOKEN=${COVERALLS_REPO_TOKEN} --link tango_cs:tango_cs -v `pwd`:/home/tango/src -v `pwd`/idl:/home/tango/idl -v `pwd`/cppzmq:/home/tango/cppzmq -v `pwd`/coveralls-cmake:/home/tango/coveralls-cmake -v `pwd`/build-wrapper-linux-x86:/home/tango/build-wrapper-linux-x86 -dit cpp_tango + - > + docker run + --rm + --name cpp_tango + -e TANGO_HOST=${TANGO_HOST} + -e TANGO_HOST2=${TANGO_HOST_IP2}:10000 + -e BINTRAY_USER_NAME=tango-ci + -e BINTRAY_API_KEY=${CI_BINTRAY_API_KEY} + -e COVERALLS_REPO_TOKEN=${COVERALLS_REPO_TOKEN} + --link tango_cs + --link tango_cs2 + -v `pwd`:/home/tango/src + -v `pwd`/idl:/home/tango/idl + -v `pwd`/cppzmq:/home/tango/cppzmq + -v `pwd`/coveralls-cmake:/home/tango/coveralls-cmake + -v `pwd`/build-wrapper-linux-x86:/home/tango/build-wrapper-linux-x86 + -dit + cpp_tango - .travis/install_tango_idl.sh - .travis/install_cppzmq.sh #work around gcov ignored by sonar @@ -67,8 +131,6 @@ deploy: after-script: - docker stop cpp_tango - - docker rm cpp_tango - - docker stop tango_cs - - docker rm tango_cs - - docker stop mysql_db - - docker rm mysql_db + - docker stop tango_cs tango_cs2 + - docker rm tango_cs tango_cs2 + - docker stop mysql_db mysql_db2 diff --git a/cppapi/client/group.cpp b/cppapi/client/group.cpp index 3df564992..d05445c63 100644 --- a/cppapi/client/group.cpp +++ b/cppapi/client/group.cpp @@ -49,63 +49,83 @@ bool GroupReply::exception_enabled = false; //============================================================================= // class GroupElementFactory //============================================================================= -GroupElements GroupElementFactory::instanciate (const std::string& p, int tmo_ms) +GroupElements GroupElementFactory::instanciate( + const std::string& name_or_pattern, + int timeout_millis) { -#if defined(_LOCAL_DEBUGGING) - cout << "GroupElementFactory::instanciate::pattern [" << p << "]" << endl; -#endif - //- a vector to store device names - std::vector dnl(0); - //- is

a device name or a device name pattern ? - if (p.find('*', 0) == std::string::npos) - { -#if defined(_LOCAL_DEBUGGING) - cout << "\t|- pattern is pure device name" << endl; -#endif - dnl.push_back(p); - } - else - { - int db_port = 0; - std::string db_host, new_pattern; - DbDatum dbd; - parse_name(p, db_host, db_port, new_pattern); - - if (db_host.size() == 0) { - Database db; - //- ask the db the list of device matching pattern p - dbd = db.get_device_exported(const_cast(p)); - } - else { - ApiUtil *au = ApiUtil::instance(); - int db_ind = au->get_db_ind(db_host,db_port); - dbd = ((au->get_db_vect())[db_ind])->get_device_exported(const_cast(new_pattern)); - } - - //- extract device names from dbd - dbd >> dnl; -#if defined(_LOCAL_DEBUGGING) - cout << "\t|- db.get_device_exported::found "; - cout << dnl.size() << " device names matching pattern" << endl; - for (unsigned int dn = 0; dn < dnl.size(); dn++) { - cout << "\t\t|- " << dnl[dn] << endl; + return create_group_elements(resolve_device_names(name_or_pattern), timeout_millis); +} + +GroupElements GroupElementFactory::create_group_elements(const DeviceNames& names, int timeout_millis) +{ + GroupElements group_elements; + group_elements.reserve(names.size()); + + for (DeviceNames::const_iterator name = names.begin(); name != names.end(); ++name) + { + group_elements.push_back(new GroupDeviceElement(*name, timeout_millis)); } -#endif - } - //- build the returned GroupElementList - GroupElements tel(0); - GroupDeviceElement* tde; - for (unsigned int i = 0; i < dnl.size(); i++) { - tde = new GroupDeviceElement(dnl[i],tmo_ms); - if (tde) { - tel.push_back(tde); + + return group_elements; +} + +DeviceNames GroupElementFactory::resolve_device_names(const std::string& name_or_pattern) +{ + const bool is_name = name_or_pattern.find('*') == std::string::npos; + + if (is_name) + { + return DeviceNames(1, name_or_pattern); } - } -#if defined(_LOCAL_DEBUGGING) - cout << "\t|- GroupElementList contains " << tel.size() << " elements" << endl; -#endif - //- return the list to the caller - return tel; + else + { + int db_port = 0; + std::string db_host = ""; + std::string name_or_pattern_without_host = ""; + parse_name(name_or_pattern, db_host, db_port, name_or_pattern_without_host); + + const bool is_local_device = db_host.empty(); + + if (is_local_device) + { + return resolve_local_device_names(name_or_pattern); + } + else + { + return resolve_remote_device_names( + db_port, + db_host, + name_or_pattern_without_host); + } + } +} + +DeviceNames GroupElementFactory::resolve_local_device_names(const std::string& name_or_pattern) +{ + std::string& name_or_patern_non_const = const_cast(name_or_pattern); + Database db; + DbDatum db_data = db.get_device_exported(name_or_patern_non_const); + + DeviceNames device_names; + device_names.reserve(db_data.size()); + db_data >> device_names; + return device_names; +} + +DeviceNames GroupElementFactory::resolve_remote_device_names( + int db_port, + std::string& db_host, + std::string& name_or_pattern_without_host) +{ + ApiUtil& api_util = *ApiUtil::instance(); + const int db_index = api_util.get_db_ind(db_host, db_port); + Database& db = *(api_util.get_db_vect()[db_index]); + DbDatum db_data = db.get_device_exported(name_or_pattern_without_host); + + DeviceNames device_names; + device_names.reserve(db_data.size()); + db_data >> device_names; + return device_names; } void GroupElementFactory::parse_name (const std::string& p, string &db_host,int &db_port,string &dev_pattern) @@ -864,7 +884,7 @@ void Group::remove_i (const std::string& p, bool fwd) #endif if (name_equals(p)) { #if defined(_LOCAL_DEBUGGING) - cout << "Group::remove_i::failed to remove " << _p << " (can't remove self)" << endl; + cout << "Group::remove_i::failed to remove " << p << " (can't remove self)" << endl; #endif return; } diff --git a/cppapi/client/group.h b/cppapi/client/group.h index dfbc90895..6145b74af 100644 --- a/cppapi/client/group.h +++ b/cppapi/client/group.h @@ -56,13 +56,11 @@ class GroupElement; //============================================================================= // Misc. Typedefs //============================================================================= -//- group content (individual devices and/or sub-groups) typedef std::vector GroupElements; -//- group content iterator typedef GroupElements::iterator GroupElementsIterator; -//----------------------------------------------------------------------------- -//- define what is a list of token (for name pattern management) typedef std::vector TokenList; +typedef std::vector DeviceNames; + //============================================================================= // class ExtRequestDesc : an asynch. request holder for groups //----------------------------------------------------------------------------- @@ -585,14 +583,22 @@ class GroupAttrReplyList : public std::vector //============================================================================= class GroupElementFactory { - friend class Group; - +public: //- instanciatethe GroupElement which name matches the specified pattern with the specified timeout //- timeout = -1 => do not change the timeout static GroupElements instanciate (const std::string& p, int tmo = -1); +private: static void parse_name (const std::string& p, std::string &db_host, int &db_port, std::string &dev_pattern); + static GroupElements create_group_elements(const DeviceNames&, int timeout_millis); + static DeviceNames resolve_device_names(const std::string&); + static DeviceNames resolve_local_device_names(const std::string&); + static DeviceNames resolve_remote_device_names( + int db_port, + std::string& db_host, + std::string& name_or_pattern_without_host); + //- forbidden methods GroupElementFactory(); ~GroupElementFactory();