diff --git a/.gitignore b/.gitignore index 2270fecb2..664f01052 100644 --- a/.gitignore +++ b/.gitignore @@ -14,32 +14,22 @@ *.a # cmake output +*.cmake +*.build +*.xcodeproj CMakeFiles CMakeCache.txt -CTestTestfile.cmake +CMakeScripts Makefile -cmake_install.cmake -cmake_uninstall.cmake -cassandra-config-version.cmake -cassandra-config.cmake -cassandra-targets.cmake install_manifest.txt # build files -build/ -Testing/ +build +Testing +Debug demo/cql_demo test/unit_tests/cql_test -# external deps -ext/bin -ext/lib -ext/src -ext/share -ext/include -ext/ssl -ext/tmp - # editor *.swp *~ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f9d5a593..707f2132e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.0) +cmake_minimum_required(VERSION 2.6.4) set(PROJECT_NAME_STR cql) # Alias for project name used in unit tests set(CQL_DRIVER_PROJECT_NAME ${PROJECT_NAME_STR}) @@ -7,11 +7,10 @@ project(${PROJECT_NAME_STR} C CXX) #------------------- # The version number #------------------- - -set (cassandra_VERSION_MAJOR 0) -set (cassandra_VERSION_MINOR 7) -set (cassandra_VERSION_PATCH 0) -set (cassandra_VERSION_STRING ${cassandra_VERSION_MAJOR}.${cassandra_VERSION_MINOR}.${cassandra_VERSION_PATCH}) +set(PROJECT_VERSION_MAJOR 0) +set(PROJECT_VERSION_MINOR 7) +set(PROJECT_VERSION_PATCH 0) +set(PROJECT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) # todo: add version header @@ -28,43 +27,33 @@ set(CMAKE_MODULE_PATH ${EXT_PREFIX}) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) - - include(openssl) - include(zlib) - set(LIBS ${LIBS} ${openssl_STATIC_LIBRARIES} ) - set(LIBS ${LIBS} ${zlib_STATIC_LIBRARIES} ) else() set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_STATIC_RUNTIME OFF) - find_package(OpenSSL REQUIRED) - set(LIBS ${LIBS} ${OPENSSL_LIBRARIES} ) - - find_package(ZLIB REQUIRED) - set(LIBS ${LIBS} ${ZLIB_LIBRARIES} ) + # Disable boost auto linking feature + # it prevents visual studio from simultaneously building + # static and shared version of driver + # needed by boost to link dynamically + # this is a noop on platforms other than windows + add_definitions(-DBOOST_ALL_DYN_LINK) + add_definitions(-DBOOST_ALL_NO_LIB) endif() -# Boost set(Boost_USE_MULTITHREADED ON) -find_package(Boost 1.54.0 COMPONENTS atomic system thread unit_test_framework date_time REQUIRED) +find_package(Boost 1.41.0 COMPONENTS system thread unit_test_framework date_time program_options REQUIRED) set(LIBS ${LIBS} ${Boost_LIBRARIES}) +find_package(OpenSSL REQUIRED) +set(LIBS ${LIBS} ${OPENSSL_LIBRARIES}) + +find_package(ZLIB REQUIRED) +set(LIBS ${LIBS} ${ZLIB_LIBRARIES}) + # Threading find_package(Threads REQUIRED) set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT}) -# ------------------------------------------------------------- -# Find libCDS library -# ------------------------------------------------------------- -# Allow access to custom FindLIBCDS module -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") - -find_package(LIBCDS REQUIRED) - -set(LIBS ${LIBS} ${LIBCDS_LIBRARIES}) -set(INCLUDES ${INCLUDES} ${LIBCDS_INCLUDE_DIRS}) -# ------------------------------------------------------------- - # Build up the include path's set(INCLUDES ${INCLUDES} ${OPENSSL_INCLUDE_DIR} ) set(INCLUDES ${INCLUDES} ${ZLIB_INCLUDE_DIR} ) @@ -73,14 +62,6 @@ set(INCLUDES ${INCLUDES} ${Boost_INCLUDE_DIRS} ) set(PROJECT_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) set(INCLUDES ${INCLUDES} ${PROJECT_INCLUDE_DIR}) - -# disable boost auto linking feature -# it prevents visual studio from simultaneously building -# static and shared version of driver -# needed by boost to link dynamically -add_definitions(-DBOOST_ALL_DYN_LINK) -add_definitions(-DBOOST_ALL_NO_LIB) - set(MULTICORE_CORES_NUMBER "3" CACHE STRING "Number of cores (for multicore compilation)") option(MULTICORE_COMPILATION "Enable multicore compilation" OFF) @@ -88,7 +69,7 @@ if(MULTICORE_COMPILATION) # MULTICORE BUILD # by default we use 3 cores if(MSVC) - add_definitions("/MP${MULTICORE_CORES_NUMBER}") + add_definitions("/MP${MULTICORE_CORES_NUMBER}") endif() # on linux platform this parameter is named -j e.g. -j 5 # but should be passed to MAKE program not to compiler! @@ -109,11 +90,14 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") else() # GCC specific compiler options # I disabled long-long warning because boost generates about 50 such warnings - # -std=c++0x, -fno-strict-aliasing :: required by libcds - set(PLATFORM_DEPENDENT_COMPILER_OPTIONS "-fPIC -Wall -pedantic -std=c++0x -Wno-long-long -fno-strict-aliasing") + set(PLATFORM_DEPENDENT_COMPILER_OPTIONS "-fPIC -Wall -pedantic -Wno-long-long -fno-strict-aliasing") endif() +# add_custom_target (AppDependencies ALL +# DEPENDS ${APP_DEPENDENCIES} +# COMMENT "Installing any missing dependencies.") + #------------------- # Cassandra static and shared #------------------- @@ -130,73 +114,63 @@ include_directories(${INCLUDES}) # we must add header files as dependencies (if header # changes project must be recompiled, right). file(GLOB INC_FILES - ${PROJECT_SOURCE_DIR}/include/cql/*.hpp ) - -file(GLOB INC_EXCEPTION_FILES - ${PROJECT_SOURCE_DIR}/include/cql/exceptions/*.hpp ) - + ${PROJECT_SOURCE_DIR}/include/cql/*.hpp ) + +file(GLOB INC_FILES_EXCEPTIONS + ${PROJECT_SOURCE_DIR}/include/cql/exceptions/*.hpp ) + file(GLOB INC_FILES_INTERNAL ${PROJECT_SOURCE_DIR}/include/cql/internal/*.hpp ) -file(GLOB INC_FILES_LOCKFREE - ${PROJECT_SOURCE_DIR}/include/cql/lockfree/*.hpp ) - file(GLOB INC_FILES_POLICIES ${PROJECT_SOURCE_DIR}/include/cql/policies/*.hpp ) - + file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/cql/*.cpp) -file(GLOB SRC_EXCEPTION_FILES +file(GLOB SRC_FILES_EXCEPTIONS ${PROJECT_SOURCE_DIR}/src/cql/exceptions/*.cpp ) file(GLOB SRC_FILES_INTERNAL ${PROJECT_SOURCE_DIR}/src/cql/internal/*.cpp ) -file(GLOB SRC_FILES_LOCKFREE - ${PROJECT_SOURCE_DIR}/src/cql/lockfree/*.cpp ) - file(GLOB SRC_FILES_POLICIES ${PROJECT_SOURCE_DIR}/src/cql/policies/*.cpp ) - + source_group("Source Files" FILES ${SRC_FILES}) source_group("Source Files\\Internal" FILES ${SRC_FILES_INTERNAL}) -source_group("Source Files\\Exceptions" FILES ${SRC_EXCEPTION_FILES}) -source_group("Source Files\\Lock Free" FILES ${SRC_FILES_LOCKFREE}) +source_group("Source Files\\Exceptions" FILES ${SRC_FILES_EXCEPTIONS}) source_group("Source Files\\Policies" FILES ${SRC_FILES_POLICIES}) source_group("Header Files" FILES ${INC_FILES}) source_group("Header Files\\Internal" FILES ${INC_FILES_INTERNAL}) -source_group("Header Files\\Exceptions" FILES ${INC_EXCEPTION_FILES}) -source_group("Header Files\\Lock Free" FILES ${INC_FILES_LOCKFREE}) +source_group("Header Files\\Exceptions" FILES ${INC_FILES_EXCEPTIONS}) source_group("Header Files\\Policies" FILES ${INC_FILES_POLICIES}) -set(ALL_SOURCE_FILES - ${SRC_FILES} ${SRC_FILES_INTERNAL} ${SRC_EXCEPTION_FILES} ${SRC_FILES_LOCKFREE} ${SRC_FILES_POLICIES} - ${INC_FILES} ${INC_FILES_INTERNAL} ${INC_EXCEPTION_FILES} ${INC_FILES_LOCKFREE} ${INC_FILES_POLICIES}) +set(ALL_SOURCE_FILES + ${SRC_FILES} ${SRC_FILES_INTERNAL} ${SRC_FILES_EXCEPTIONS} ${SRC_FILES_POLICIES} + ${INC_FILES} ${INC_FILES_INTERNAL} ${INC_FILES_EXCEPTIONS} ${INC_FILES_POLICIES}) # build dynamic and static version of library - -# !!!! DYNAMIC TARGET CURRENTY DISABLED (TOO SPEED UP COMPILATION) -# add_library(${PROJECT_LIB_NAME} SHARED ${ALL_SOURCE_FILES}) +add_library(${PROJECT_LIB_NAME} SHARED ${ALL_SOURCE_FILES}) set(PROJECT_LIB_NAME_STATIC "${PROJECT_LIB_NAME}_static") add_library(${PROJECT_LIB_NAME_STATIC} STATIC ${ALL_SOURCE_FILES}) -#target_link_libraries(${PROJECT_LIB_NAME} ${LIBS}) +target_link_libraries(${PROJECT_LIB_NAME} ${LIBS}) target_link_libraries(${PROJECT_LIB_NAME_STATIC} ${LIBS}) -#set_target_properties(${PROJECT_LIB_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_LIB_NAME}) -#set_target_properties(${PROJECT_LIB_NAME} PROPERTIES VERSION ${cassandra_VERSION_STRING} SOVERSION ${cassandra_VERSION_MAJOR}) +set_target_properties(${PROJECT_LIB_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_LIB_NAME}) +set_target_properties(${PROJECT_LIB_NAME} PROPERTIES VERSION ${PROJECT_VERSION_STRING} SOVERSION ${PROJECT_VERSION_MAJOR}) set_target_properties(${PROJECT_LIB_NAME_STATIC} PROPERTIES OUTPUT_NAME ${PROJECT_LIB_NAME_STATIC}) -set_target_properties(${PROJECT_LIB_NAME_STATIC} PROPERTIES VERSION ${cassandra_VERSION_STRING} SOVERSION ${cassandra_VERSION_MAJOR}) +set_target_properties(${PROJECT_LIB_NAME_STATIC} PROPERTIES VERSION ${PROJECT_VERSION_STRING} SOVERSION ${PROJECT_VERSION_MAJOR}) set(PROJECT_COMPILER_FLAGS "${CMAKE_CXX_FLAGS} ${PLATFORM_DEPENDENT_COMPILER_OPTIONS}") -#set_property( -# TARGET ${PROJECT_LIB_NAME} -# APPEND PROPERTY COMPILE_FLAGS ${PROJECT_COMPILER_FLAGS}) +set_property( + TARGET ${PROJECT_LIB_NAME} + APPEND PROPERTY COMPILE_FLAGS ${PROJECT_COMPILER_FLAGS}) set_property( TARGET ${PROJECT_LIB_NAME_STATIC} @@ -206,23 +180,26 @@ set_property( # install target #------------------- -file(GLOB INSTALL_HEADERS "${PROJECT_INCLUDE_DIR}/cql/*.hpp") - # Where to put headers set(INSTALL_HEADERS_DIR "${CMAKE_INSTALL_PREFIX}/include/cql") -install(FILES ${INSTALL_HEADERS} DESTINATION "${INSTALL_HEADERS_DIR}") +install(FILES ${INC_FILES} DESTINATION "${INSTALL_HEADERS_DIR}") +install(FILES ${INC_FILES_EXCEPTIONS} DESTINATION "${INSTALL_HEADERS_DIR}/exceptions") +install(FILES ${INC_FILES_POLICIES} DESTINATION "${INSTALL_HEADERS_DIR}/policies") # Where to put libraries set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") # For windows only set(INSTALL_DLL_DIR "${CMAKE_INSTALL_PREFIX}/bin") -#install(TARGETS ${PROJECT_LIB_NAME_STATIC} ${PROJECT_LIB_NAME} -install(TARGETS ${PROJECT_LIB_NAME_STATIC} - RUNTIME DESTINATION ${INSTALL_DLL_DIR} # for dll files - LIBRARY DESTINATION ${INSTALL_LIB_DIR} # for shared library - ARCHIVE DESTINATION ${INSTALL_LIB_DIR}) # for static library +install(TARGETS ${PROJECT_LIB_NAME} + RUNTIME DESTINATION ${INSTALL_DLL_DIR} # for dll files + LIBRARY DESTINATION ${INSTALL_LIB_DIR} # for shared library + ARCHIVE DESTINATION ${INSTALL_LIB_DIR}) # for static library +install(TARGETS ${PROJECT_LIB_NAME_STATIC} + RUNTIME DESTINATION ${INSTALL_DLL_DIR} # for dll files + LIBRARY DESTINATION ${INSTALL_LIB_DIR} # for shared library + ARCHIVE DESTINATION ${INSTALL_LIB_DIR}) # for static library #------------------- # uninstall target @@ -236,23 +213,14 @@ configure_file( add_custom_target(UNINSTALL COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) - #------------------- # Boost unit tests #------------------- -add_subdirectory(extra/ccm_bridge) -add_subdirectory(test/unit_tests) +# add_subdirectory(extra/ccm_bridge) +# add_subdirectory(test/unit_tests) #------------------- # the demo program #------------------- - add_subdirectory(demo) - -#------------------- -# test libcds -#------------------- - -# Exclude demo from CMAKE build system -# add_subdirectory(test/libcds_demo) diff --git a/Demo_cql b/Demo_cql deleted file mode 100755 index c0a6085d9..000000000 Binary files a/Demo_cql and /dev/null differ diff --git a/README.md b/README.md index 584fc6c10..fdcddbee1 100644 --- a/README.md +++ b/README.md @@ -55,41 +55,39 @@ In addition to the sample code below there is a fully functional [demo](https:// #include #include #include -#include int main(int argc, char**) { using namespace cql; using boost::shared_ptr; - - // Boilerplate: initialize cql with 512 hazard pointers. - cql_initialize(512); + + // initialize cql + cql_initialize(); cql_thread_infrastructure_t cql_ti; - + // Suppose you have the Cassandra cluster at 127.0.0.1, // listening at default port (9042). shared_ptr builder = cql::cql_cluster_t::builder(); builder->add_contact_point(boost::asio::ip::address::from_string("127.0.0.1")); - + // Now build a model of cluster and connect it to DB. shared_ptr cluster(builder->build()); shared_ptr session(cluster->connect()); - + // Write a query, switch keyspaces. shared_ptr my_first_query(new cql::cql_query_t("SELECT * FROM system.schema_keyspaces;")); - + // Send the query. boost::shared_future future = session->query(my_first_query); - + // Wait for the query to execute; retrieve the result. future.wait(); shared_ptr result = future.get().result; - + // Boilerplate: close the connection session and perform the cleanup. session->close(); cluster->shutdown(); - cds::gc::HP::force_dispose(); return 0; } ``` @@ -111,4 +109,3 @@ 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. - diff --git a/cmake/Modules/FindLIBCDS.cmake b/cmake/Modules/FindLIBCDS.cmake deleted file mode 100644 index 5a4e58592..000000000 --- a/cmake/Modules/FindLIBCDS.cmake +++ /dev/null @@ -1,56 +0,0 @@ -# System must have set LIBCDS_ROOT -# environmental variable set -# (on linux we also try to guess if library is -# available). -# -# OUTPUT: -# LIBCDS_FOUND - is set to YES if library was found -# LIBCDS_INCLUDE_DIRS - include dirs to libCDS library -# LIBCDS_LIBRARIES - list of libCDS libraries -# - -include(FindPackageHandleStandardArgs) - -find_path(LIBCDS_INCLUDE_DIRS - NAMES cds - PATHS ENV LIBCDS_ROOT - PATH_SUFFIXES include - DOC "LIBCDS include directory") - -if(WIN32 AND MSVC) - # In Visual Studio we must link to proper version of library - find_library(LIBCDS_LIBRARY_RELEASE - NAMES libcds-x86-vc10 - PATHS ENV LIBCDS_ROOT - PATH_SUFFIXES lib - DOC "LIBSSH library directory") - - find_library(LIBCDS_LIBRARY_DEBUG - NAMES libcds-x86-vc10_debug - PATHS ENV LIBCDS_ROOT - PATH_SUFFIXES lib - DOC "LIBCDS library directory") -else() - find_library(LIBCDS_LIBRARY_RELEASE - NAMES libcds cds - PATHS ENV LIBCDS_ROOT - /usr/local/lib - PATH_SUFFIXES lib - DOC "LIBSSH library directory") - - find_library(LIBCDS_LIBRARY_DEBUG - NAMES libcds-debug cds-debug - PATHS ENV LIBCDS_ROOT - /usr/local/lib - PATH_SUFFIXES lib - DOC "LIBCDS library directory") -endif() - -# Select debug or release version of library -include(SelectLibraryConfigurations) -select_library_configurations(LIBCDS) - -set(LIBCDS_LIBRARIES ${LIBCDS_LIBRARY}) - -find_package_handle_standard_args(LIBCDS DEFAULT_MSG LIBCDS_LIBRARIES LIBCDS_INCLUDE_DIRS) -mark_as_advanced(LIBCDS_INCLUDE_DIRS LIBCDS_LIBRARIES) diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 58aba257c..55c2b9f1d 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -1,28 +1,32 @@ #------------------- # Demo #------------------- -cmake_minimum_required(VERSION 2.8.11) +cmake_minimum_required(VERSION 2.6.4) -set(DEMO Demo_${CQL_DRIVER_PROJECT_NAME}) -project(${DEMO} C CXX) +# set(DEMO Demo_${CQL_DRIVER_PROJECT_NAME}) +# project(${DEMO} C CXX) -file(GLOB DEMO_SRC_FILES *.cpp) +# file(GLOB DEMO_SRC_FILES *.cpp) -# Add EXCLUDE_FROM_ALL flag to exclude demo project -# from ALL target -add_executable(${DEMO} ${DEMO_SRC_FILES}) +# # Add EXCLUDE_FROM_ALL flag to exclude demo project +# # from ALL target +# add_executable(${DEMO} ${DEMO_SRC_FILES}) + +# set_property( +# TARGET ${DEMO} +# APPEND PROPERTY COMPILE_FLAGS ${PROJECT_COMPILER_FLAGS}) -set_property( - TARGET ${DEMO} - APPEND PROPERTY COMPILE_FLAGS ${PROJECT_COMPILER_FLAGS}) -# Setup include directories -# Directories are inherited from parent project -set(CCM_BRIDGE_INCLUDES "${CMAKE_PROJECT_SOURCE}/extra/ccm_bridge/include") -target_include_directories(${DEMO} PUBLIC ${INCLUDES} ${CCM_BRIDGE_INCLUDES}) -target_link_libraries(${DEMO} ${LIBS} ${PROJECT_LIB_NAME_STATIC} CCMBridge) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ".") +set(PROJECT_DEMO_NAME ${PROJECT_NAME_STR}_demo) -add_dependencies(${DEMO} ${PROJECT_LIB_NAME_STATIC}) -add_dependencies(${DEMO} CCMBridge) \ No newline at end of file +file(GLOB DEMO_SRC_FILES ${PROJECT_SOURCE_DIR}/demo/*.cpp) +include_directories(${INCLUDES}) +add_executable(${PROJECT_DEMO_NAME} ${DEMO_SRC_FILES}) +target_link_libraries(${PROJECT_DEMO_NAME} ${LIBS} ${PROJECT_LIB_NAME}) + +set_property( + TARGET ${PROJECT_DEMO_NAME} + APPEND PROPERTY COMPILE_FLAGS ${PROJECT_COMPILER_FLAGS}) \ No newline at end of file diff --git a/demo/main.cpp b/demo/main.cpp index be4c83640..b4e9723d2 100644 --- a/demo/main.cpp +++ b/demo/main.cpp @@ -19,12 +19,16 @@ #include #include +#include #include #include #include #include #include #include +#include +#include +#include #include #include @@ -36,14 +40,6 @@ #include #include #include -#include - -#include -#include - -#include - -using namespace cql; // helper function to print query results void @@ -54,12 +50,13 @@ print_rows( for (size_t i = 0; i < result.column_count(); ++i) { cql::cql_byte_t* data = NULL; cql::cql_int_t size = 0; - + result.get_data(i, &data, size); - + std::cout.write(reinterpret_cast(data), size); - for(int i = size; i < 25; i++) + for (int i = size; i < 25; i++) { std::cout << ' ' ; + } std::cout << " | "; } std::cout << std::endl; @@ -76,26 +73,17 @@ log_callback( std::cout << "LOG: " << message << std::endl; } -void demo(bool use_ssl) { - cql::cql_thread_infrastructure_t cql_ti; - +void +demo( + const std::string& host, + bool use_ssl) +{ try { - int numberOfNodes = 1; - - const cql_ccm_bridge_configuration_t& conf = cql::get_ccm_bridge_configuration(); - cql_ccm_bridge_t::create(conf, "test", numberOfNodes, true); - boost::shared_ptr builder = cql::cql_cluster_t::builder(); builder->with_log_callback(&log_callback); + builder->add_contact_point(boost::asio::ip::address::from_string(host)); - for(int i=1;i<=numberOfNodes;i++) - builder->add_contact_point( - boost::asio::ip::address::from_string( - conf.ip_prefix() + boost::lexical_cast(i))); - - // decide which client factory we want, SSL or non-SSL. This is a hack, if you pass any commandline arg to the - // binary it will use the SSL factory, non-SSL by default if (use_ssl) { builder->with_ssl(); } @@ -103,17 +91,13 @@ void demo(bool use_ssl) { boost::shared_ptr cluster(builder->build()); boost::shared_ptr session(cluster->connect()); - if(session) { - - - // The connection succeeded - std::cout << "TRUE" << std::endl; + if (session) { // execute a query, switch keyspaces boost::shared_ptr use_system( new cql::cql_query_t("USE system;", cql::CQL_CONSISTENCY_ONE)); - - + + boost::shared_future future = session->query(use_system); // wait for the query to execute @@ -142,7 +126,6 @@ void demo(bool use_ssl) { } cluster->shutdown(); - cds::gc::HP::force_dispose(); std::cout << "THE END" << std::endl; } catch (std::exception& e) @@ -152,78 +135,38 @@ void demo(bool use_ssl) { } int -main(int argc, char**) +main( + int argc, + char** vargs) { - cql::cql_initialize(512); - - bool use_ssl = argc > 1; - demo(use_ssl); - - cql::cql_terminate(); - return 0; -} + bool ssl = false; + std::string host; + + boost::program_options::options_description desc("Options"); + desc.add_options() + ("help", "produce help message") + ("ssl", boost::program_options::value(&ssl)->default_value(false), "use SSL") + ("host", boost::program_options::value(&host)->default_value("127.0.0.1"), "node to use as initial contact point"); + + boost::program_options::variables_map variables_map; + try { + boost::program_options::store(boost::program_options::parse_command_line(argc, vargs, desc), variables_map); + boost::program_options::notify(variables_map); + } + catch (boost::program_options::unknown_option ex) { + std::cerr << desc << "\n"; + std::cerr << ex.what() << "\n"; + return 1; + } -template -struct split_list_map_traits_t - : public cds::container::split_list::type_traits -{ - typedef cds::container::michael_list_tag ordered_list ; - typedef std::hash hash ; - - struct ordered_list_traits: public cds::container::michael_list::type_traits { - typedef std::less less; - }; -}; - -template -struct sl_map_t { - typedef - cds::container::SplitListMap > - type; -}; - -class my_type { -public: - my_type(const std::string& name) - : _name(name) { - std::cout << "type with name '" << name << "' created" << std::endl; - } - - ~my_type() { - std::cout << "type with name '" << _name << "' destroyed" << std::endl; + if (variables_map.count("help")) { + std::cerr << desc << "\n"; + return 0; } - - const std::string& - name() const { return _name; } -private: - std::string _name; -}; - -int main3(int, char**) { + cql::cql_initialize(); - { - cql::cql_thread_infrastructure_t t; - - { - sl_map_t >::type map; - for(int i = 0; i < 10; i++) { - map.insert(i, - boost::shared_ptr(new my_type("foo" + boost::lexical_cast(i)))); - } - - for(sl_map_t >::type::iterator it = map.begin(); - it != map.end(); ++it) - { - std::cout << "key: " << it->first << ", value: " << it->second->name() << std::endl; - map.erase(it->first); - } - - std::cout << "after loop, size:" << map.size() << std::endl; - } - } - - std::cout << "before terminate" << std::endl; + demo(host, ssl); + cql::cql_terminate(); - std::cout << "after terminate" << std::endl; - return 0; -} \ No newline at end of file + return 0; +} diff --git a/ext/libcds_osx_srcs.zip b/ext/libcds_osx_srcs.zip deleted file mode 100644 index e5f35e3aa..000000000 Binary files a/ext/libcds_osx_srcs.zip and /dev/null differ diff --git a/ext/openssl.cmake b/ext/openssl.cmake deleted file mode 100644 index 3e34e9eb6..000000000 --- a/ext/openssl.cmake +++ /dev/null @@ -1,42 +0,0 @@ -# -# Install openssl from source -# - -if (NOT openssl_NAME) - -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7) - -include(ExternalProject) -include(zlib) - -if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # On Mac, 64-bit builds must be manually requested. - set (SSL_CONFIGURE_COMMAND ./Configure darwin64-x86_64-cc ) -else() - # The config script seems to auto-select the platform correctly on linux - # It calls ./Configure for us. - set (SSL_CONFIGURE_COMMAND ./config) -endif() - -set(ABBREV "openssl") -set(${ABBREV}_NAME ${ABBREV}) -set(${ABBREV}_INCLUDE_DIRS ${EXT_PREFIX}/include) -set(APP_DEPENDENCIES ${APP_DEPENDENCIES} ${ABBREV}) - -message("Installing ${openssl_NAME} into ext build area: ${EXT_PREFIX} ...") - -ExternalProject_Add(openssl - DEPENDS zlib - PREFIX ${EXT_PREFIX} - URL http://openssl.org/source/openssl-1.0.0e.tar.gz - URL_MD5 "7040b89c4c58c7a1016c0dfa6e821c86" - PATCH_COMMAND "" - CONFIGURE_COMMAND ${SSL_CONFIGURE_COMMAND} zlib no-shared no-zlib-dynamic --prefix=${EXT_PREFIX} - BUILD_IN_SOURCE 1 - ) - -set(${ABBREV}_STATIC_LIBRARIES ${EXT_PREFIX}/lib/libcrypto.a ${EXT_PREFIX}/lib/libssl.a) - -set_target_properties(${openssl_NAME} PROPERTIES EXCLUDE_FROM_ALL ON) - -endif(NOT openssl_NAME) diff --git a/ext/zlib.cmake b/ext/zlib.cmake deleted file mode 100644 index e0f99528e..000000000 --- a/ext/zlib.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# -# Install zlib from source -# - -if (NOT zlib_NAME) - -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7) - -include (ExternalProject) - -set(ABBREV "zlib") -set(${ABBREV}_NAME ${ABBREV}) -set(${ABBREV}_INCLUDE_DIRS ${EXT_PREFIX}/include) -set(APP_DEPENDENCIES ${APP_DEPENDENCIES} ${ABBREV}) - -message("Installing ${zlib_NAME} into ext build area: ${EXT_PREFIX} ...") - -ExternalProject_Add(zlib - PREFIX ${EXT_PREFIX} - URL http://zlib.net/zlib-1.2.8.tar.gz - URL_MD5 "44d667c142d7cda120332623eab69f40" - PATCH_COMMAND "" - CONFIGURE_COMMAND ./configure -p=${EXT_PREFIX} --static --64 - BUILD_COMMAND make - INSTALL_COMMAND make install prefix=${EXT_PREFIX} - BUILD_IN_SOURCE 1 - ) - -set(${ABBREV}_STATIC_LIBRARIES ${EXT_PREFIX}/lib/libz.a) - -set_target_properties(${zlib_NAME} PROPERTIES EXCLUDE_FROM_ALL ON) - -endif (NOT zlib_NAME) diff --git a/include/cql/common_type_definitions.hpp b/include/cql/common_type_definitions.hpp index a36475929..26812d2b0 100644 --- a/include/cql/common_type_definitions.hpp +++ b/include/cql/common_type_definitions.hpp @@ -1,4 +1,4 @@ -/* +/* * File: common_type_definitions.hpp * Author: mc * @@ -12,31 +12,14 @@ #include #include "cql/cql_endpoint.hpp" -#include "cql/lockfree/cql_lockfree_hash_map.hpp" #include "cql/cql_uuid.hpp" #include "cql/cql_connection.hpp" namespace cql { - -typedef - cql::cql_lockfree_hash_map_t< - cql_uuid_t, - boost::shared_ptr > - cql_connections_collection_t; -typedef - cql::cql_lockfree_hash_map_t< - cql_endpoint_t, - // if we use shared_ptr's here, there would be an assertion error at program end - // i cannot figure out what was cause of this bug, but not using - // shared_ptr's helped. - cql_connections_collection_t* > - cql_connection_pool_t; - -typedef + typedef std::map cql_credentials_t; } #endif /* COMMON_TYPE_DEFINITIONS_HPP_ */ - diff --git a/include/cql/cql.hpp b/include/cql/cql.hpp index bda2e6117..81baa393d 100644 --- a/include/cql/cql.hpp +++ b/include/cql/cql.hpp @@ -23,7 +23,7 @@ #include namespace cql { - + typedef ::uint8_t cql_byte_t; typedef ::uint16_t cql_short_t; typedef ::int32_t cql_int_t; @@ -154,29 +154,14 @@ to_string(const cql_consistency_enum); // with library. // This function MUST be called only once. // This function is NOT thread safe. -// @hazard_pointers_count - number of hazard pointers used by -// libcds. void -cql_initialize(size_t const hazard_pointers_count = 128); +cql_initialize(); // Terminates cql library. // This function must be called at program end, this MUST // be called only once. -void +void cql_terminate(); -struct cql_thread_infrastructure_impl_t; - -// This class must be instantinated on EVERY thread that uses libcql. -class cql_thread_infrastructure_t: public boost::noncopyable { -public: - // Throws cql::cql_initialization_exception when initializaton - // fails. - cql_thread_infrastructure_t(); - ~cql_thread_infrastructure_t(); -private: - cql_thread_infrastructure_impl_t* _this; -}; - } // namespace cql #endif // __CQL_H_INCLUDED__ diff --git a/include/cql/cql_builder.hpp b/include/cql/cql_builder.hpp index 362d81c6a..415f13bb9 100644 --- a/include/cql/cql_builder.hpp +++ b/include/cql/cql_builder.hpp @@ -22,48 +22,56 @@ namespace cql { class cql_cluster_t; -class cql_client_options_t { +class cql_client_options_t +{ public: - cql_client_options_t(cql_connection_t::cql_log_callback_t log_callback) - : _log_callback(log_callback) {} + cql_client_options_t( + cql_connection_t::cql_log_callback_t log_callback) : + _log_callback(log_callback) + {} - inline cql_connection_t::cql_log_callback_t - log_callback() const { + inline cql_connection_t::cql_log_callback_t + log_callback() const + { return _log_callback; } private: cql_connection_t::cql_log_callback_t _log_callback; - }; -class cql_protocol_options_t { +class cql_protocol_options_t +{ public: cql_protocol_options_t( - const std::list& contact_points, - boost::shared_ptr ssl_context) - : _contact_points(contact_points), - _ssl_context(ssl_context) { } - - const std::list& - contact_points() const { + const std::list& contact_points, + boost::shared_ptr ssl_context) : + _contact_points(contact_points), + _ssl_context(ssl_context) + {} + + const std::list& + contact_points() const + { return _contact_points; } - - boost::shared_ptr - ssl_context() const { + + boost::shared_ptr + ssl_context() const + { return _ssl_context; } private: - const std::list _contact_points; - boost::shared_ptr _ssl_context; - + const std::list _contact_points; + boost::shared_ptr _ssl_context; }; -class cql_pooling_options_t { +class cql_pooling_options_t +{ public: - cql_pooling_options_t() { + cql_pooling_options_t() + { _min_simultaneous_requests_for_local = default_min_requests; _min_simultaneous_requests_for_remote = default_min_requests; @@ -76,9 +84,11 @@ class cql_pooling_options_t { _max_connections_for_local = default_max_pool_local; _max_connections_for_remote = default_max_pool_remote; } - - int - min_simultaneous_requests_per_connection_treshold(cql_host_distance_enum distance) const { + + int + min_simultaneous_requests_per_connection_treshold( + cql_host_distance_enum distance) const + { switch (distance) { case CQL_HOST_DISTANCE_LOCAL: return _min_simultaneous_requests_for_local; case CQL_HOST_DISTANCE_REMOTE: return _min_simultaneous_requests_for_remote; @@ -88,14 +98,14 @@ class cql_pooling_options_t { } } - cql_pooling_options_t& + cql_pooling_options_t& set_min_simultaneous_requests_per_connection_treshold( - cql_host_distance_enum distance, - int min_simultaneous_connections) + cql_host_distance_enum distance, + int min_simultaneous_connections) { - if(min_simultaneous_connections < 0) + if (min_simultaneous_connections < 0) throw std::invalid_argument("min_simultaneous_connections cannot be negative."); - + switch (distance) { case CQL_HOST_DISTANCE_LOCAL: _min_simultaneous_requests_for_local = min_simultaneous_connections; @@ -108,12 +118,14 @@ class cql_pooling_options_t { default: throw std::invalid_argument("invalid distance value."); } - + return *this; } - int - max_simultaneous_requests_per_connection_treshold(cql_host_distance_enum distance) const { + int + max_simultaneous_requests_per_connection_treshold( + cql_host_distance_enum distance) const + { switch (distance) { case CQL_HOST_DISTANCE_LOCAL: return _max_simultaneous_requests_for_local; case CQL_HOST_DISTANCE_REMOTE: return _max_simultaneous_requests_for_remote; @@ -123,10 +135,10 @@ class cql_pooling_options_t { } } - cql_pooling_options_t& + cql_pooling_options_t& set_max_simultaneous_requests_per_connection_treshold( - cql_host_distance_enum distance, - int max_simultaneous_requests) + cql_host_distance_enum distance, + int max_simultaneous_requests) { switch (distance) { case CQL_HOST_DISTANCE_LOCAL: @@ -137,15 +149,15 @@ class cql_pooling_options_t { break; case CQL_HOST_DISTANCE_IGNORE: break; - + default: throw std::invalid_argument("Cannot set max streams per connection threshold"); } - + return *this; } - int + int core_connections_per_host(cql_host_distance_enum distance) const { switch (distance) { case CQL_HOST_DISTANCE_LOCAL: return _core_connections_for_local; @@ -156,11 +168,15 @@ class cql_pooling_options_t { } } - cql_pooling_options_t& - set_core_connections_per_host(cql_host_distance_enum distance, int core_connections) { - if(core_connections < 0) + cql_pooling_options_t& + set_core_connections_per_host( + cql_host_distance_enum distance, + int core_connections) + { + if (core_connections < 0) { throw std::invalid_argument("core_connections cannot be negative."); - + } + switch (distance) { case CQL_HOST_DISTANCE_LOCAL: _core_connections_for_local = core_connections; @@ -170,15 +186,17 @@ class cql_pooling_options_t { break; case CQL_HOST_DISTANCE_IGNORE: break; - + default: throw std::invalid_argument("invlaid distance value."); } return *this; } - int - max_connection_per_host(cql_host_distance_enum distance) const { + int + max_connection_per_host( + cql_host_distance_enum distance) const + { switch (distance) { case CQL_HOST_DISTANCE_LOCAL: return _max_connections_for_local; case CQL_HOST_DISTANCE_REMOTE: return _max_connections_for_remote; @@ -188,8 +206,11 @@ class cql_pooling_options_t { } } - cql_pooling_options_t& - set_max_connections_per_host(cql_host_distance_enum distance, int max_connections) { + cql_pooling_options_t& + set_max_connections_per_host( + cql_host_distance_enum distance, + int max_connections) + { switch (distance) { case CQL_HOST_DISTANCE_LOCAL: _max_connections_for_local = max_connections; @@ -204,7 +225,7 @@ class cql_pooling_options_t { } return *this; } - + private: static const int default_min_requests = 25; static const int default_max_requests = 100; @@ -230,183 +251,232 @@ class cql_pooling_options_t { class cql_policies_t { public: - cql_policies_t() - : _load_balancing_policy(new cql_round_robin_policy_t()), - _reconnection_policy(new cql_exponential_reconnection_policy_t( - /* base dealy: */ boost::posix_time::seconds(1), - /* max delay : */ boost::posix_time::minutes(10))), - _retry_policy(new cql_default_retry_policy_t()) - { } - + cql_policies_t() : + _load_balancing_policy(new cql_round_robin_policy_t()), + _reconnection_policy( + new cql_exponential_reconnection_policy_t( + boost::posix_time::seconds(1), // base dealy: + boost::posix_time::minutes(10))), // max delay + _retry_policy(new cql_default_retry_policy_t()) + {} + cql_policies_t( boost::shared_ptr load_balancing_policy, boost::shared_ptr reconnection_policy, - boost::shared_ptr retry_policy) - : _load_balancing_policy(load_balancing_policy), - _reconnection_policy(reconnection_policy), - _retry_policy(retry_policy) - { } - - inline boost::shared_ptr - load_balancing_policy() const { + boost::shared_ptr retry_policy) : + _load_balancing_policy(load_balancing_policy), + _reconnection_policy(reconnection_policy), + _retry_policy(retry_policy) + {} + + inline boost::shared_ptr + load_balancing_policy() const + { return _load_balancing_policy; } - - inline boost::shared_ptr - reconnection_policy() const { + + inline boost::shared_ptr + reconnection_policy() const + { return _reconnection_policy; } - + inline boost::shared_ptr - retry_policy() const { + retry_policy() const + { return _retry_policy; } - + private: friend class cql_configuration_t; - virtual void - init(cql_cluster_t* cluster) { + virtual void + init(cql_cluster_t* cluster) + { assert(cluster != NULL); _load_balancing_policy->init(cluster); } - + boost::shared_ptr _load_balancing_policy; boost::shared_ptr _reconnection_policy; boost::shared_ptr _retry_policy; }; -class cql_configuration_t { +class cql_configuration_t +{ public: - cql_configuration_t(const cql_client_options_t& client_options, - const cql_protocol_options_t& protocol_options, - const cql_pooling_options_t& pooling_options, - const cql_policies_t& policies, - const cql_credentials_t& credentials) - : _client_options(client_options) - , _protocol_options(protocol_options) - , _pooling_options(pooling_options) - , _policies(policies) - , _credentials(credentials) - { } - - inline const cql_protocol_options_t& - protocol_options() const { + cql_configuration_t( + boost::asio::io_service& io_service, + const cql_client_options_t& client_options, + const cql_protocol_options_t& protocol_options, + const cql_pooling_options_t& pooling_options, + const cql_policies_t& policies, + const cql_credentials_t& credentials) : + _io_service(io_service), + _client_options(client_options), + _protocol_options(protocol_options), + _pooling_options(pooling_options), + _policies(policies), + _credentials(credentials) + {} + + inline const cql_protocol_options_t& + protocol_options() const + { return _protocol_options; } - - inline const cql_client_options_t& - client_options() const { + + inline const cql_client_options_t& + client_options() const + { return _client_options; } - - inline const cql_pooling_options_t& - pooling_options() const { + + inline const cql_pooling_options_t& + pooling_options() const + { return _pooling_options; } - - inline const cql_policies_t& - policies() const { + + inline const cql_policies_t& + policies() const + { return _policies; } - + inline const cql_credentials_t& - credentials() const { + credentials() const + { return _credentials; } + inline boost::asio::io_service& + io_service() + { + return _io_service; + } + private: friend class cql_cluster_impl_t; - - void - init(cql_cluster_t* cluster) { + + void + init(cql_cluster_t* cluster) + { _policies.init(cluster); } - - cql_client_options_t _client_options; - cql_protocol_options_t _protocol_options; - cql_pooling_options_t _pooling_options; - cql_policies_t _policies; - cql_credentials_t _credentials; + + boost::asio::io_service& _io_service; + cql_client_options_t _client_options; + cql_protocol_options_t _protocol_options; + cql_pooling_options_t _pooling_options; + cql_policies_t _policies; + cql_credentials_t _credentials; }; -class cql_initializer_t { +class cql_initializer_t +{ public: virtual const std::list& contact_points() const = 0; - - virtual boost::shared_ptr - configuration() const = 0; + + virtual boost::shared_ptr + configuration() = 0; }; -class cql_builder_t : public cql_initializer_t, boost::noncopyable { +class cql_builder_t : + public cql_initializer_t, + boost::noncopyable +{ public: - static const int DEFAULT_PORT = 9042; - - cql_builder_t() - : _log_callback(0) { } + static const int DEFAULT_PORT = 9042; + + cql_builder_t() : + _log_callback(0) + {} inline virtual const std::list& - contact_points() const { + contact_points() const + { return _contact_points; } - inline virtual boost::shared_ptr - configuration() const { + inline virtual boost::shared_ptr + configuration() + { return boost::shared_ptr( new cql_configuration_t( + _io_service, cql_client_options_t(_log_callback), - cql_protocol_options_t(_contact_points,_ssl_context), + cql_protocol_options_t( + _contact_points, + _ssl_context), cql_pooling_options_t(), cql_policies_t(), _credentials)); } - boost::shared_ptr + boost::shared_ptr build(); - inline cql_builder_t& - with_ssl() { - boost::shared_ptr ssl_context(new boost::asio::ssl::context(boost::asio::ssl::context::sslv23)); + inline cql_builder_t& + with_ssl() + { + boost::shared_ptr ssl_context( + new boost::asio::ssl::context( +#if BOOST_VERSION <= 104800 + _io_service, +#endif + boost::asio::ssl::context::sslv23)); _ssl_context = ssl_context; return *this; } - cql_builder_t& - add_contact_point(const ::boost::asio::ip::address& address); - cql_builder_t& - add_contact_point(const ::boost::asio::ip::address& address, - unsigned short port); - + add_contact_point( + const ::boost::asio::ip::address& address); + cql_builder_t& - add_contact_point(const cql_endpoint_t& endpoint); + add_contact_point( + const ::boost::asio::ip::address& address, + unsigned short port); - cql_builder_t& - add_contact_points(const std::list< ::boost::asio::ip::address>& addresses); + cql_builder_t& + add_contact_point( + const cql_endpoint_t& endpoint); cql_builder_t& - add_contact_points(const std::list< ::boost::asio::ip::address>& addresses, - unsigned short port); - + add_contact_points( + const std::list< ::boost::asio::ip::address>& addresses); + + cql_builder_t& + add_contact_points( + const std::list< ::boost::asio::ip::address>& addresses, + unsigned short port); + cql_builder_t& - add_contact_points(const std::list& endpoints); - - inline cql_builder_t& - with_log_callback(cql::cql_connection_t::cql_log_callback_t log_callback) { + add_contact_points( + const std::list& endpoints); + + inline cql_builder_t& + with_log_callback( + cql::cql_connection_t::cql_log_callback_t log_callback) + { _log_callback = log_callback; return *this; } - + cql_builder_t& - with_credentials(const std::string& user_name, const std::string& password); - + with_credentials( + const std::string& user_name, + const std::string& password); + private: - std::list _contact_points; - boost::shared_ptr _ssl_context; - cql_connection_t::cql_log_callback_t _log_callback; - cql_credentials_t _credentials; + boost::asio::io_service _io_service; + std::list _contact_points; + boost::shared_ptr _ssl_context; + cql_connection_t::cql_log_callback_t _log_callback; + cql_credentials_t _credentials; }; diff --git a/include/cql/cql_cluster.hpp b/include/cql/cql_cluster.hpp index 6248e6836..fc8921f17 100644 --- a/include/cql/cql_cluster.hpp +++ b/include/cql/cql_cluster.hpp @@ -34,25 +34,25 @@ class cql_metadata_t; class cql_cluster_t: boost::noncopyable { public: - static boost::shared_ptr - built_from(const cql_initializer_t& initializer); - - static boost::shared_ptr + static boost::shared_ptr + built_from(cql_initializer_t& initializer); + + static boost::shared_ptr builder(); - virtual boost::shared_ptr + virtual boost::shared_ptr connect() = 0; - - virtual boost::shared_ptr + + virtual boost::shared_ptr connect(const std::string& keyspace) = 0; - - virtual void + + virtual void shutdown(int timeout_ms = -1) = 0; - + // returns MOCK metadata object. virtual boost::shared_ptr metadata() const = 0; - + virtual inline ~cql_cluster_t() { } }; diff --git a/include/cql/cql_connection.hpp b/include/cql/cql_connection.hpp index e322e02d2..ca04e3ea7 100644 --- a/include/cql/cql_connection.hpp +++ b/include/cql/cql_connection.hpp @@ -27,7 +27,9 @@ #include #include +#include #include +#include #include "cql/cql.hpp" #include "cql/cql_future_connection.hpp" @@ -48,58 +50,58 @@ struct cql_error_t; class cql_connection_t : boost::noncopyable { public: - typedef - boost::function + typedef + boost::function cql_log_callback_t; - typedef - boost::function + typedef + boost::function cql_connection_callback_t; - - typedef - boost::function + + typedef + boost::function cql_connection_errback_t; - - typedef - boost::function + + typedef + boost::function cql_event_callback_t; - typedef - boost::function + typedef + boost::function cql_message_callback_t; - - typedef - boost::function + + typedef + boost::function cql_message_errback_t; - typedef - std::map + typedef + std::map cql_credentials_t; virtual ~cql_connection_t() { } - virtual bool + virtual bool is_healthy() const = 0; - - virtual bool + + virtual bool is_busy(int) const = 0; - - virtual bool + + virtual bool is_free(int) const = 0; - + virtual bool is_empty() const = 0; - virtual cql_stream_t + virtual cql_stream_t acquire_stream() = 0; - - virtual void + + virtual void release_stream(cql_stream_t& stream) = 0; virtual cql_uuid_t id() const = 0; - + /** Connect to the server at the specified address and port. @@ -149,8 +151,8 @@ class cql_connection_t : /** Prepare a CQL statement. - When the callback is triggered it will be passed a cql_message_result_t - which contains the ID of the prepared statement. + When the callback is triggered it will be passed a cql_message_result_t + which contains the ID of the prepared statement. This ID is used when composing execution messages. @param query query string. @@ -259,7 +261,7 @@ class cql_connection_t : */ virtual void reconnect() = 0; - + }; } // namespace cql diff --git a/include/cql/cql_endpoint.hpp b/include/cql/cql_endpoint.hpp index 0d9387ea4..e92c77a7a 100644 --- a/include/cql/cql_endpoint.hpp +++ b/include/cql/cql_endpoint.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_endpoint_t.hpp * Author: mc * @@ -13,84 +13,128 @@ #include #include -#include "cql/lockfree/boost_ip_address_traits.hpp" - namespace cql { - - class cql_endpoint_t { + + class cql_endpoint_t + { public: - cql_endpoint_t() - : _address(), _port(0) { } - + cql_endpoint_t() : + _address(), + _port(0) + {} + cql_endpoint_t( const ::boost::asio::ip::address& address, - unsigned short port) - : _address(address), _port(port) { } - + unsigned short port) : + _address(address), _port(port) + {} + inline const ::boost::asio::ip::address& - address() const { return _address; } - + address() const + { + return _address; + } + inline unsigned short - port() const { return _port; } - + port() const + { + return _port; + } + inline boost::asio::ip::tcp::resolver::query - resolver_query() const { + resolver_query() const + { return boost::asio::ip::tcp::resolver::query( _address.to_string(), boost::lexical_cast(_port)); } - + inline std::string - to_string() const { + to_string() const + { return boost::str(boost::format("%1%:%2%") % _address % _port); } - + inline bool - is_unspecified() const { - return _address.is_unspecified(); + is_unspecified() const + { + return (_address == ::boost::asio::ip::address()); } - - friend bool - operator ==(const cql_endpoint_t& left, const cql_endpoint_t& right) { - return (left._port == right._port) + + friend bool + operator ==(const cql_endpoint_t& left, const cql_endpoint_t& right) + { + return (left._port == right._port) && (left._address == right._address); } - + friend bool - operator !=(const cql_endpoint_t& left, const cql_endpoint_t& right) { - return (left._port != right._port) + operator !=(const cql_endpoint_t& left, const cql_endpoint_t& right) + { + return (left._port != right._port) || (left._address != right._address); } - + private: ::boost::asio::ip::address _address; unsigned short _port; }; - + } namespace std { - template<> - struct hash< ::cql::cql_endpoint_t> { - public: - typedef - ::cql::cql_endpoint_t - argument_type; + // template<> + // struct hash { + // public: + // typedef + // ::cql::cql_endpoint_t + // argument_type; - typedef - ::std::size_t - result_type; + // typedef + // ::std::size_t + // result_type; - inline result_type - operator ()(const argument_type& endpoint) const { - return - (1234567u * endpoint.port()) - + _address_hash(endpoint.address()); - } - - private: - std::hash< ::boost::asio::ip::address> _address_hash; - }; + + + // inline result_type + // operator()( + // const argument_type& endpoint) const + // { + // return (1234567u * endpoint.port()) + get_address_hash(endpoint.address()); + // } + + // private: + // inline result_type + // get_address_hash( + // const boost::asio::ip::address& address) const + // { + // if (address.is_v4()) { + // return get_ip_hash(address.to_v4().to_bytes()); + // } + // else { + // return get_ip_hash(address.to_v6().to_bytes()); + // } + // } + + // template + // inline result_type + // get_ip_hash( + // const TBytesType& ip_bytes) const + // { + // // implemented using djb2 algorithm + // // see: http://www.cse.yorku.ca/~oz/hash.html + + // unsigned long hash = 5381; + + // for (typename TBytesType::const_iterator it = ip_bytes.cbegin(); + // it != ip_bytes.cend(); ++it) + // { + // hash = ((hash << 5) + hash) + *it; + // } + + // return static_cast(hash); + // } + // }; template<> struct less< ::cql::cql_endpoint_t> { @@ -109,24 +153,23 @@ namespace std { inline result_type operator ()( - const ::cql::cql_endpoint_t& first, - const ::cql::cql_endpoint_t& second) const + const ::cql::cql_endpoint_t& first, + const ::cql::cql_endpoint_t& second) const { bool is_less = _address_less(first.address(), second.address()); if(is_less) return true; - + bool is_greater = _address_less(second.address(), first.address()); if(is_greater) return false; - + return first.port() < second.port(); } - + private: - std::less< ::boost::asio::ip::address> _address_less; + std::less _address_less; }; } #endif /* CQL_ENDPOINT_HPP_ */ - diff --git a/include/cql/cql_host.hpp b/include/cql/cql_host.hpp index 544916396..8fed53361 100644 --- a/include/cql/cql_host.hpp +++ b/include/cql/cql_host.hpp @@ -16,66 +16,81 @@ namespace cql { class CQL_EXPORT cql_host_t { public: - typedef + typedef boost::asio::ip::address ip_address_t; - inline bool - is_up() const { return _is_up; } - + inline bool + is_up() const + { + return _is_up; + } + inline const ip_address_t& - address() const { return _endpoint.address(); } - - inline unsigned short - port() const { return _endpoint.port(); } - + address() const + { + return _endpoint.address(); + } + + inline unsigned short + port() const + { + return _endpoint.port(); + } + inline const cql_endpoint_t& - endpoint() const { return _endpoint; } - + endpoint() const + { + return _endpoint; + } + inline const std::string& - datacenter() const { return _datacenter; } - + datacenter() const + { + return _datacenter; + } + inline const std::string& - rack() const { return _rack; } - + rack() const + { + return _rack; + } + bool is_considerably_up() const; - + cql_host_distance_enum - distance(const cql_policies_t& policies) const; - + distance( + const cql_policies_t& policies) const; + bool set_down(); - + bool bring_up(); - + void set_location_info( const std::string& datacenter, const std::string& rack); - + static ::boost::shared_ptr create( - const cql_endpoint_t& endpoint, + const cql_endpoint_t& endpoint, const boost::shared_ptr& reconnection_policy); private: cql_host_t( - const cql_endpoint_t& endpoint, + const cql_endpoint_t& endpoint, const boost::shared_ptr& reconnection_policy); - cql_endpoint_t _endpoint; - std::string _datacenter; - std::string _rack; - bool _is_up; - boost::posix_time::ptime _next_up_time; - - boost::shared_ptr - _reconnection_policy; - - boost::shared_ptr - _reconnection_schedule; + cql_endpoint_t _endpoint; + std::string _datacenter; + std::string _rack; + bool _is_up; + boost::posix_time::ptime _next_up_time; + boost::shared_ptr _reconnection_policy; + boost::shared_ptr _reconnection_schedule; }; } -#endif // CQL_HOST_HPP_ \ No newline at end of file +#endif // CQL_HOST_HPP_ diff --git a/include/cql/cql_lockfree_map.hpp b/include/cql/cql_lockfree_map.hpp deleted file mode 100644 index 9a8ea7b66..000000000 --- a/include/cql/cql_lockfree_map.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CQL_LOCKFREE_MAP_HPP_ -#define CQL_LOCKFREE_MAP_HPP_ - -namespace cql { - template - class cql_lockfree_map_t { - public: - // @expected_size - How many items you expect to - // be in map - cql_lockfree_map_t(size_t expected_size); - - // Tries to add specified key with specified value to map. - // If key already exists in map returns false and DOESN'T change - // value. - bool try_insert(const TKey& key, const TValue& value); - - // Tries to get result from dictionary - bool try_get(const TKey& key, TValue& result); - }; -} - -#endif // CQL_LOCKFREE_MAP_HPP_ \ No newline at end of file diff --git a/include/cql/cql_metadata.hpp b/include/cql/cql_metadata.hpp index 11ab44ed0..5ca7f0f42 100644 --- a/include/cql/cql_metadata.hpp +++ b/include/cql/cql_metadata.hpp @@ -37,7 +37,7 @@ namespace cql { }; class cql_schema_changed_info_t { - public: + public: enum schema_change_type_enum { SCHEMA_CHANGE_TYPE_CREATED, SCHEMA_CHANGE_TYPE_DROPPED, @@ -59,7 +59,7 @@ namespace cql { const std::string& keyspace, const std::string& table) : _change_type(change_type), - _keyspace(keyspace), + _keyspace(keyspace), _table(table) { } @@ -70,11 +70,11 @@ namespace cql { // CURRENTLY THIS IS MOCK THAT IS USED ONLY IN POLICIES // TO POPULATE HOSTS COLLECTIONS. - + class cql_cluster_impl_t; class cql_host_t; class cql_hosts_t; - + class cql_metadata_t: boost::noncopyable { public: // TODO: Provide notifications for events @@ -82,62 +82,62 @@ namespace cql { // boost::signals2::signal // on_host_state_changed_t; // -// inline void +// inline void // on_host_state_changed(const on_host_state_changed_t::slot_type& slot) { //// _host_state_changed.connect(slot); // } -// +// // typedef // boost::signals2::signal // on_schema_changed_t; // -// inline void +// inline void // on_schema_changed(const on_schema_changed_t::slot_type& slot) { //// _schema_changed.connect(slot); // } -// - +// + // Puts all known hosts at the end of @collection. void - get_hosts(std::vector >& collection) const; - + get_hosts(std::vector >& collection) const; + boost::shared_ptr get_host(const cql_endpoint_t& endpoint) const; - + // Puts host addresses at the end of @collection void - get_endpoints(std::vector* collection) const; - + get_endpoints(std::vector& collection) const; + friend class cql_control_connection_t; private: - + boost::shared_ptr add_host(const cql_endpoint_t& endpoint); - + void add_hosts(const std::list& endpoints); - + void remove_host(const cql_endpoint_t& endpoint); - + void set_down_host(const cql_endpoint_t& endpoint); - + void bring_up_host(const cql_endpoint_t& endpoint); - + private: cql_metadata_t( boost::shared_ptr reconnection_policy); - + friend class cql_cluster_impl_t; - + //on_host_state_changed_t _host_state_changed; //on_schema_changed_t _schema_changed; - + boost::shared_ptr _reconnection_policy; boost::shared_ptr _hosts; }; } -#endif // CQL_METADATA_H_ \ No newline at end of file +#endif // CQL_METADATA_H_ diff --git a/include/cql/cql_query.hpp b/include/cql/cql_query.hpp index c2d9faa06..145fbe984 100644 --- a/include/cql/cql_query.hpp +++ b/include/cql/cql_query.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_query.hpp * Author: mc * @@ -15,76 +15,131 @@ #include "cql/cql_stream.hpp" namespace cql { - + class cql_query_t { public: - cql_query_t(const std::string& query_string) - : _query_string(query_string) - , _consistency(CQL_CONSISTENCY_DEFAULT) - , _is_traced(false) - , _retry_policy() { } - - cql_query_t(const std::string& query_string, - const cql_consistency_enum consistency, - const bool is_traced = false, - const boost::shared_ptr retry_policy = 0) - : _query_string(query_string) - , _consistency(consistency) - , _is_traced(is_traced) - , _retry_policy(retry_policy) { } - + cql_query_t( + const std::string& query_string) : + _query_string(query_string), + _consistency(CQL_CONSISTENCY_DEFAULT), + _is_traced(false), + _retry_policy() + {} + + cql_query_t( + const std::string& query_string, + const cql_consistency_enum consistency) : + _query_string(query_string), + _consistency(consistency), + _is_traced(false), + _retry_policy() + {} + + cql_query_t( + const std::string& query_string, + const cql_consistency_enum consistency, + const bool is_traced) : + _query_string(query_string), + _consistency(consistency), + _is_traced(is_traced), + _retry_policy() + {} + + cql_query_t( + const std::string& query_string, + const cql_consistency_enum consistency, + const bool is_traced, + const boost::shared_ptr retry_policy) : + _query_string(query_string), + _consistency(consistency), + _is_traced(is_traced), + _retry_policy(retry_policy) + {} + inline bool - is_traced() const { return _is_traced; } - + is_traced() const + { + return _is_traced; + } + inline void - enable_tracing() { _is_traced = true; } - + enable_tracing() + { + _is_traced = true; + } + inline void - disable_tracing() { _is_traced = false; } - + disable_tracing() + { + _is_traced = false; + } + inline cql_consistency_enum - consistency() const { return _consistency; } + consistency() const + { + return _consistency; + } inline void - set_consistency(const cql_consistency_enum consistency) { + set_consistency( + const cql_consistency_enum consistency) + { _consistency = consistency; } - + inline boost::shared_ptr - retry_policy() const { return _retry_policy; } - + retry_policy() const + { + return _retry_policy; + } + inline void - set_retry_policy(const boost::shared_ptr& retry_policy) { + set_retry_policy( + const boost::shared_ptr& retry_policy) + { _retry_policy = retry_policy; } - + inline bool - has_retry_policy() const { return (bool)_retry_policy; } + has_retry_policy() const { + return (bool)_retry_policy; + } inline const cql_stream_t& - stream() const { return _stream; } - + stream() const + { + return _stream; + } + inline void - set_stream(const cql_stream_t& stream) { + set_stream( + const cql_stream_t& stream) + { _stream = stream; } inline const std::string& - query() const { return _query_string; } + query() const + { + return _query_string; + } inline void - set_query(const std::string& query_string) { _query_string = query_string; } + set_query( + const std::string& query_string) + { + _query_string = query_string; + } private: - std::string _query_string; - cql_consistency_enum _consistency; - bool _is_traced; - boost::shared_ptr _retry_policy; - cql_stream_t _stream; + std::string _query_string; + cql_consistency_enum _consistency; + bool _is_traced; + boost::shared_ptr _retry_policy; + cql_stream_t _stream; }; } #endif /* CQL_QUERY_HPP */ - diff --git a/include/cql/cql_reconnection_schedule.hpp b/include/cql/cql_reconnection_schedule.hpp index e3c61460c..747fd53a1 100644 --- a/include/cql/cql_reconnection_schedule.hpp +++ b/include/cql/cql_reconnection_schedule.hpp @@ -15,14 +15,14 @@ namespace cql { // the host is detected down to schedule the first reconnection attempt, and // then once after each failed reconnection attempt to schedule the next one. // Hence each call to this method are free to return a different value. - // + // // @returns a time in milliseconds to wait before attempting the next reconnection. virtual boost::posix_time::time_duration get_delay() = 0; - virtual + virtual ~cql_reconnection_schedule_t() { } }; } -#endif // CQL_RECONNECTION_SCHEDULT_HPP_ \ No newline at end of file +#endif // CQL_RECONNECTION_SCHEDULT_HPP_ diff --git a/include/cql/cql_stream.hpp b/include/cql/cql_stream.hpp index 7ce8616b8..ad58ecf8f 100644 --- a/include/cql/cql_stream.hpp +++ b/include/cql/cql_stream.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_stream.hpp * Author: mc * @@ -11,37 +11,37 @@ #include "cql/cql.hpp" namespace cql { - -// class represents virtual stream inside + +// class represents virtual stream inside // single connection. class cql_stream_t { static const int INVALID_STREAM_ID = -1; - + public: cql_stream_t() : _stream_id(INVALID_STREAM_ID) { } - + bool is_invalid() const { return (_stream_id == INVALID_STREAM_ID); } - + cql_stream_id_t stream_id() const { return _stream_id; } private: cql_stream_t(cql_stream_id_t stream_id) : _stream_id(stream_id) { } - + static cql_stream_t from_stream_id(const cql_stream_id_t& stream_id); - + static const cql_stream_t& invalid_stream(); - + cql_stream_id_t _stream_id; - template + template friend class cql_callback_storage_t; - + friend class cql_header_impl_t; }; @@ -49,4 +49,3 @@ class cql_stream_t { #endif /* CQL_STREAM_HPP */ - diff --git a/include/cql/cql_uuid.hpp b/include/cql/cql_uuid.hpp index 7d3476811..5545628e3 100644 --- a/include/cql/cql_uuid.hpp +++ b/include/cql/cql_uuid.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_uuid_t.hpp * Author: mc * @@ -15,57 +15,56 @@ namespace cql { } namespace std { - template<> - struct hash; + // template<> + // struct hash; } namespace cql { - + class cql_uuid_t { public: // TODO: This is currently implemented as simple long // but soon we switch to official UUID implementation // as described here: // http://www.ietf.org/rfc/rfc4122.txt - + static cql_uuid_t create(); - + friend bool operator <(const cql_uuid_t& left, const cql_uuid_t& right); - + private: cql_uuid_t(unsigned long uuid): _uuid(uuid) { } - + unsigned long _uuid; - - friend class std::hash; + + // friend struct std::hash; }; } -namespace std { +// namespace std { - template<> - struct hash { - public: - typedef - cql::cql_uuid_t - argument_type; - - typedef - size_t - result_type; - - size_t - operator ()(const cql::cql_uuid_t& id) const { - return - ((id._uuid * 3169) << 16) + - ((id._uuid * 23) << 8) + - id._uuid; - } - }; -} +// template<> +// struct hash { +// public: +// typedef +// cql::cql_uuid_t +// argument_type; -#endif /* CQL_UUID_HPP_ */ +// typedef +// size_t +// result_type; +// size_t +// operator ()(const cql::cql_uuid_t& id) const { +// return +// ((id._uuid * 3169) << 16) + +// ((id._uuid * 23) << 8) + +// id._uuid; +// } +// }; +// } + +#endif /* CQL_UUID_HPP_ */ diff --git a/include/cql/exceptions/cql_write_timeout_exception.hpp b/include/cql/exceptions/cql_write_timeout_exception.hpp index 7fd0260b7..7b67e9e64 100644 --- a/include/cql/exceptions/cql_write_timeout_exception.hpp +++ b/include/cql/exceptions/cql_write_timeout_exception.hpp @@ -14,35 +14,36 @@ namespace cql { // A Cassandra timeout during a write query. -class CQL_EXPORT cql_write_timeout_exception: public cql_query_timeout_exception { +class CQL_EXPORT cql_write_timeout_exception : + public cql_query_timeout_exception +{ public: - cql_write_timeout_exception( - cql_consistency_enum consistency_level, - cql_int_t received, - cql_int_t required, - const char* write_type) - - : cql_query_timeout_exception( + cql_write_timeout_exception( + cql_consistency_enum consistency_level, + cql_int_t received, + cql_int_t required, + const char* write_type) : + cql_query_timeout_exception( create_message(consistency_level, received, required), - consistency_level, - received, + consistency_level, + received, required), - _write_type(write_type) - { } - - + _write_type(write_type) + {} + + inline const char* write_type() const { return _write_type; } - + private: - std::string + std::string create_message( cql_consistency_enum consistency_level, cql_int_t received, cql_int_t required); - + const char* _write_type; }; } diff --git a/include/cql/internal/cql_callback_storage.hpp b/include/cql/internal/cql_callback_storage.hpp index ffec4f614..cfa59e232 100644 --- a/include/cql/internal/cql_callback_storage.hpp +++ b/include/cql/internal/cql_callback_storage.hpp @@ -2,123 +2,135 @@ #define CQL_CALLBACK_STORAGE_HPP_ #include -#include -#include +#include +#include #include "cql/cql.hpp" #include "cql/cql_stream.hpp" namespace cql { - -// TType - type of array items, + +// TType - type of array items, // must have default constructor. -// Size - size of the array, should not exceed 4096 -// for performance reasons. -template -class cql_callback_storage_t { +template +class cql_callback_storage_t +{ public: - cql_callback_storage_t() - : _free_indexes(Size) + cql_callback_storage_t( + size_t size) : + _contents(size), + _is_used(size, false), + _free_indexes() { -#ifdef _WIN32 - for(int index =0;index lock(_locks[index]); + + return _contents[index]; } void set_callbacks( - const cql_stream_t& stream, - const TType& value) + const cql_stream_t& stream, + const TType& value) { - if(stream.is_invalid()) + boost::mutex::scoped_lock lock(_mutex); + if (stream.is_invalid()) { throw std::invalid_argument("index is invalid."); + } long index = stream.stream_id(); check_boundaries(index); - - boost::lock_guard lock(_locks[index]); _contents[index] = value; } private: void - check_boundaries(const long index) const { - if(index < 0 || (unsigned)index >= Size) + check_boundaries( + const long index) const + { + if (index < 0 || (unsigned) index >= _is_used.size()) { throw std::out_of_range("stream id is out of range."); + } } - - void - populate_free_indexes() { - for(size_t index = 0; index < Size; index++) - _free_indexes.unsynchronized_push(index); - } - TType _contents[Size]; - boost::atomic_bool _is_used[Size]; - boost::detail::spinlock _locks[Size]; - boost::lockfree::stack _free_indexes; + boost::mutex _mutex; + std::vector _contents; + std::vector _is_used; + std::stack _free_indexes; }; } -#endif // CQL_CALLBACK_STORAGE_HPP_ \ No newline at end of file +#endif // CQL_CALLBACK_STORAGE_HPP_ diff --git a/include/cql/internal/cql_cluster_impl.hpp b/include/cql/internal/cql_cluster_impl.hpp index c38d1ed00..553c559b8 100644 --- a/include/cql/internal/cql_cluster_impl.hpp +++ b/include/cql/internal/cql_cluster_impl.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_cluster_impl.hpp * Author: mc * @@ -9,46 +9,51 @@ #define CQL_CLUSTER_IMPL_HPP_ #include +#include -#include "cql/cql_connection_factory.hpp" -#include "cql/cql_connection.hpp" -#include "cql/cql_session.hpp" -#include "cql/internal/cql_session_impl.hpp" -#include "cql/internal/cql_control_connection.hpp" #include "cql/cql_builder.hpp" +#include "cql/cql_connection.hpp" +#include "cql/cql_connection_factory.hpp" #include "cql/cql_metadata.hpp" -#include "cql/lockfree/cql_lockfree_hash_map.hpp" +#include "cql/cql_session.hpp" #include "cql/cql_uuid.hpp" +#include "cql/internal/cql_control_connection.hpp" +#include "cql/internal/cql_session_impl.hpp" + namespace cql { // This is a non-SSL client factory -struct client_functor_t { +struct client_functor_t +{ public: - - client_functor_t(boost::asio::io_service& service, - cql::cql_connection_t::cql_log_callback_t log_callback) : + + client_functor_t( + boost::asio::io_service& service, + cql::cql_connection_t::cql_log_callback_t log_callback) : _io_service(service), _log_callback(log_callback) {} inline boost::shared_ptr - operator()() { + operator()() + { // called every time the pool needs to initiate a new connection to a host return cql::cql_connection_factory_t::create_connection(_io_service, _log_callback); } private: - boost::asio::io_service& _io_service; + boost::asio::io_service& _io_service; cql::cql_connection_t::cql_log_callback_t _log_callback; }; // This is an SSL client factory -struct client_ssl_functor_t { -public: +struct client_ssl_functor_t +{ + public: - client_ssl_functor_t(boost::asio::io_service& service, - boost::asio::ssl::context& context, + client_ssl_functor_t(boost::asio::io_service& service, + boost::asio::ssl::context& context, cql::cql_connection_t::cql_log_callback_t log_callback) : _io_service(service), _ssl_ctx(context), @@ -56,82 +61,89 @@ struct client_ssl_functor_t { {} inline boost::shared_ptr - operator()() { + operator()() + { // called every time the pool needs to initiate a new connection to a host return cql::cql_connection_factory_t::create_connection(_io_service, _ssl_ctx, _log_callback); } private: - boost::asio::io_service& _io_service; - boost::asio::ssl::context& _ssl_ctx; + boost::asio::io_service& _io_service; + boost::asio::ssl::context& _ssl_ctx; cql::cql_connection_t::cql_log_callback_t _log_callback; }; -class cql_cluster_impl_t: public cql_cluster_t { +class cql_cluster_impl_t : + public cql_cluster_t +{ private: // Main function of thread on which we call io_service::run static void - asio_thread_main(boost::asio::io_service* io_service) { - cql::cql_thread_infrastructure_t gc; + asio_thread_main( + boost::asio::io_service* io_service) + { io_service->run(); - cds::gc::HP::force_dispose(); } - + public: cql_cluster_impl_t( - const std::list& endpoints, - boost::shared_ptr configuration) - : _contact_points(endpoints) - , _configuration(configuration) - , work(new boost::asio::io_service::work(_io_service)) - , thread(boost::bind(&cql_cluster_impl_t::asio_thread_main, &_io_service)) + const std::list& endpoints, + boost::shared_ptr configuration) : + _io_service(configuration->io_service()), + _contact_points(endpoints), + _configuration(configuration), + _work(new boost::asio::io_service::work(configuration->io_service())), + _thread(boost::bind(&cql_cluster_impl_t::asio_thread_main, &configuration->io_service())) { - _configuration->init(this); - const cql_policies_t& policies = _configuration->policies(); - - _metadata = boost::shared_ptr(new cql_metadata_t( - policies.reconnection_policy() - )); - - _metadata->add_hosts(endpoints); - - _control_connection = boost::shared_ptr( - new cql_control_connection_t( - *this, - _io_service, - configuration + _configuration->init(this); + const cql_policies_t& policies = _configuration->policies(); + + _metadata = boost::shared_ptr(new cql_metadata_t(policies.reconnection_policy())); + + _metadata->add_hosts(endpoints); + + _control_connection = boost::shared_ptr( + new cql_control_connection_t( + *this, + _io_service, + configuration )); } - - virtual - ~cql_cluster_impl_t() { } - + + virtual + ~cql_cluster_impl_t() + {} + virtual boost::shared_ptr - connect() { + connect() + { return connect(""); } - - virtual boost::shared_ptr - connect(const std::string& keyspace) { + + virtual boost::shared_ptr + connect( + const std::string& keyspace) + { // decide which client factory we want, SSL or non-SSL. This is a hack, if you pass any commandline arg to the // binary it will use the SSL factory, non-SSL by default cql::cql_session_t::cql_client_callback_t client_factory; - boost::asio::ssl::context* ssl_context = + boost::asio::ssl::context* ssl_context = _configuration->protocol_options() .ssl_context() .get(); - - cql::cql_connection_t::cql_log_callback_t log_callback = + + cql::cql_connection_t::cql_log_callback_t log_callback = _configuration->client_options() .log_callback(); if (ssl_context != 0) { client_factory = client_ssl_functor_t( - _io_service, - const_cast(*ssl_context), + _io_service, + const_cast(*ssl_context), log_callback); - } else { + } + else { client_factory = client_functor_t(_io_service, log_callback); } @@ -139,60 +151,53 @@ class cql_cluster_impl_t: public cql_cluster_t { cql_session_callback_info_t session_callbacks; session_callbacks.set_client_callback(client_factory); session_callbacks.set_log_callback(log_callback); - + boost::shared_ptr session( new cql_session_impl_t(session_callbacks, _configuration)); session->init(_io_service); _control_connection->init(); - - // HACK: Comment this out to get libcds gc bug - // bool session_add = _connected_sessions.try_add(session->id(), session); - // assert(session_add); - + return session; } - virtual void + virtual void shutdown(int timeout_ms) { close_sessions(); _control_connection->shutdown(); - - if(work.get()!=NULL) { - work.reset(); - thread.join(); + + if (_work.get() != NULL) { + _work.reset(); + _thread.join(); } } - - virtual boost::shared_ptr + + virtual boost::shared_ptr metadata() const { return _metadata; } - + friend class cql_metadata_t; - + private: - - typedef - cql_lockfree_hash_map_t > - connected_sessions_t; - + + typedef std::map > connected_sessions_t; + void - close_sessions() { - for(connected_sessions_t::iterator it = _connected_sessions.begin(); - it != _connected_sessions.end(); ++it) + close_sessions() + { + boost::mutex::scoped_lock lock(_mutex); + for (connected_sessions_t::iterator it = _connected_sessions.begin(); + it != _connected_sessions.end(); ++it) { - boost::shared_ptr session; - if(_connected_sessions.try_erase(it->first, &session)) - session->close(); + it->second->close(); + _connected_sessions.erase(it); } } - - const std::list _contact_points; - boost::shared_ptr _configuration; - // Initialize the IO service, this allows us to perform network operations asyncronously - boost::asio::io_service _io_service; + boost::asio::io_service& _io_service; + const std::list _contact_points; + boost::shared_ptr _configuration; // Typically async operations are performed in the thread performing the request, because we want synchronous behavior // we're going to spawn a thread whose sole purpose is to perform network communication, and we'll use this thread to @@ -200,16 +205,14 @@ class cql_cluster_impl_t: public cql_cluster_t { // // Also, typically the boost::asio::io_service::run will exit as soon as it's work is done, which we want to prevent // because it's in it's own thread. Using boost::asio::io_service::work prevents the thread from exiting. - boost::scoped_ptr work; - boost::thread thread; - - boost::shared_ptr _metadata; - connected_sessions_t _connected_sessions; - - boost::shared_ptr _control_connection; + boost::mutex _mutex; + boost::scoped_ptr _work; + boost::thread _thread; + boost::shared_ptr _metadata; + connected_sessions_t _connected_sessions; + boost::shared_ptr _control_connection; }; } #endif /* CQL_CLUSTER_IMPL_HPP_ */ - diff --git a/include/cql/internal/cql_connection_impl.hpp b/include/cql/internal/cql_connection_impl.hpp index 648ab6e6e..5d75017c4 100644 --- a/include/cql/internal/cql_connection_impl.hpp +++ b/include/cql/internal/cql_connection_impl.hpp @@ -40,14 +40,12 @@ #include #include #include -#include #include +#include #include +#include #include -#include -#include -#include - +#include #include "cql/cql.hpp" #include "cql/cql_connection.hpp" @@ -86,22 +84,22 @@ class cql_connection_impl_t : public cql::cql_connection_t // stream with is 0 is dedicated to events messages and // connection management. static const int NUMBER_OF_USER_STREAMS = 127; - + public: - typedef - std::list + typedef + std::list request_buffer_t; - - typedef - std::pair + + typedef + std::pair callback_pair_t; - - typedef - cql::cql_callback_storage_t + + typedef + cql::cql_callback_storage_t callback_storage_t; - - typedef - boost::function + + typedef + boost::function write_callback_t; cql_connection_impl_t( @@ -111,8 +109,8 @@ class cql_connection_impl_t : public cql::cql_connection_t _resolver(io_service), _transport(transport), _request_buffer(0), - _callback_storage(), - _numer_of_free_stream_ids(NUMBER_OF_USER_STREAMS), + _callback_storage(NUMBER_OF_STREAMS), + _number_of_free_stream_ids(NUMBER_OF_USER_STREAMS), _connect_callback(0), _connect_errback(0), _log_callback(log_callback), @@ -123,41 +121,47 @@ class cql_connection_impl_t : public cql::cql_connection_t _closing(false), _reserved_stream(_callback_storage.acquire_stream()), _uuid(cql_uuid_t::create()) - { } + {} boost::shared_future - connect(const cql_endpoint_t& endpoint) + connect(const cql_endpoint_t& endpoint) { boost::shared_ptr > promise( - new cql_promise_t()); + new cql_promise_t()); - connect(endpoint, - boost::bind(&cql_connection_impl_t::_connection_future_callback, this, promise, ::_1), - boost::bind(&cql_connection_impl_t::_connection_future_errback, this, promise, ::_1, ::_2)); + connect( + endpoint, + boost::bind(&cql_connection_impl_t::_connection_future_callback, this, promise, ::_1), + boost::bind(&cql_connection_impl_t::_connection_future_errback, this, promise, ::_1, ::_2)); return promise->shared_future(); } void - connect(const cql_endpoint_t& endpoint, - cql_connection_callback_t callback, - cql_connection_errback_t errback) + connect( + const cql_endpoint_t& endpoint, + cql_connection_callback_t callback, + cql_connection_errback_t errback) { _endpoint = endpoint; _connect_callback = callback; _connect_errback = errback; resolve(); } - + virtual cql_uuid_t - id() const { return _uuid; } + id() const + { + return _uuid; + } boost::shared_future - query(const boost::shared_ptr& query_) + query( + const boost::shared_ptr& query_) { boost::shared_ptr > promise( new cql_promise_t()); - + query(query_, boost::bind(&cql_connection_impl_t::_statement_future_callback, this, promise, ::_1, ::_2, ::_3), boost::bind(&cql_connection_impl_t::_statement_future_errback, this, promise, ::_1, ::_2, ::_3)); @@ -166,11 +170,12 @@ class cql_connection_impl_t : public cql::cql_connection_t } boost::shared_future - prepare(const boost::shared_ptr& query) + prepare( + const boost::shared_ptr& query) { boost::shared_ptr > promise( new cql_promise_t()); - + prepare(query, boost::bind(&cql_connection_impl_t::_statement_future_callback, this, promise, ::_1, ::_2, ::_3), boost::bind(&cql_connection_impl_t::_statement_future_errback, this, promise, ::_1, ::_2, ::_3)); @@ -179,11 +184,12 @@ class cql_connection_impl_t : public cql::cql_connection_t } boost::shared_future - execute(const boost::shared_ptr& message) + execute( + const boost::shared_ptr& message) { boost::shared_ptr > promise( new cql_promise_t()); - + execute(message, boost::bind(&cql_connection_impl_t::_statement_future_callback, this, promise, ::_1, ::_2, ::_3), boost::bind(&cql_connection_impl_t::_statement_future_errback, this, promise, ::_1, ::_2, ::_3)); @@ -192,13 +198,14 @@ class cql_connection_impl_t : public cql::cql_connection_t } cql::cql_stream_t - query(const boost::shared_ptr& query, - cql::cql_connection_t::cql_message_callback_t callback, - cql::cql_connection_t::cql_message_errback_t errback) + query( + const boost::shared_ptr& query, + cql::cql_connection_t::cql_message_callback_t callback, + cql::cql_connection_t::cql_message_errback_t errback) { cql_stream_t stream = query->stream(); - - if(stream.is_invalid()) { + + if (stream.is_invalid()) { errback(*this, stream, create_stream_id_error()); return stream; } @@ -216,106 +223,124 @@ class cql_connection_impl_t : public cql::cql_connection_t } cql::cql_stream_t - prepare(const boost::shared_ptr& query, - cql::cql_connection_t::cql_message_callback_t callback, - cql::cql_connection_t::cql_message_errback_t errback) + prepare( + const boost::shared_ptr& query, + cql::cql_connection_t::cql_message_callback_t callback, + cql::cql_connection_t::cql_message_errback_t errback) { cql_stream_t stream = query->stream(); - - if(stream.is_invalid()) { + + if (stream.is_invalid()) { errback(*this, stream, create_stream_id_error()); return stream; } _callback_storage.set_callbacks(stream, callback_pair_t(callback, errback)); - - create_request(new cql::cql_message_prepare_impl_t(query), - boost::bind(&cql_connection_impl_t::write_handle, - this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred), - stream); + + create_request( + new cql::cql_message_prepare_impl_t(query), + boost::bind(&cql_connection_impl_t::write_handle, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred), + stream); return stream; } cql::cql_stream_t - execute(const boost::shared_ptr& message, - cql::cql_connection_t::cql_message_callback_t callback, - cql::cql_connection_t::cql_message_errback_t errback) { + execute( + const boost::shared_ptr& message, + cql::cql_connection_t::cql_message_callback_t callback, + cql::cql_connection_t::cql_message_errback_t errback) + { cql_stream_t stream = acquire_stream(); assert(0); // TODO: change this method to use new stream allocation mechanism - if(stream.is_invalid()) { + if (stream.is_invalid()) { errback(*this, stream, create_stream_id_error()); return stream; } - + _callback_storage.set_callbacks(stream, callback_pair_t(callback, errback)); - create_request(message->impl(), - boost::bind(&cql_connection_impl_t::write_handle, - this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred), - stream); + create_request( + message->impl(), + boost::bind(&cql_connection_impl_t::write_handle, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred), + stream); return stream; } bool - defunct() const { + defunct() const + { return _defunct; } bool - ready() const { + ready() const + { return _ready; } void - close() { + close() + { _closing = true; log(CQL_LOG_INFO, "closing connection"); - + boost::system::error_code ec; _transport->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); _transport->lowest_layer().close(); } virtual const cql_endpoint_t& - endpoint() const { return _endpoint; } + endpoint() const + { + return _endpoint; + } void set_events( cql::cql_connection_t::cql_event_callback_t event_callback, - const std::list& events) { + const std::list& events) + { _event_callback = event_callback; _events = events; } const std::list& - events() const { + events() const + { return _events; } cql::cql_connection_t::cql_event_callback_t - event_callback() const { + event_callback() const + { return _event_callback; } const cql_credentials_t& - credentials() const { + credentials() const + { return _credentials; } void - set_credentials(const cql_connection_t::cql_credentials_t& credentials) { + set_credentials( + const cql_connection_t::cql_credentials_t& credentials) + { _credentials = credentials; } void - reconnect() { + reconnect() + { _closing = false; _events_registered = false; _ready = false; @@ -325,7 +350,8 @@ class cql_connection_impl_t : public cql::cql_connection_t private: inline cql::cql_error_t - create_stream_id_error() { + create_stream_id_error() + { cql::cql_error_t error; error.library = true; error.message = "Too many streams. The maximum value of parallel requests is 127 (1 is reserved by this library)"; @@ -333,8 +359,10 @@ class cql_connection_impl_t : public cql::cql_connection_t } inline void - log(cql::cql_short_t level, - const std::string& message) { + log( + cql::cql_short_t level, + const std::string& message) + { if (_log_callback) { _log_callback(level, message); } @@ -343,7 +371,7 @@ class cql_connection_impl_t : public cql::cql_connection_t void _connection_future_callback( boost::shared_ptr > promise, - cql_connection_t&) + cql_connection_t&) { promise->set_value(cql::cql_future_connection_t(this)); } @@ -352,7 +380,7 @@ class cql_connection_impl_t : public cql::cql_connection_t _connection_future_errback( boost::shared_ptr > promise, cql_connection_t&, - const cql_error_t& error) + const cql_error_t& error) { promise->set_value(cql::cql_future_connection_t(this, error)); } @@ -362,7 +390,7 @@ class cql_connection_impl_t : public cql::cql_connection_t boost::shared_ptr > promise, cql_connection_t&, const cql::cql_stream_t& stream, - cql::cql_result_t* result_ptr) + cql::cql_result_t* result_ptr) { promise->set_value(cql::cql_future_result_t(this, stream, result_ptr)); } @@ -372,68 +400,82 @@ class cql_connection_impl_t : public cql::cql_connection_t boost::shared_ptr > promise, cql_connection_t&, const cql::cql_stream_t& stream, - const cql_error_t& error) + const cql_error_t& error) { promise->set_value(cql::cql_future_result_t(this, stream, error)); } void - resolve() { + resolve() + { log(CQL_LOG_DEBUG, "resolving remote host: " + _endpoint.to_string()); - - _resolver.async_resolve(_endpoint.resolver_query(), - boost::bind(&cql_connection_impl_t::resolve_handle, - this, - boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); + + _resolver.async_resolve( + _endpoint.resolver_query(), + boost::bind(&cql_connection_impl_t::resolve_handle, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::iterator)); } void - resolve_handle(const boost::system::error_code& err, - boost::asio::ip::tcp::resolver::iterator endpoint_iterator) { + resolve_handle( + const boost::system::error_code& err, + boost::asio::ip::tcp::resolver::iterator endpoint_iterator) + { if (!err) { log(CQL_LOG_DEBUG, "resolved remote host, attempting to connect"); #if BOOST_VERSION >= 104800 - boost::asio::async_connect(_transport->lowest_layer(), - endpoint_iterator, - boost::bind(&cql_connection_impl_t::connect_handle, - this, - boost::asio::placeholders::error)); + boost::asio::async_connect( + _transport->lowest_layer(), + endpoint_iterator, + boost::bind(&cql_connection_impl_t::connect_handle, + this, + boost::asio::placeholders::error)); #else - _transport->lowest_layer().async_connect(*endpoint_iterator, - boost::bind(&cql_connection_impl_t::connect_handle, - this, - boost::asio::placeholders::error)); + _transport->lowest_layer().async_connect( + *endpoint_iterator, + boost::bind(&cql_connection_impl_t::connect_handle, + this, + boost::asio::placeholders::error)); #endif - } else { + } + else { log(CQL_LOG_CRITICAL, "error resolving remote host " + err.message()); check_transport_err(err); } } void - connect_handle(const boost::system::error_code& err) { + connect_handle( + const boost::system::error_code& err) + { if (!err) { log(CQL_LOG_DEBUG, "connection successful to remote host"); if (_transport->requires_handshake()) { - _transport->async_handshake(boost::bind(&cql_connection_impl_t::handshake_handle, - this, - boost::asio::placeholders::error)); - } else { + _transport->async_handshake( + boost::bind(&cql_connection_impl_t::handshake_handle, + this, + boost::asio::placeholders::error)); + } + else { options_write(); } - } else { + } + else { log(CQL_LOG_CRITICAL, "error connecting to remote host " + err.message()); check_transport_err(err); } } void - handshake_handle(const boost::system::error_code& err) { + handshake_handle( + const boost::system::error_code& err) { if (!err) { log(CQL_LOG_DEBUG, "successful ssl handshake with remote host"); options_write(); - } else { + } + else { log(CQL_LOG_CRITICAL, "error performing ssl handshake " + err.message()); check_transport_err(err); } @@ -441,41 +483,48 @@ class cql_connection_impl_t : public cql::cql_connection_t // if stream cannot be acquired returns invalid stream virtual cql::cql_stream_t - acquire_stream() { + acquire_stream() + { cql_stream_t stream = _callback_storage.acquire_stream(); return stream; } - + // releases stream, parameter will be set to invalid stream. virtual void - release_stream(cql_stream_t& stream) { + release_stream(cql_stream_t& stream) + { _callback_storage.release_stream(stream); } - - virtual bool - is_healthy() const { + + virtual bool + is_healthy() const + { return true; } - virtual bool - is_busy(int max) const { - return (NUMBER_OF_STREAMS - _numer_of_free_stream_ids.load(boost::memory_order_acquire)) >= max; + virtual bool + is_busy(int max) const + { + return (NUMBER_OF_STREAMS - _number_of_free_stream_ids) >= max; } - - virtual bool - is_free(int min) const { - return (NUMBER_OF_STREAMS - _numer_of_free_stream_ids.load(boost::memory_order_acquire)) <= min; + + virtual bool + is_free(int min) const + { + return (NUMBER_OF_STREAMS - _number_of_free_stream_ids) <= min; } - + virtual bool - is_empty() const { - return (NUMBER_OF_USER_STREAMS == _numer_of_free_stream_ids.load(boost::memory_order_acquire)); + is_empty() const + { + return (NUMBER_OF_USER_STREAMS == _number_of_free_stream_ids); } void - create_request(cql::cql_message_t* message, - write_callback_t callback, - cql_stream_t& stream) + create_request( + cql::cql_message_t* message, + write_callback_t callback, + cql_stream_t& stream) { cql::cql_error_t err; message->prepare(&err); @@ -490,23 +539,26 @@ class cql_connection_impl_t : public cql::cql_connection_t log(CQL_LOG_DEBUG, "sending message: " + header.str() + " " + message->str()); std::vector buf; - + buf.push_back(boost::asio::buffer(header.buffer()->data(), header.size())); _request_buffer.push_back(header.buffer()); - + if (header.length() != 0) { buf.push_back(boost::asio::buffer(message->buffer()->data(), message->size())); _request_buffer.push_back(message->buffer()); - } else { + } + else { _request_buffer.push_back(cql_message_buffer_t()); } - + boost::asio::async_write(*_transport, buf, callback); } void - write_handle(const boost::system::error_code& err, - std::size_t num_bytes) { + write_handle( + const boost::system::error_code& err, + std::size_t num_bytes) + { if (!_request_buffer.empty()) { // the write request is complete free the request buffers _request_buffer.pop_front(); @@ -514,16 +566,19 @@ class cql_connection_impl_t : public cql::cql_connection_t _request_buffer.pop_front(); } } + if (!err) { log(CQL_LOG_DEBUG, "wrote to socket " + boost::lexical_cast(num_bytes) + " bytes"); - } else { + } + else { log(CQL_LOG_ERROR, "error writing to socket " + err.message()); check_transport_err(err); } } void - header_read() { + header_read() + { boost::asio::async_read(*_transport, boost::asio::buffer(_response_header.buffer()->data(), _response_header.size()), #if BOOST_VERSION >= 104800 @@ -535,17 +590,20 @@ class cql_connection_impl_t : public cql::cql_connection_t } void - header_read_handle(const boost::system::error_code& err) { + header_read_handle( + const boost::system::error_code& err) + { if (!err) { cql::cql_error_t decode_err; if (_response_header.consume(&decode_err)) { log(CQL_LOG_DEBUG, "received header for message " + _response_header.str()); body_read(_response_header); - } else { + } + else { log(CQL_LOG_ERROR, "error decoding header " + _response_header.str()); } - } - else if(err.value() == boost::system::errc::operation_canceled) { + } + else if (err.value() == boost::system::errc::operation_canceled) { /* do nothing */ } else { @@ -598,41 +656,42 @@ class cql_connection_impl_t : public cql::cql_connection_t void - body_read_handle(const cql::cql_header_impl_t& header, - const boost::system::error_code& err) { - + body_read_handle( + const cql::cql_header_impl_t& header, + const boost::system::error_code& err) + { log(CQL_LOG_DEBUG, "received body for message " + header.str()); - if(err) { + if (err) { log(CQL_LOG_ERROR, "error reading body " + err.message()); check_transport_err(err); - + header_read(); // loop return; } - + cql::cql_error_t consume_error; if (!_response_message->consume(&consume_error)) { log(CQL_LOG_ERROR, "error deserializing result message " + consume_error.message); - + header_read(); return; } switch (header.opcode()) { - case CQL_OPCODE_RESULT: + case CQL_OPCODE_RESULT: { log(CQL_LOG_DEBUG, "received result message " + header.str()); - + cql_stream_t stream = header.stream(); - - if(!_callback_storage.has_callbacks(stream)) { + + if (!_callback_storage.has_callbacks(stream)) { log(CQL_LOG_INFO, "no callback found for message " + header.str()); } else { callback_pair_t callback_pair = _callback_storage.get_callbacks(stream); release_stream(stream); - + callback_pair.first(*this, header.stream(), dynamic_cast(_response_message.release())); } break; @@ -645,33 +704,34 @@ class cql_connection_impl_t : public cql::cql_connection_t } break; - case CQL_OPCODE_ERROR: + case CQL_OPCODE_ERROR: { cql_stream_t stream = header.stream(); - if(!_callback_storage.has_callbacks(stream)) { + if (!_callback_storage.has_callbacks(stream)) { log(CQL_LOG_INFO, "no callback found for message " + header.str() + " " + _response_message->str()); } else { callback_pair_t callback_pair = _callback_storage.get_callbacks(stream); release_stream(stream); - - cql::cql_message_error_impl_t* m = + + cql::cql_message_error_impl_t* m = dynamic_cast(_response_message.get()); - - cql::cql_error_t cql_error = + + cql::cql_error_t cql_error = cql::cql_error_t::cassandra_error(m->code(), m->message()); - + callback_pair.second(*this, stream, cql_error); - } + } break; } - + case CQL_OPCODE_READY: log(CQL_LOG_DEBUG, "received ready message"); if (!_events_registered) { events_register(); - } else { + } + else { _ready = true; if (_connect_callback) { // let the caller know that the connection is ready @@ -698,7 +758,8 @@ class cql_connection_impl_t : public cql::cql_connection_t } void - events_register() { + events_register() + { std::auto_ptr m(new cql::cql_message_register_impl_t()); m->events(_events); @@ -713,44 +774,52 @@ class cql_connection_impl_t : public cql::cql_connection_t } void - options_write() { - create_request(new cql::cql_message_options_impl_t(), - (boost::function)boost::bind(&cql_connection_impl_t::write_handle, - this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred), - _reserved_stream); + options_write() + { + create_request( + new cql::cql_message_options_impl_t(), + (boost::function)boost::bind( + &cql_connection_impl_t::write_handle, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred), + _reserved_stream); // start listening header_read(); } void - startup_write() { + startup_write() + { std::auto_ptr m(new cql::cql_message_startup_impl_t()); m->version(CQL_VERSION_IMPL); - create_request(m.release(), - boost::bind(&cql_connection_impl_t::write_handle, - this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred), - _reserved_stream); + create_request( + m.release(), + boost::bind(&cql_connection_impl_t::write_handle, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred), + _reserved_stream); } void - credentials_write() { + credentials_write() + { std::auto_ptr m(new cql::cql_message_credentials_impl_t()); m->credentials(_credentials); - create_request(m.release(), - boost::bind(&cql_connection_impl_t::write_handle, - this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred), - _reserved_stream); + create_request( + m.release(), + boost::bind(&cql_connection_impl_t::write_handle, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred), + _reserved_stream); } inline void - check_transport_err(const boost::system::error_code& err) { + check_transport_err(const boost::system::error_code& err) + { if (!_transport->lowest_layer().is_open()) { _ready = false; _defunct = true; @@ -765,28 +834,27 @@ class cql_connection_impl_t : public cql::cql_connection_t } } - cql_endpoint_t _endpoint; - boost::asio::ip::tcp::resolver _resolver; - std::auto_ptr _transport; - cql::cql_stream_id_t _stream_counter; - request_buffer_t _request_buffer; - cql::cql_header_impl_t _response_header; - std::auto_ptr _response_message; - callback_storage_t _callback_storage; - boost::atomic_int _numer_of_free_stream_ids; - cql_connection_callback_t _connect_callback; - cql_connection_errback_t _connect_errback; - cql_log_callback_t _log_callback; - bool _events_registered; - std::list _events; - cql_event_callback_t _event_callback; + cql_endpoint_t _endpoint; + boost::asio::ip::tcp::resolver _resolver; + std::auto_ptr _transport; + cql::cql_stream_id_t _stream_counter; + request_buffer_t _request_buffer; + cql::cql_header_impl_t _response_header; + std::auto_ptr _response_message; + callback_storage_t _callback_storage; + int _number_of_free_stream_ids; + cql_connection_callback_t _connect_callback; + cql_connection_errback_t _connect_errback; + cql_log_callback_t _log_callback; + bool _events_registered; + std::list _events; + cql_event_callback_t _event_callback; cql::cql_connection_t::cql_credentials_t _credentials; - bool _defunct; - bool _ready; - bool _closing; - // Stream with ID equal 0 - cql_stream_t _reserved_stream; - cql_uuid_t _uuid; + bool _defunct; + bool _ready; + bool _closing; + cql_stream_t _reserved_stream; + cql_uuid_t _uuid; }; } // namespace cql diff --git a/include/cql/internal/cql_control_connection.hpp b/include/cql/internal/cql_control_connection.hpp index e1485de24..86635a358 100644 --- a/include/cql/internal/cql_control_connection.hpp +++ b/include/cql/internal/cql_control_connection.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "cql/cql_builder.hpp" @@ -19,79 +18,99 @@ class cql_cluster_t; class cql_session_t; class cql_configuration_t; class cql_connection_t; - -class cql_control_connection_t : private boost::noncopyable { + +class cql_control_connection_t : + private boost::noncopyable +{ public: - cql_control_connection_t(cql_cluster_t& cluster, - boost::asio::io_service& io_service, - boost::shared_ptr configuration); - - void init(); - void shutdown(int timeout_ms = -1); - - virtual ~cql_control_connection_t(); - + cql_control_connection_t( + cql_cluster_t& cluster, + boost::asio::io_service& io_service, + boost::shared_ptr configuration); + + void + init(); + + void + shutdown( + int timeout_ms = -1); + + virtual + ~cql_control_connection_t(); + private: void - metadata_hosts_event(void* sender, boost::shared_ptr event); - + metadata_hosts_event( + void* sender, + boost::shared_ptr event); + void setup_event_listener(); void refresh_node_list_and_token_map(); - + void - conn_cassandra_event(void* sender, boost::shared_ptr event); + conn_cassandra_event( + void* sender, + boost::shared_ptr event); void - setup_control_connection(bool refresh_only = false); + setup_control_connection( + bool refresh_only = false); bool refresh_hosts(); - + void reconnection_callback(); - boost::mutex _mutex; - - boost::atomic_bool _is_open; - boost::shared_ptr _session; - - cql_cluster_t& _cluster; - boost::asio::io_service& _io_service; - boost::shared_ptr _configuration; - boost::asio::deadline_timer _timer; - cql_connection_t::cql_log_callback_t _log_callback; - boost::shared_ptr _active_connection; - + boost::mutex _mutex; + bool _is_open; + boost::shared_ptr _session; + cql_cluster_t& _cluster; + boost::asio::io_service& _io_service; + boost::shared_ptr _configuration; + boost::asio::deadline_timer _timer; + cql_connection_t::cql_log_callback_t _log_callback; + boost::shared_ptr _active_connection; boost::shared_ptr _reconnection_schedule; - + static cql_host_t::ip_address_t - make_ipv4_address_from_bytes(cql::cql_byte_t* data); - + make_ipv4_address_from_bytes( + cql::cql_byte_t* data); + static std::string - select_keyspaces_expression() { + select_keyspaces_expression() + { return "SELECT * FROM system.schema_keyspaces;"; } + static std::string - select_column_families_expression() { + select_column_families_expression() + { return "SELECT * FROM system.schema_columnfamilies;"; } + static std::string - select_columns_expression() { + select_columns_expression() + { return "SELECT * FROM system.schema_columns;"; } + static std::string - select_peers_expression() { + select_peers_expression() + { return "SELECT peer, data_center, rack, tokens, rpc_address FROM system.peers;"; } + static std::string - select_local_expression() { + select_local_expression() + { return "SELECT cluster_name, data_center, rack, tokens, partitioner FROM system.local WHERE key='local';"; } - + }; } // namespace cql diff --git a/include/cql/internal/cql_hosts.hpp b/include/cql/internal/cql_hosts.hpp index 91d8657cf..d91cc80ad 100644 --- a/include/cql/internal/cql_hosts.hpp +++ b/include/cql/internal/cql_hosts.hpp @@ -1,13 +1,13 @@ #ifndef CQL_HOSTS_HPP_ #define CQL_HOSTS_HPP_ +#include #include -#include #include +#include +#include -#include "cql/lockfree/boost_ip_address_traits.hpp" -#include "cql/lockfree/cql_lockfree_hash_map.hpp" #include "cql/cql_host.hpp" #include "cql/cql_endpoint.hpp" #include "cql/policies/cql_reconnection_policy.hpp" @@ -15,7 +15,7 @@ namespace cql { class cql_hosts_t { - + typedef ::boost::shared_ptr host_ptr_t; @@ -23,60 +23,76 @@ namespace cql { public: inline bool - try_get(const cql_endpoint_t& endpoint, host_ptr_t* host) { - if(!host) + try_get( + const cql_endpoint_t& endpoint, + host_ptr_t* host) + { + boost::mutex::scoped_lock lock(_mutex); + + if (!host) { throw std::invalid_argument("host cannot be null."); + } + - return _hosts.try_get(endpoint, host); + hosts_map_t::const_iterator iter = _hosts.find(endpoint); + if (iter != _hosts.end()) { + *host = iter->second; + return true; + } + return false; } - // Concurrently returns list of hosts. + // Concurrently returns list of hosts. // This may NOT return all hosts, due to concurrency issues. // How to use: // std::vector<> hosts; // this_class->get_hosts(&hosts); // Thorws std::invalid_argument when passed pointer is null. void - get_hosts(std::vector* empty_vector); + get_hosts( + std::vector& empty_vector); // See get_hosts comment. void - get_endpoints(std::vector* empty_vector); + get_endpoints( + std::vector& empty_vector); // brigns up specifed host. if host doesn't exist it // is created. bool - bring_up(const cql_endpoint_t& endpoint); + bring_up( + const cql_endpoint_t& endpoint); // sets host down if it exists in collection, otherwise // do nothing. bool - set_down(const cql_endpoint_t& endpoint); + set_down( + const cql_endpoint_t& endpoint); // removes host from collection, returns true when // host was removed, false otherwise. bool - try_remove(const cql_endpoint_t& endpoint); + try_remove( + const cql_endpoint_t& endpoint); // expected_load - specify how many host you expect will be used // by this class. This can speed up certain operations like host lookup. - static ::boost::shared_ptr + static boost::shared_ptr create( - const boost::shared_ptr& reconnection_policy, - const size_t expected_load = 1024); - + const boost::shared_ptr& reconnection_policy); + private: cql_hosts_t( - const boost::shared_ptr& rp, - const size_t expected_size) - : _reconnection_policy(rp), - _hosts(expected_size) { } + const boost::shared_ptr& rp) + : _reconnection_policy(rp) + {} - boost::shared_ptr - _reconnection_policy; + typedef std::map hosts_map_t; - cql_lockfree_hash_map_t _hosts; + boost::mutex _mutex; + boost::shared_ptr _reconnection_policy; + hosts_map_t _hosts; }; } -#endif // CQL_HOSTS_HPP_ \ No newline at end of file +#endif // CQL_HOSTS_HPP_ diff --git a/include/cql/internal/cql_promise.hpp b/include/cql/internal/cql_promise.hpp index 515403b76..d2320df28 100644 --- a/include/cql/internal/cql_promise.hpp +++ b/include/cql/internal/cql_promise.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_promise.hpp * Author: mc * @@ -12,46 +12,54 @@ #include #include -#include "cql/internal/cql_util.hpp" - namespace cql { template class cql_promise_t { public: - cql_promise_t() - : _value_set(new boost::atomic_bool(false)) - , _promise(new boost::promise()) - , _future(_promise->get_future()) { } - + cql_promise_t() : + _mutex(new boost::mutex()), + _value_set(new bool(false)), + _promise(new boost::promise()), + _future(_promise->get_future()) + {} + // in multithraded environment only // one thread will succeedd in setting promise value. inline bool - set_value(const TResult& value) { - if(try_acquire_lock(_value_set)) { + set_value( + const TResult& value) + { + boost::mutex::scoped_lock lock(*_mutex); + if (!*_value_set) { _promise->set_value(value); return true; } return false; } - + inline bool - set_exception(const boost::exception_ptr& exception) { - if(try_acquire_lock(_value_set)) { + set_exception( + const boost::exception_ptr& exception) + { + boost::mutex::scoped_lock lock(*_mutex); + if (!*_value_set) { _promise->set_exception(exception); return true; } - + return false; } - - inline boost::shared_future - shared_future() const { - return _future; - } - + + inline boost::shared_future + shared_future() const + { + return _future; + } + private: - boost::shared_ptr _value_set; + boost::shared_ptr _mutex; + boost::shared_ptr _value_set; boost::shared_ptr > _promise; boost::shared_future _future; }; @@ -59,4 +67,3 @@ class cql_promise_t { } #endif /* CQL_PROMISE_HPP */ - diff --git a/include/cql/internal/cql_rand.hpp b/include/cql/internal/cql_rand.hpp index 368197624..9b2f3f312 100644 --- a/include/cql/internal/cql_rand.hpp +++ b/include/cql/internal/cql_rand.hpp @@ -6,4 +6,4 @@ namespace cql { int cql_rand(); } -#endif // CQL_RAND_HPP_ \ No newline at end of file +#endif // CQL_RAND_HPP_ diff --git a/include/cql/internal/cql_session_impl.hpp b/include/cql/internal/cql_session_impl.hpp index 4e5fd5310..e67dc04be 100644 --- a/include/cql/internal/cql_session_impl.hpp +++ b/include/cql/internal/cql_session_impl.hpp @@ -25,25 +25,24 @@ #include #include -#include +#include #include #include #include +#include #include -#include +#include "cql/common_type_definitions.hpp" #include "cql/cql.hpp" -#include "cql/cql_connection.hpp" -#include "cql/cql_session.hpp" #include "cql/cql_builder.hpp" #include "cql/cql_cluster.hpp" -#include "cql/policies/cql_load_balancing_policy.hpp" -#include "cql/lockfree/boost_ip_address_traits.hpp" -#include "cql/lockfree/cql_lockfree_hash_map.hpp" +#include "cql/cql_connection.hpp" #include "cql/cql_endpoint.hpp" -#include "cql/common_type_definitions.hpp" -#include "cql/internal/cql_trashcan.hpp" +#include "cql/cql_session.hpp" +#include "cql/policies/cql_load_balancing_policy.hpp" + #include "cql/internal/cql_promise.hpp" +#include "cql/internal/cql_trashcan.hpp" namespace cql { @@ -53,7 +52,8 @@ class cql_result_t; class cql_execute_t; struct cql_error_t; -class cql_session_callback_info_t { +class cql_session_callback_info_t +{ public: explicit cql_session_callback_info_t( @@ -66,51 +66,63 @@ class cql_session_callback_info_t { _defunct_callback(defunct), _log_callback(log) { } - inline void - set_client_callback(const cql_session_t::cql_client_callback_t& client_callback) { + inline void + set_client_callback( + const cql_session_t::cql_client_callback_t& client_callback) + { _client_callback = client_callback; } - + inline void - set_ready_callback(const cql_session_t::cql_ready_callback_t& ready_callback) { + set_ready_callback( + const cql_session_t::cql_ready_callback_t& ready_callback) + { _ready_callback = ready_callback; } - + inline void - set_defunct_callback(const cql_session_t::cql_defunct_callback_t& defunct_callback) { + set_defunct_callback( + const cql_session_t::cql_defunct_callback_t& defunct_callback) + { _defunct_callback = defunct_callback; } - + inline void - set_log_callback(const cql_session_t::cql_log_callback_t& log_callback) { + set_log_callback( + const cql_session_t::cql_log_callback_t& log_callback) + { _log_callback = log_callback; } - + private: - cql_session_t::cql_client_callback_t - client_callback() const { + cql_session_t::cql_client_callback_t + client_callback() const + { return _client_callback; } - - cql_session_t::cql_ready_callback_t - ready_callback() const { + + cql_session_t::cql_ready_callback_t + ready_callback() const + { return _ready_callback; } - - cql_session_t::cql_defunct_callback_t - defunct_callback() const { + + cql_session_t::cql_defunct_callback_t + defunct_callback() const + { return _defunct_callback; } - - cql_session_t::cql_log_callback_t - log_callback() const { + + cql_session_t::cql_log_callback_t + log_callback() const + { return _log_callback; } - + friend class cql_session_impl_t; - + private: - + cql_session_t::cql_client_callback_t _client_callback; cql_session_t::cql_ready_callback_t _ready_callback; cql_session_t::cql_defunct_callback_t _defunct_callback; @@ -119,105 +131,113 @@ class cql_session_callback_info_t { class cql_session_impl_t : public cql_session_t, - boost::noncopyable + boost::noncopyable { public: cql_session_impl_t( const cql_session_callback_info_t& callbacks, boost::shared_ptr configuration); - void + void init(boost::asio::io_service& io_service); - boost::shared_ptr + boost::shared_ptr connect( - boost::shared_ptr query_plan, - cql_stream_t* stream, + boost::shared_ptr query_plan, + cql_stream_t* stream, std::list* tried_hosts); - + virtual cql_uuid_t id() const; - - virtual + + virtual ~cql_session_impl_t(); -private: - struct client_container_t { +private: + typedef std::map > cql_connections_collection_t; + + struct client_container_t + { client_container_t( - const boost::shared_ptr& c) - : connection(c) - , errors(0) { } + const boost::shared_ptr& c) : + connection(c), + errors(0) + {} boost::shared_ptr connection; size_t errors; }; - - typedef - boost::ptr_deque - clients_collection_t; typedef - boost::atomic - connection_counter_t; - + boost::ptr_deque + clients_collection_t; + + typedef long connection_counter_t; + typedef - cql_lockfree_hash_map_t< - cql_endpoint_t, - boost::shared_ptr > - connections_counter_t; - - boost::shared_ptr - allocate_connection(const boost::shared_ptr& host); + std::map< + cql_endpoint_t, + boost::shared_ptr > + connections_counter_t; + + boost::shared_ptr + allocate_connection( + const boost::shared_ptr& host); - void - free_connection(boost::shared_ptr connection); + void + free_connection( + boost::shared_ptr connection); typedef - cql_stream_t (::cql::cql_connection_t::* exec_query_method_t )( - const boost::shared_ptr& query, - cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback); + cql_stream_t(cql::cql_connection_t::* exec_query_method_t )( + const boost::shared_ptr& query, + cql_connection_t::cql_message_callback_t callback, + cql_connection_t::cql_message_errback_t errback); cql_stream_t execute_operation( - const boost::shared_ptr& query, - cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback, - exec_query_method_t method); + const boost::shared_ptr& query, + cql_connection_t::cql_message_callback_t callback, + cql_connection_t::cql_message_errback_t errback, + exec_query_method_t method); cql_stream_t query( - const boost::shared_ptr& query, - cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback); + const boost::shared_ptr& query, + cql_connection_t::cql_message_callback_t callback, + cql_connection_t::cql_message_errback_t errback); cql_stream_t prepare( - const boost::shared_ptr& query, - cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback); + const boost::shared_ptr& query, + cql_connection_t::cql_message_callback_t callback, + cql_connection_t::cql_message_errback_t errback); cql_stream_t execute( - const boost::shared_ptr& message, - cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback); + const boost::shared_ptr& message, + cql_connection_t::cql_message_callback_t callback, + cql_connection_t::cql_message_errback_t errback); boost::shared_future - query(const boost::shared_ptr& query); + query( + const boost::shared_ptr& query); boost::shared_future - prepare(const boost::shared_ptr& query); + prepare( + const boost::shared_ptr& query); boost::shared_future - execute(const boost::shared_ptr& message); + execute( + const boost::shared_ptr& message); void close(); inline void - log(cql_short_t level, + log( + cql_short_t level, const std::string& message); void @@ -228,76 +248,76 @@ class cql_session_impl_t : void connect_errback( boost::shared_ptr > promise, - cql_connection_t& client, - const cql_error_t& error); + cql_connection_t& client, + const cql_error_t& error); void connect_future_callback( boost::shared_ptr > promise, - cql_connection_t& client); + cql_connection_t& client); void connect_future_errback( boost::shared_ptr > promise, - cql_connection_t& client, - const cql_error_t& error); + cql_connection_t& client, + const cql_error_t& error); boost::shared_ptr - get_connection(const boost::shared_ptr& query, - cql_stream_t* stream); + get_connection( + const boost::shared_ptr& query, + cql_stream_t* stream); cql_host_distance_enum - get_host_distance(boost::shared_ptr host); - + get_host_distance( + boost::shared_ptr host); + void free_connections( - cql_connections_collection_t& connections, - const std::list& connections_to_remove); + cql_connections_collection_t& connections, + const std::list& connections_to_remove); cql_connections_collection_t* add_to_connection_pool( - const cql_endpoint_t& host_address); + cql_endpoint_t& host_address); void try_remove_connection( cql_connections_collection_t* const connections, - const cql_uuid_t& connection_id); + const cql_uuid_t& connection_id); boost::shared_ptr try_find_free_stream( - boost::shared_ptr const& host, - cql_connections_collection_t* const connections, - cql_stream_t* stream); - + boost::shared_ptr const& host, + cql_connections_collection_t* const connections, + cql_stream_t* stream); + bool increase_connection_counter( const boost::shared_ptr& host); - + bool decrease_connection_counter( const boost::shared_ptr& host); - + long get_max_connections_number( const boost::shared_ptr& host); - - + + friend class cql_trashcan_t; - -private: - - cql_session_t::cql_client_callback_t _client_callback; - cql_session_t::cql_ready_callback_t _ready_callback; - cql_session_t::cql_defunct_callback_t _defunct_callback; - cql_session_t::cql_log_callback_t _log_callback; - cql_session_t::cql_connection_errback_t _connect_errback; - - cql_uuid_t _uuid; - boost::shared_ptr _configuration; - - cql_connection_pool_t _connection_pool; - boost::shared_ptr _trashcan; - connections_counter_t _connection_counters; + typedef boost::ptr_map connection_pool_t; + + boost::mutex _mutex; + cql_session_t::cql_client_callback_t _client_callback; + cql_session_t::cql_ready_callback_t _ready_callback; + cql_session_t::cql_defunct_callback_t _defunct_callback; + cql_session_t::cql_log_callback_t _log_callback; + cql_session_t::cql_connection_errback_t _connect_errback; + cql_uuid_t _uuid; + boost::shared_ptr _configuration; + connection_pool_t _connection_pool; + boost::shared_ptr _trashcan; + connections_counter_t _connection_counters; }; } // namespace cql diff --git a/include/cql/internal/cql_system_dependent.hpp b/include/cql/internal/cql_system_dependent.hpp index d47c16f78..5af9d81f3 100644 --- a/include/cql/internal/cql_system_dependent.hpp +++ b/include/cql/internal/cql_system_dependent.hpp @@ -2,7 +2,7 @@ #ifndef CQL_SYSTEM_DEPENDENT_H_ #define CQL_SYSTEM_DEPENDENT_H_ -// snprintf +// snprintf #include #ifdef _WIN32 @@ -10,4 +10,4 @@ #endif -#endif // CQL_SYSTEM_DEPENDENT_H_ \ No newline at end of file +#endif // CQL_SYSTEM_DEPENDENT_H_ diff --git a/include/cql/internal/cql_trashcan.hpp b/include/cql/internal/cql_trashcan.hpp index 59cf4219d..ea24d79ee 100644 --- a/include/cql/internal/cql_trashcan.hpp +++ b/include/cql/internal/cql_trashcan.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_trashcan.hpp * Author: mc * @@ -8,58 +8,59 @@ #ifndef CQL_TRASHCAN_HPP_ #define CQL_TRASHCAN_HPP_ -#include #include +#include +#include +#include -#include "cql/lockfree/cql_lockfree_hash_map.hpp" #include "cql/common_type_definitions.hpp" + #include "cql/cql_endpoint.hpp" #include "cql/cql_connection.hpp" namespace cql { class cql_session_impl_t; - - class cql_trashcan_t: boost::noncopyable + + class cql_trashcan_t : + boost::noncopyable { public: cql_trashcan_t( boost::asio::io_service& timer_service, - cql_session_impl_t& session) - : _timer(timer_service), - _session(session) { } - - ~cql_trashcan_t(); - + cql_session_impl_t& session) : + _timer(timer_service), + _session(session) + {} + void - put(const boost::shared_ptr& connection); - + put( + const boost::shared_ptr& connection); + boost::shared_ptr - recycle(const cql_endpoint_t& address); - + recycle( + const cql_endpoint_t& address); + void remove_all(); - + private: + typedef std::map > cql_connections_collection_t; + void - cleanup(); - - void - cleanup( - const cql_uuid_t& connection_id, - cql_connections_collection_t* const connections); - - void - timeout(const boost::system::error_code& error); - + timeout( + const boost::system::error_code& error); + boost::posix_time::time_duration timer_expires_time() const; - - boost::asio::deadline_timer _timer; - cql_connection_pool_t _trashcan; - cql_session_impl_t& _session; + + typedef boost::ptr_map connection_pool_t; + + boost::mutex _mutex; + boost::asio::deadline_timer _timer; + connection_pool_t _trashcan; + cql_session_impl_t& _session; }; } #endif /* CQL_TRASHCAN_HPP_ */ - diff --git a/include/cql/internal/cql_util.hpp b/include/cql/internal/cql_util.hpp index fbaee0337..2aee298e9 100644 --- a/include/cql/internal/cql_util.hpp +++ b/include/cql/internal/cql_util.hpp @@ -24,7 +24,6 @@ #include #include #include -#include #include "cql/cql.hpp" #include "cql/internal/cql_system_dependent.hpp" @@ -42,19 +41,19 @@ operator<<(std::ostream& o, const cql_hex_char_struct_t& hs) { return (o << std::hex << (int)hs.c); } -inline cql_hex_char_struct_t +inline cql_hex_char_struct_t hex(unsigned char _c) { return cql_hex_char_struct_t(_c); } // Safe version of strncpy (this method always null terminates // dest buffer). -char* +char* safe_strncpy(char* dest, const char* src, const size_t count); // When str is NULL returns empty string(""), in any other // case returns str. -inline const char* +inline const char* empty_when_null(const char* str) { if(!str) return ""; @@ -64,21 +63,16 @@ empty_when_null(const char* str) { // tries to convert given string to boost asio ip address. // return false when conversion fails, return true otherwise. // if this returns true then result will contain valid ip address. -bool +bool to_ipaddr(const std::string& str, boost::asio::ip::address* result); // returns current UTC time. -// result of this functions depends on local +// result of this functions depends on local // system settings which may be modified by user. -boost::posix_time::ptime +boost::posix_time::ptime utc_now(); -// tries to change lock sate to true, returns true lock state -// was changed, false otherwise. -bool -try_acquire_lock(const boost::shared_ptr& lock); - } // namespace cql #endif // CQL_UTIL_H_ diff --git a/include/cql/lockfree/boost_ip_address_traits.hpp b/include/cql/lockfree/boost_ip_address_traits.hpp deleted file mode 100644 index 520d4b982..000000000 --- a/include/cql/lockfree/boost_ip_address_traits.hpp +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef BOOST_IP_ADDRESS_TRAITS_ -#define BOOST_IP_ADDRESS_TRAITS_ - -// File contains specializations of std::less<> -// and std::hash<> for boost::asio::ip:address type. - -#include - -namespace std { - - template<> - struct hash< ::boost::asio::ip::address> { - public: - typedef - ::boost::asio::ip::address - argument_type; - - typedef - ::std::size_t - result_type; - - private: - template - inline result_type - get_hash(const TBytesType& ip_bytes) const { - // implemented using djb2 algorithm - // see: http://www.cse.yorku.ca/~oz/hash.html - - unsigned long hash = 5381; - - for(typename TBytesType::const_iterator it = ip_bytes.cbegin(); - it != ip_bytes.cend(); ++it) - { - hash = ((hash << 5) + hash) + *it; - } - - return static_cast(hash); - } - - public: - inline result_type - operator ()(const argument_type& address) const { - if(address.is_v4()) { - return get_hash(address.to_v4().to_bytes()); - } - else { - return get_hash(address.to_v6().to_bytes()); - } - } - }; - - template<> - struct less< ::boost::asio::ip::address> { - public: - typedef - ::boost::asio::ip::address - ip_addr; - - typedef - ip_addr - first_argument_type; - - typedef - ip_addr - second_argument_type; - - typedef - bool - result_type; - - private: - typedef - ::boost::asio::ip::address_v6 - ip_v6; - - inline ip_v6 - to_ip_v6(const ip_addr& address) const { - return address.is_v6() - ? address.to_v6() - : ip_v6::v4_mapped(address.to_v4()); - } - - public: - inline result_type - operator ()(const ip_addr& first, const ip_addr& second) const { - ip_v6 first_v6 = to_ip_v6(first); - ip_v6 second_v6 = to_ip_v6(second); - - ip_v6::bytes_type first_bytes = first_v6.to_bytes(); - ip_v6::bytes_type second_bytes = second_v6.to_bytes(); - - ip_v6::bytes_type::const_iterator first_it = first_bytes.cbegin(); - ip_v6::bytes_type::const_iterator second_it = second_bytes.cbegin(); - - // compare addresses bytes - for(; first_it != first_bytes.cend(); ++first_it, ++second_it) { - int delta = (int)*first_it - (int)*second_it; - if(delta != 0) - return delta < 0; - } - - // both addresses are equal - return false; - } - }; -} - -#endif // BOOST_IP_ADDRESS_TRAITS_ \ No newline at end of file diff --git a/include/cql/lockfree/cql_2hashmap.hpp b/include/cql/lockfree/cql_2hashmap.hpp deleted file mode 100644 index 698d20f02..000000000 --- a/include/cql/lockfree/cql_2hashmap.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * File: cql_2hashmap_t.hpp - * Author: mc - * - * Created on October 2, 2013, 8:39 AM - */ - -#ifndef CQL_2HASHMAP_T_HPP -#define CQL_2HASHMAP_T_HPP - -#include -#include "cql/lockfree/cql_lockfree_hash_map.hpp" - -namespace cql { - template - struct cql_2key_t { - cql_2key_t(const TKey1& key1, const TKey2& key2) - : _key1(key1), _key2(key2) { } - - inline const TKey1& - key1() const { return _key1; } - - inline const TKey2& - key2() const { return _key2; } - - private: - TKey1 _key1; - TKey2 _key2; - }; -} - -namespace std { - template - struct hash > { - typedef - cql::cql_2key_t - argument_type; - - typedef - ::std::size_t - result_type; - - hash() - : _key1_hash() - , _key2_hash() { } - - inline result_type - operator ()(const argument_type& key) const { - return - _key1_hash(key.key1()) * 178493u + - _key2_hash(key.key2()); - } - - private: - ::std::hash _key1_hash; - ::std::hash _key2_hash; - }; - - template - struct less > { - typedef - cql::cql_2key_t - first_argument_type; - - typedef - cql::cql_2key_t - second_argument_type; - - typedef - bool - result_type; - - less() - : _key1_less() - , _key2_less() { } - - inline result_type - operator ()(const first_argument_type& first, const second_argument_type& second) const { - if(_key1_less(first.key1(), second.key1())) - return true; - - if(_key1_less(second.key1(), first.key1())) - return false; - - return _key2_less(first.key2(), second.key2()); - } - - private: - ::std::less _key1_less; - ::std::less _key2_less; - }; -} - -namespace cql { - template - class cql_2hashmap_t - : public cql_lockfree_hash_map_t, TValue> - { - public: - cql_2hashmap_t() - : cql_lockfree_hash_map_t, TValue>() { } - - cql_2hashmap_t(size_t expected_items_count, size_t load_factor = 1) - : cql_lockfree_hash_map_t, TValue> (expected_items_count, load_factor) { } - - inline virtual - ~cql_2hashmap_t() { } - }; -} - -#endif /* CQL_2HASHMAP_T_HPP */ - diff --git a/include/cql/lockfree/cql_lockfree_hash_map.hpp b/include/cql/lockfree/cql_lockfree_hash_map.hpp deleted file mode 100644 index 3bc1ca08d..000000000 --- a/include/cql/lockfree/cql_lockfree_hash_map.hpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * File: lockfree_hash_map.hpp - * Author: mc - * - * Created on September 18, 2013, 1:20 PM - */ - -#ifndef CQL_LOCKFREE_HASH_MAP_HPP_ -#define CQL_LOCKFREE_HASH_MAP_HPP_ - -// -// REQUIRES NEW C++11 STANDARD -// -#include -#include -#include -#include - -#include -#include -#include - -namespace cql { - template - struct cql_lockfree_hash_map_traits_t - : public cds::container::split_list::type_traits - { - - typedef cds::container::michael_list_tag ordered_list ; // what type of ordered list we want to use - typedef std::hash hash ; // hash functor for the key stored in split-list map - - // Type traits for our MichaelList class - struct ordered_list_traits: public cds::container::michael_list::type_traits { - typedef std::less less; // comparer that specifies order of list nodes - }; - }; - - template - class cql_lockfree_hash_map_t { - public: - typedef - cds::container::SplitListMap > - base_hash_map; - - typedef - typename base_hash_map::iterator - iterator; - - typedef - typename base_hash_map::const_iterator - const_iterator; - - private: - - // Functor copies value associated with given key - // in hash_map to storage pointed by param storage. - struct copy_value_functor_t { - inline - copy_value_functor_t(TValue* storage) - : _storage(storage) - { - assert(storage != NULL); - }; - - inline void - operator ()(std::pair const& pair) { - *_storage = pair.second; - } - - inline void - operator ()(bool is_new, std::pair const& pair) { - // is_new is true when this function is called for newly - // inserted item - *_storage = pair.second; - } - - private: - TValue* const _storage; - }; - - public: - - cql_lockfree_hash_map_t() - : _map() { } - - cql_lockfree_hash_map_t(size_t expected_items_count, size_t load_factor = 1) - : _map(expected_items_count, load_factor) { } - - inline virtual - ~cql_lockfree_hash_map_t() { } - - inline size_t - size() const { - return _map.size(); - } - - inline void - clear() { - _map.clear(); - } - - inline bool - try_add(TKey const& key, TValue const& value) { - return _map.insert(key, value); - } - - inline bool - try_erase(TKey const& key, TValue* const value) { - assert(value != NULL); - copy_value_functor_t f(value); - return _map.erase(key, f); - } - - inline bool - try_erase(TKey const& key) { - return _map.erase(key); - } - - inline bool - try_get(TKey const& key, TValue* const value) { - assert(value != NULL); - copy_value_functor_t f(value); - return _map.find(key, f); - } - - // Inserts hash map key to container using back inserter. - // How to use: - // std::vector keys; - // map.unsafe_get_keys(back_inserter(keys)); - // - // Warning: This is called unsafe because it may not return all keys - // contained in map. - template - inline void - get_keys(TOutputIterator b_inserter) { - typename base_hash_map::iterator it = _map.begin(); - for(; it != _map.end(); ++it) { - *b_inserter++ = it->first; // copy key - } - } - - template - inline void - get_values(TOutputIterator b_inserter) { - typename base_hash_map::iterator it = _map.begin(); - for(; it != _map.end(); ++it) { - *b_inserter++ = it->second; // copy key - } - } - - // Retruns map iterator. - // This may not traverse all hash map elements - // due to concurrency issues. - inline iterator - begin() { - return _map.begin(); - } - - inline iterator - end() { - return _map.end(); - } - - inline const_iterator - cbegin() const { - return _map.cbegin(); - } - - inline const_iterator - cend() const { - return _map.cend(); - } - - public: - base_hash_map _map; - }; -} - -#endif /* CQL_LOCKFREE_HASH_MAP_HPP_ */ - diff --git a/include/cql/policies/cql_default_retry_policy.hpp b/include/cql/policies/cql_default_retry_policy.hpp index 458815e99..cd26b3760 100644 --- a/include/cql/policies/cql_default_retry_policy.hpp +++ b/include/cql/policies/cql_default_retry_policy.hpp @@ -7,7 +7,7 @@ #include "cql/policies/cql_retry_policy.hpp" namespace cql { - class cql_default_retry_policy_t: + class cql_default_retry_policy_t: public cql_retry_policy_t, boost::noncopyable { @@ -15,27 +15,27 @@ namespace cql { virtual cql_retry_decision_t read_timeout( const cql_query_t& query, - cql_consistency_enum consistency, - int required_responses, - int received_responses, - bool data_retrieved, + cql_consistency_enum consistency, + int required_responses, + int received_responses, + bool data_retrieved, int retry_number); virtual cql_retry_decision_t write_timeout( const cql_query_t& query, - cql_consistency_enum consistency, + cql_consistency_enum consistency, const std::string& write_type, - int required_acks, - int received_acks, + int required_acks, + int received_acks, int retry_number ); virtual cql_retry_decision_t unavailable( const cql_query_t& query, - cql_consistency_enum consistency, - int required_replica, + cql_consistency_enum consistency, + int required_replica, int alive_replica, int retry_number); @@ -43,4 +43,4 @@ namespace cql { }; } -#endif \ No newline at end of file +#endif diff --git a/include/cql/policies/cql_exponential_reconnection_policy_t.hpp b/include/cql/policies/cql_exponential_reconnection_policy_t.hpp index bd8f60b71..4aad5f6ff 100644 --- a/include/cql/policies/cql_exponential_reconnection_policy_t.hpp +++ b/include/cql/policies/cql_exponential_reconnection_policy_t.hpp @@ -1,4 +1,4 @@ -/* +/* * File: cql_exponential_reconnection_policy_t.hpp * Author: mc * @@ -14,46 +14,46 @@ namespace cql { class cql_exponential_reconnection_schedule_t; - - class CQL_EXPORT cql_exponential_reconnection_policy_t - : public cql_reconnection_policy_t + + class CQL_EXPORT cql_exponential_reconnection_policy_t + : public cql_reconnection_policy_t { public: - + inline boost::posix_time::time_duration base_delay() const { return _base_delay; } - + inline boost::posix_time::time_duration max_delay() const { return _max_delay; } - + virtual boost::shared_ptr new_schedule(); - + cql_exponential_reconnection_policy_t( const boost::posix_time::time_duration& base_delay, const boost::posix_time::time_duration& max_delay); - + private: - + boost::posix_time::time_duration _base_delay; boost::posix_time::time_duration _max_delay; }; - - class CQL_EXPORT cql_exponential_reconnection_schedule_t + + class CQL_EXPORT cql_exponential_reconnection_schedule_t : public cql_reconnection_schedule_t { public: virtual boost::posix_time::time_duration get_delay(); - + private: cql_exponential_reconnection_schedule_t( const cql_exponential_reconnection_policy_t& policy) - : _policy(policy), _attempts(0), + : _policy(policy), _attempts(0), _last_delay(boost::posix_time::microseconds(0)) { } - + friend class cql_exponential_reconnection_policy_t; - + const cql_exponential_reconnection_policy_t _policy; int _attempts; boost::posix_time::time_duration _last_delay; @@ -61,4 +61,3 @@ namespace cql { } #endif /* CQL_EXPONENTIAL_RECONNECTION_POLICY_T_HPP_ */ - diff --git a/include/cql/policies/cql_reconnection_policy.hpp b/include/cql/policies/cql_reconnection_policy.hpp index 6b4af3516..8c1d8186d 100644 --- a/include/cql/policies/cql_reconnection_policy.hpp +++ b/include/cql/policies/cql_reconnection_policy.hpp @@ -27,5 +27,4 @@ namespace cql { virtual ~cql_reconnection_policy_t() { } }; } - -#endif // CQL_RECONNECTION_POLICY_HPP_ \ No newline at end of file +#endif // CQL_RECONNECTION_POLICY_HPP_ diff --git a/include/cql/policies/cql_retry_policy.hpp b/include/cql/policies/cql_retry_policy.hpp index b6b49f582..ff9050390 100644 --- a/include/cql/policies/cql_retry_policy.hpp +++ b/include/cql/policies/cql_retry_policy.hpp @@ -21,10 +21,10 @@ namespace cql { inline const boost::optional& consistency_level() const { return _consistency; } - inline static cql_retry_decision_t + inline static cql_retry_decision_t rethrow_decision() { return cql_retry_decision_t( - CQL_RETRY_DECISION_RETHROW, + CQL_RETRY_DECISION_RETHROW, CQL_CONSISTENCY_DEFAULT); } @@ -47,7 +47,7 @@ namespace cql { cql_retry_decision_enum retry_decision, const boost::optional& consistency) : _retry_decision(retry_decision), - _consistency(_consistency) { } + _consistency(consistency) { } cql_retry_decision_enum _retry_decision; boost::optional _consistency; @@ -60,27 +60,27 @@ namespace cql { virtual cql_retry_decision_t read_timeout( const cql_query_t& query, - cql_consistency_enum consistency, - int required_responses, - int received_responses, - bool data_retrieved, + cql_consistency_enum consistency, + int required_responses, + int received_responses, + bool data_retrieved, int retry_number) = 0; virtual cql_retry_decision_t write_timeout( const cql_query_t& query, - cql_consistency_enum consistency, + cql_consistency_enum consistency, const std::string& write_type, - int required_acks, - int received_acks, + int required_acks, + int received_acks, int retry_number ) = 0; virtual cql_retry_decision_t unavailable( const cql_query_t& query, - cql_consistency_enum consistency, - int required_replica, + cql_consistency_enum consistency, + int required_replica, int alive_replica, int retry_number) = 0; @@ -88,4 +88,4 @@ namespace cql { }; } -#endif // CQL_CQL_QUERY_H_ \ No newline at end of file +#endif // CQL_CQL_QUERY_H_ diff --git a/include/cql/policies/cql_round_robin_policy.hpp b/include/cql/policies/cql_round_robin_policy.hpp index 3ee04a5b4..d9889ee3a 100644 --- a/include/cql/policies/cql_round_robin_policy.hpp +++ b/include/cql/policies/cql_round_robin_policy.hpp @@ -3,54 +3,62 @@ #include #include -#include +#include -#include "cql/internal/cql_rand.hpp" #include "cql/policies/cql_load_balancing_policy.hpp" namespace cql { class cql_host_t; class cql_cluster_t; - class cql_round_robin_query_plan_t: public cql_query_plan_t { + class cql_round_robin_query_plan_t : + public cql_query_plan_t + { public: cql_round_robin_query_plan_t( - const cql_cluster_t* cluster, - unsigned index); + const cql_cluster_t* cluster, + unsigned index); // Returns next host to query. virtual boost::shared_ptr next_host_to_query(); private: - unsigned _index; - unsigned _current; - std::vector > _hosts; + boost::mutex _mutex; + unsigned _index; + unsigned _current; + std::vector > _hosts; }; - class cql_round_robin_policy_t: + class cql_round_robin_policy_t : public cql_load_balancing_policy_t, boost::noncopyable { public: - cql_round_robin_policy_t() - : _cluster(), - _index(0) { } + cql_round_robin_policy_t() : + _cluster(), + _index(0) + {} - virtual cql_host_distance_enum - distance(const cql_host_t& host); + virtual cql_host_distance_enum + distance( + const cql_host_t& host); - virtual boost::shared_ptr - new_query_plan(const boost::shared_ptr& query); + virtual boost::shared_ptr + new_query_plan( + const boost::shared_ptr& query); + + protected: + + virtual void + init( + cql_cluster_t* cluster); - protected: - virtual void - init(cql_cluster_t* cluster); - private: - cql_cluster_t* _cluster; - boost::atomic _index; + boost::mutex _mutex; + cql_cluster_t* _cluster; + unsigned _index; }; } -#endif \ No newline at end of file +#endif diff --git a/instruction_win_lin.txt.txt b/instruction_win_lin.txt.txt index e1f026f11..4058cce89 100644 --- a/instruction_win_lin.txt.txt +++ b/instruction_win_lin.txt.txt @@ -1,26 +1,25 @@ Cassandra C++ driver: General Instructions - + (with some Ubuntu- and Windows-specific info. For OS X please refer to macosx_instruction.txt) ---------------------------------------------------------------------------------------------------------------- 0. CMake - The project uses CMake as configuration creator. Under Windows it is recommended to install it from http://cmaketools.codeplex.com/. - Under Ubuntu it might be necessay to build CMake from sources (at the time of this writing we used CMake 2.8.11). - - We made efforts to keep CMakeLists.txt files well documented. You should have no problems with manual adjustments of build settings. In particular it may be necessary to adjust paths for libcds and libssh (see the dependencies note below). + - We made efforts to keep CMakeLists.txt files well documented. You should have no problems with manual adjustments of build settings. 1. How to build the project - - Dependencies: Boost (currently tested with Boost 1.54), libcds (currently 1.4.0), libssh. + - Dependencies: Boost (currently tested with Boost 1.54), libssh. - Additional dependencies that are necessary and may or may not be present on your system: zlib, openssl. - On Windows only the 32 bit version was tested. Please remember that whenever you wish to use dynamically linked libraries (DLLs), they must be located in right directory. For the 64-bit DLLs the right directoy is c:/Windows/System32 (sic) and the 32-bit ones in c:/windows/SysWOW64 (sic). 2. Random remarks - As the IDE for Linux we recommend Eclipse with Git plugin. - - We use CppCheck to statically validate the code against c++03 standard. Libcds uses C++11 features, but the rest of this project should not depend on C++11 features. + - We use CppCheck to statically validate the code against c++03 standard. - There exists a good (proprietary) plugin for VS2010: Visual Assist X. It makes IntelliSense work well with C++. - - The docs on libcds website are out of date. Please use the ones generated by doxygen while building libcds. 3. How it works? @@ -38,4 +37,4 @@ - We recommend formatting with `astyle' command (Linux). - No `using namespace ...' in header files. We avoid `using namespace' in general. - Doxygen comments. Some day... -- For complex classes we use pimpl pattern with abstract base class. \ No newline at end of file +- For complex classes we use pimpl pattern with abstract base class. diff --git a/macosx_instruction.txt b/macosx_instruction.txt index 7d7df6246..b3e1a91df 100644 --- a/macosx_instruction.txt +++ b/macosx_instruction.txt @@ -1,24 +1,22 @@ CASSANDRA CPP DRIVER UNDER MAC OS X NOTES ON BUILDING AND RUNNING - -(tested on Mac OS X 10.8.4 with 2.9 GHz Intel Core i5) - + (tested on Mac OS X 10.9) 0. Cassandra and CCM -The easiest way to get Cassandra up and running on Mac is to install CCM (Cassandra -Cluster Manager). CCM will download Cassandra, so we get one less thing to +The easiest way to get Cassandra up and running on Mac is to install CCM (Cassandra +Cluster Manager). CCM will download Cassandra, so we get one less thing to worry about. The easiest way to get CCM for Mac is to install it via MacPorts: sudo port -v sync && sudo port -v install ccm -(In case you don't have MacPorts, install it by following the instructions at +(In case you don't have MacPorts, install it by following the instructions at http://www.macports.org/install.php) Remeber to set up loopback aliases if you want to spawn more than one Cassandra node: - + sudo ifconfig lo0 alias 127.0.0.2 up sudo ifconfig lo0 alias 127.0.0.3 up sudo ifconfig lo0 alias 127.0.0.4 up @@ -33,117 +31,29 @@ At this stage CCM should work fine. The following procedure aims at setting up Clang toolchain to build our cpp-driver, with Xcode as the preferred IDE. -a. Update the Xcode to the recent version (5.0 at the time of this writing) +a. Update the Xcode to the recent version (5.0.1 at the time of this writing) b. Launch Xcode and go to Preferences->Downloads. Download and install the latest command line tools. Now you need to get the Boost libraries. There is one caveat, though: Boost -packaged by Homebrew is linked by default against GNU libstdc++. We suggest to +packaged by Homebrew is linked by default against GNU libstdc++. We suggest to stick to the libc++ throughout the further development and not to mix both standard libraries. We therefore need to build the Boost with Clang and link it with libc++. This is easiest done by: brew update -brew install boost --with-c++11 +brew install boost --c++11 (Yes, Homebrew will complain about Macports and Homebrew being used at the same time. Unfortunately, Homebrew does not have a CCM package, so we had to use MacPorts there.) -In the same spirit you can install libopenssl, which is also required by the project: - - brew install openssl - -------------------------------------------------------------------------------- - -2. LibCDS (tested on ver. 1.4.0) - -Apparently, libcds does not have a predefined build configuration for Mac OS X. -We have to apply minor modifications to use the 'Linux' target here. - -For the impatient: you can find the modified sources in the cpp-driver/ext directory. -Please, just unpack them and run the build/build-iMac.sh script. - -Otherwise, first download the original sources of libcds and go to 'build' directory -therein. Edit the 'build.sh' script. We need to change a few things there: - -- In the section 'Determine OS family', add target 'darwin' to the family of -'linux|sunos|hpux|aix|...' (so that you have 'darwin|linux|sunos|hpux|aix|...'). -Otherwise the script will halt here with complain about "Unknown operation system". - -- In the section 'Determine compiler flags' we added 'darwin' as possible OS_FAMILY. - - x86) - case $OS_FAMILY in - linux|freebsd|darwin) - buildCXXflags="-m64 -fPIC -march=$ArchFlag" - buildCflags="-m64 -fPIC -march=$ArchFlag" - buildLDflags="-m64 -fPIC" - buildTestLDflags="-m64 -fPIC" - ;; - -After editing the build script, go to the cds/compiler/clang/defs.h file. All -you have to do there is to direct the preprocessor onto the "Linux path". We simply - -...changed this line: -#if defined( __linux__ ) -to this: -#if defined( __linux__ ) || defined(__APPLE__) - -However, the interfaces for getting high resolution time apparently differ in Linux -and in OS X. To fix this, go to cds/os/linux/timer.h and add the following lines among other #includes: - -#ifdef __APPLE__ - #include - #include -#endif - -Then go to the static method Timer::current(native_timer_type&) and modify its body -as follows: - -static void current( native_timer_type& tmr ) -{ -#ifdef __APPLE__ - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - tmr.tv_sec = mts.tv_sec; - tmr.tv_nsec = mts.tv_nsec; -#elce - clock_gettime(CLOCK_REALTIME, &tmr); -#endif -} - -Now cd to the build/ directory and try to build the project with the following command: - -./build.sh --with-make make --with-boost /usr/local/include -c clang -x clang++ \ - -z '-std=c++11 -stdlib=libc++ -Wall -pedantic' \ - -l "-L/usr/local/lib -stdlib=libc++" 2>&1 | tee build.log - -(Please mind the library paths; in your environment they may differ.) - -If it fails at linking, you may need to edit the Makefile. In our cases it was necessary -to add the '-mt' suffix to boost libs listed there. We also removed '-lrt' from linker -input and added '-lboost_system-mt'. - -After building the libcds.so.x.y.z and libcds-debug.so.x.y.z, copy them to the -libpath in your system and create the appropriate aliases there, e.g. -'libcds.dylib' and 'libcds-debug.dylib'. You can also run the tests before deployment. -(find the test app in bin/gcc-platform-darwin-0/test-hdr) - ------------------------------------------------------------------------------- -3. Building the cpp driver +2. Building the cpp driver This one is relatively straightforward. Once you have all the libraries installed, just run the CMake in 'cpp-driver's root folder: cmake -G "Xcode" -In our case CMake was unable to find the cds header files; most likely -you will encounter the same issue. In such case you can edit CMakeCache.txt and manually -set LIBCDS_INCLUDE_DIRS to point the *root directory* of CDS. Alternatively, you -can think of copying the cds headers to appropriate system-wide locations. - ------------------------------------------------------------------------------- diff --git a/nbproject/Package-Default.bash b/nbproject/Package-Default.bash index 69ed0131b..3eac2de05 100644 --- a/nbproject/Package-Default.bash +++ b/nbproject/Package-Default.bash @@ -12,8 +12,6 @@ CND_DISTDIR=dist CND_BUILDDIR=build NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging TMPDIRNAME=tmp-packaging -OUTPUT_PATH=libcds_demo -OUTPUT_BASENAME=libcds_demo PACKAGE_TOP_DIR=cpp-driver/ # Functions diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index 4e02d6e8f..7499b6b40 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -250,14 +250,6 @@ - - - - - - lockfree_hash_map.hpp - main.cpp - @@ -302,7 +294,6 @@ . ${MAKE} -f Makefile ${MAKE} -f Makefile clean - libcds_demo ../../boost_1_54_0 @@ -317,7 +308,6 @@ - ../../cds /extra/ccm_bridge/include extra/ccm_bridge/include @@ -330,7 +320,6 @@ extra/ccm_bridge - ../../cds extra/ccm_bridge/include @@ -342,7 +331,6 @@ - ../../cds . @@ -353,7 +341,6 @@ - ../../cds BOOST_ALL_DYN_LINK diff --git a/src/cql/cql.cpp b/src/cql/cql.cpp index 5af52996b..e7520dbaf 100644 --- a/src/cql/cql.cpp +++ b/src/cql/cql.cpp @@ -15,9 +15,6 @@ */ #include #include -#include -#include -#include #include "cql/cql.hpp" @@ -53,44 +50,20 @@ cql::to_string(const cql_host_distance_enum host_distance) { namespace { bool cql_library_initialized = false; - boost::shared_ptr cql_hp_singleton; } void -cql::cql_initialize(size_t const hazard_pointers_count) { +cql::cql_initialize() { if(cql_library_initialized) return; - + cql_library_initialized = true; - - cds::Initialize(0); - cql_hp_singleton = boost::shared_ptr(new cds::gc::HP(hazard_pointers_count)); } void cql::cql_terminate() { if(!cql_library_initialized) return; - - cql_library_initialized = false; - - cql_hp_singleton.reset(); - cds::Terminate(); -} - -namespace cql { -struct cql_thread_infrastructure_impl_t { -public: - - // libcds thread garbage collector. - cds::gc::HP::thread_gc _thread_gc; -}; -} - -cql::cql_thread_infrastructure_t::cql_thread_infrastructure_t() { - _this = new cql_thread_infrastructure_impl_t(); -} -cql::cql_thread_infrastructure_t::~cql_thread_infrastructure_t() { - delete _this; + cql_library_initialized = false; } diff --git a/src/cql/cql_builder.cpp b/src/cql/cql_builder.cpp index 91eb43e2f..407492f59 100644 --- a/src/cql/cql_builder.cpp +++ b/src/cql/cql_builder.cpp @@ -20,25 +20,24 @@ #include "cql/cql_builder.hpp" #include "cql/internal/cql_util.hpp" - cql::cql_builder_t& cql::cql_builder_t::add_contact_point( const ::boost::asio::ip::address& address) { _contact_points.push_back( cql_endpoint_t(address, DEFAULT_PORT)); - + return *this; } cql::cql_builder_t& cql::cql_builder_t::add_contact_point( - const ::boost::asio::ip::address& address, + const ::boost::asio::ip::address& address, unsigned short port) { _contact_points.push_back( cql_endpoint_t(address, port)); - + return *this; } @@ -47,56 +46,57 @@ cql::cql_builder_t::add_contact_point( const cql_endpoint_t& endpoint) { _contact_points.push_back(endpoint); - + return *this; } -cql::cql_builder_t& +cql::cql_builder_t& cql::cql_builder_t::add_contact_points( - const std::list< ::boost::asio::ip::address>& addresses) + const std::list< ::boost::asio::ip::address>& addresses) { - cql_builder_t& (cql_builder_t::*add_contact)(const ::boost::asio::ip::address&) + cql_builder_t& (cql_builder_t::*add_contact)(const ::boost::asio::ip::address&) = &cql_builder_t::add_contact_point; - + std::for_each(addresses.begin(), addresses.end(), boost::bind(add_contact, this, _1)); - + return *this; } -cql::cql_builder_t& +cql::cql_builder_t& cql::cql_builder_t::add_contact_points( const std::list< ::boost::asio::ip::address>& addresses, - const unsigned short port) + const unsigned short port) { std::for_each(addresses.begin(), addresses.end(), boost::bind(&cql_builder_t::add_contact_point, this, _1, port)); - + return *this; } -cql::cql_builder_t& +cql::cql_builder_t& cql::cql_builder_t::add_contact_points( - const std::list& addresses) + const std::list& addresses) { - cql_builder_t& (cql_builder_t::*add_contact)(const cql_endpoint_t&) + cql_builder_t& (cql_builder_t::*add_contact)(const cql_endpoint_t&) = &cql_builder_t::add_contact_point; - + std::for_each(addresses.begin(), addresses.end(), boost::bind(add_contact, this, _1)); - + return *this; } -boost::shared_ptr -cql::cql_builder_t::build() { +boost::shared_ptr +cql::cql_builder_t::build() +{ return cql_cluster_t::built_from(*this); } cql::cql_builder_t& cql::cql_builder_t::with_credentials( - const std::string& user_name, - const std::string& password) + const std::string& user_name, + const std::string& password) { cql_credentials_t credentials; @@ -106,4 +106,3 @@ cql::cql_builder_t::with_credentials( _credentials = credentials; return *this; } - diff --git a/src/cql/cql_cluster.cpp b/src/cql/cql_cluster.cpp index 86bccdd35..f94a5a5de 100644 --- a/src/cql/cql_cluster.cpp +++ b/src/cql/cql_cluster.cpp @@ -29,16 +29,19 @@ #include "cql/internal/cql_cluster_impl.hpp" -boost::shared_ptr -cql::cql_cluster_t::built_from(const cql_initializer_t& initializer) { - return boost::shared_ptr(new cql::cql_cluster_impl_t( - initializer.contact_points(), - initializer.configuration())); +boost::shared_ptr +cql::cql_cluster_t::built_from( + cql_initializer_t& initializer) +{ + return boost::shared_ptr( + new cql::cql_cluster_impl_t( + initializer.contact_points(), + initializer.configuration())); } -boost::shared_ptr -cql::cql_cluster_t::builder() { +boost::shared_ptr +cql::cql_cluster_t::builder() +{ return boost::shared_ptr( new cql::cql_builder_t()); } - diff --git a/src/cql/cql_host.cpp b/src/cql/cql_host.cpp index a2dcd0f89..f8b71f0f4 100644 --- a/src/cql/cql_host.cpp +++ b/src/cql/cql_host.cpp @@ -31,29 +31,31 @@ cql::cql_host_t::cql_host_t( ::boost::shared_ptr cql::cql_host_t::create( - const cql_endpoint_t& endpoint, + const cql_endpoint_t& endpoint, const boost::shared_ptr& reconnection_policy) { - if(endpoint.is_unspecified()) - throw std::invalid_argument("unspecified IP address."); + // if (endpoint.is_unspecified()) { + // throw std::invalid_argument("unspecified IP address."); + // } - if(!reconnection_policy) + if (!reconnection_policy) { throw std::invalid_argument("reconnection policy cannot be null."); + } return ::boost::shared_ptr( new cql_host_t(endpoint, reconnection_policy)); } -void -cql::cql_host_t::set_location_info( - const std::string& datacenter, +void +cql::cql_host_t::set_location_info( + const std::string& datacenter, const std::string& rack ) { _datacenter = datacenter; _rack = rack; } -bool +bool cql::cql_host_t::is_considerably_up() const { if(is_up()) @@ -63,11 +65,11 @@ cql::cql_host_t::is_considerably_up() const return (_next_up_time <= utc_time); } -bool +bool cql::cql_host_t::set_down() { if (is_considerably_up()) { - boost::posix_time::time_duration delay = + boost::posix_time::time_duration delay = _reconnection_schedule->get_delay(); boost::posix_time::ptime now = utc_now(); @@ -83,16 +85,16 @@ cql::cql_host_t::set_down() return false; } -bool +bool cql::cql_host_t::bring_up() { _reconnection_schedule = _reconnection_policy->new_schedule(); - + if (!_is_up) { _is_up = true; return true; } - + return false; } diff --git a/src/cql/cql_metadata.cpp b/src/cql/cql_metadata.cpp index 89b231d88..c5036ed0d 100644 --- a/src/cql/cql_metadata.cpp +++ b/src/cql/cql_metadata.cpp @@ -23,33 +23,29 @@ #include "cql/internal/cql_cluster_impl.hpp" #include "cql/cql_builder.hpp" #include "cql/internal/cql_hosts.hpp" -#include "cql/lockfree/boost_ip_address_traits.hpp" void cql::cql_metadata_t::get_hosts(std::vector >& collection) const { - _hosts->get_hosts(&collection); + _hosts->get_hosts(collection); } - + boost::shared_ptr cql::cql_metadata_t::get_host(const cql_endpoint_t& endpoint) const { boost::shared_ptr host; - + if(_hosts->try_get(endpoint, &host)) return host; - + return boost::shared_ptr(); } - + void -cql::cql_metadata_t::get_endpoints(std::vector* collection) const { - if(!collection) - throw std::invalid_argument("collection cannot be null."); - +cql::cql_metadata_t::get_endpoints(std::vector& collection) const { _hosts->get_endpoints(collection); } boost::shared_ptr -cql::cql_metadata_t::add_host(const cql_endpoint_t& endpoint) +cql::cql_metadata_t::add_host(const cql_endpoint_t& endpoint) { _hosts->bring_up(endpoint); return get_host(endpoint); @@ -64,7 +60,7 @@ void cql::cql_metadata_t::set_down_host(const cql_endpoint_t& endpoint) { _hosts->set_down(endpoint); } - + void cql::cql_metadata_t::bring_up_host(const cql_endpoint_t& endpoint) { _hosts->bring_up(endpoint); @@ -73,13 +69,13 @@ cql::cql_metadata_t::bring_up_host(const cql_endpoint_t& endpoint) { cql::cql_metadata_t::cql_metadata_t( boost::shared_ptr reconnection_policy) : _reconnection_policy(reconnection_policy), - _hosts(cql_hosts_t::create(reconnection_policy)) + _hosts(cql_hosts_t::create(reconnection_policy)) { } void cql::cql_metadata_t::add_hosts( - const std::list& endpoints) -{ - std::for_each(endpoints.begin(), endpoints.end(), + const std::list& endpoints) +{ + std::for_each(endpoints.begin(), endpoints.end(), boost::bind(&cql_metadata_t::add_host, this, _1)); } diff --git a/src/cql/cql_uuid.cpp b/src/cql/cql_uuid.cpp index 564e80083..c0e30c9c1 100644 --- a/src/cql/cql_uuid.cpp +++ b/src/cql/cql_uuid.cpp @@ -13,18 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include +#include + #include "cql/cql_uuid.hpp" cql::cql_uuid_t cql::cql_uuid_t::create() { - static boost::atomic_ulong id; + static unsigned long id; + static boost::mutex mutex; + + boost::mutex::scoped_lock lock(mutex); return cql::cql_uuid_t(id++); -} +} namespace cql { -bool -operator <(const cql::cql_uuid_t& left, const cql::cql_uuid_t& right) { - return (left._uuid < right._uuid); -} + bool + operator <(const cql::cql_uuid_t& left, const cql::cql_uuid_t& right) { + return (left._uuid < right._uuid); + } } diff --git a/src/cql/internal/cql_control_connection.cpp b/src/cql/internal/cql_control_connection.cpp index 3564ad5b3..859d34c2b 100644 --- a/src/cql/internal/cql_control_connection.cpp +++ b/src/cql/internal/cql_control_connection.cpp @@ -26,16 +26,20 @@ #include "cql/internal/cql_cluster_impl.hpp" #include "cql/exceptions/cql_exception.hpp" +typedef boost::tuple row_t; +typedef std::list row_collection_t; + namespace cql { - -cql_control_connection_t::cql_control_connection_t(cql_cluster_t& cluster, - boost::asio::io_service& io_service, - boost::shared_ptr configuration) - : _cluster(cluster) - , _io_service(io_service) - , _configuration(configuration) - , _timer(io_service) - , _log_callback(_configuration->client_options().log_callback()) + +cql_control_connection_t::cql_control_connection_t( + cql_cluster_t& cluster, + boost::asio::io_service& io_service, + boost::shared_ptr configuration) : + _cluster(cluster), + _io_service(io_service), + _configuration(configuration), + _timer(io_service), + _log_callback(_configuration->client_options().log_callback()) { cql_session_callback_info_t session_callbacks; @@ -43,28 +47,29 @@ cql_control_connection_t::cql_control_connection_t(cql_cluster_t& boost::asio::ssl::context* ssl_context = _configuration->protocol_options() .ssl_context().get(); - + if (ssl_context != 0) { client_factory = client_ssl_functor_t( - _io_service, - const_cast(*ssl_context), - _log_callback); + _io_service, + const_cast(*ssl_context), + _log_callback); } else { client_factory = client_functor_t(_io_service, _log_callback); } - + session_callbacks.set_client_callback(client_factory); //session_callbacks.set_ready_callback(xxx); // TODO(JS) //session_callbacks.set_defunct_callback(xx); // TODO(JS) session_callbacks.set_log_callback(_log_callback); - + boost::scoped_ptr _reconnection_policy_tmp( - new cql_exponential_reconnection_policy_t(boost::posix_time::seconds(2), - boost::posix_time::minutes(5))); - + new cql_exponential_reconnection_policy_t( + boost::posix_time::seconds(2), + boost::posix_time::minutes(5))); + _reconnection_schedule = _reconnection_policy_tmp->new_schedule(); - + _session = boost::shared_ptr( new cql_session_impl_t(session_callbacks, configuration)); } @@ -75,243 +80,263 @@ cql_control_connection_t::init() _session->init(_io_service); setup_control_connection(); } - + void cql_control_connection_t::shutdown(int timeout_ms) { + boost::mutex::scoped_lock lock(_mutex); // NOTE: seems that session does not support timeout? - if(_is_open.exchange(false, boost::memory_order_acq_rel)) { - _timer.cancel(); - boost::static_pointer_cast(_session)->close(); - } + _is_open = false; + _timer.cancel(); + boost::static_pointer_cast(_session)->close(); } - + cql_control_connection_t::~cql_control_connection_t() { try { shutdown(); } catch(...) { - if(_log_callback) + if (_log_callback) { _log_callback(CQL_LOG_ERROR, "Error while shutting down control connection"); + } } } void -cql_control_connection_t::metadata_hosts_event(void* sender, - boost::shared_ptr event) -{// Just a stub (At this point) -} - +cql_control_connection_t::metadata_hosts_event( + void* sender, + boost::shared_ptr event) +{} + void cql_control_connection_t::setup_event_listener() { boost::shared_ptr query_plan = _configuration->policies() .load_balancing_policy() - ->new_query_plan(boost::shared_ptr()); - + ->new_query_plan(boost::shared_ptr()); + cql_stream_t stream; std::list tried_hosts; - + _active_connection = _session->connect(query_plan, &stream, &tried_hosts); } cql_host_t::ip_address_t -cql_control_connection_t::make_ipv4_address_from_bytes(cql::cql_byte_t* data) +cql_control_connection_t::make_ipv4_address_from_bytes( + cql::cql_byte_t* data) { - int digit0 = int(data[0]), - digit1 = int(data[1]), - digit2 = int(data[2]), - digit3 = int(data[3]); - - return cql_host_t::ip_address_t::from_string(boost::lexical_cast(digit0) + "." - + boost::lexical_cast(digit1) + "." - + boost::lexical_cast(digit2) + "." - + boost::lexical_cast(digit3)); + int digit0 = int(data[0]); + int digit1 = int(data[1]); + int digit2 = int(data[2]); + int digit3 = int(data[3]); + + return cql_host_t::ip_address_t::from_string( + boost::lexical_cast(digit0) + "." + + boost::lexical_cast(digit1) + "." + + boost::lexical_cast(digit2) + "." + + boost::lexical_cast(digit3)); } - + void cql_control_connection_t::refresh_node_list_and_token_map() { - if(_log_callback) + if (_log_callback) { _log_callback(CQL_LOG_INFO, "Refreshing node list and token map..."); - - boost::shared_future query_future_result = - boost::static_pointer_cast(_session) - ->query(boost::make_shared(cql_query_t(select_peers_expression()))); - - if(query_future_result.timed_wait(boost::posix_time::seconds(10))) { // THINKOF(JS): do blocking wait? + } + + boost::shared_ptr query(new cql_query_t(select_peers_expression())); + boost::shared_future query_future_result = boost::static_pointer_cast(_session)->query(query); + + if (query_future_result.timed_wait(boost::posix_time::seconds(10))) { // THINKOF(JS): do blocking wait? cql_future_result_t query_result = query_future_result.get(); - - if(query_result.error.is_err()) { - if(_log_callback) _log_callback(CQL_LOG_ERROR, query_result.error.message); + + if (query_result.error.is_err()) { + if (_log_callback) { + _log_callback(CQL_LOG_ERROR, query_result.error.message); + } return; } - + boost::shared_ptr clusters_metadata = _cluster.metadata(); + row_collection_t rows; // (address, data_center, rack, tokens) - std::list > rows; // (address, data_center, rack, tokens) - boost::shared_ptr result = query_result.result; - while(result->next()) - { + while (result->next()) { cql_host_t::ip_address_t peer_address; bool output = false; - - if(!(result->is_null("rpc_address", output)) && !output) - { + + if (!(result->is_null("rpc_address", output)) && !output) { cql::cql_byte_t* data = NULL; cql::cql_int_t size = 0; result->get_data("rpc_address", &data, size); - if(size == 4) + if (size == 4) { peer_address = make_ipv4_address_from_bytes(data); + } } - if(peer_address.is_unspecified()) - { - if(!(result->is_null("peer", output)) && !output) - { + + if (peer_address == ::boost::asio::ip::address()) { + if (!(result->is_null("peer", output)) && !output) { cql::cql_byte_t* data = NULL; cql::cql_int_t size = 0; result->get_data("peer", &data, size); - if(size == 4) + if (size == 4) { peer_address = make_ipv4_address_from_bytes(data); + } } - else if(_log_callback) + else if (_log_callback) { _log_callback(CQL_LOG_ERROR, "No rpc_address found for host in peers system table."); + } } - if(!(peer_address.is_unspecified())) - { + else { std::string data_center, rack, tokens; result->get_string("data_center", data_center); result->get_string("rack", rack); result->get_string("tokens", tokens); rows.push_back(boost::make_tuple(peer_address, data_center, rack, tokens)); } - + } // TODO(JS) make 'select_local" query here. - + // Now we will determine the port number, assuming there is one (common for whole cluster). // Otherwise, we use default 9042. int port_number; { std::vector current_endpoints; - clusters_metadata->get_endpoints(¤t_endpoints); + clusters_metadata->get_endpoints(current_endpoints); port_number = current_endpoints.empty() ? cql_builder_t::DEFAULT_PORT : current_endpoints[0].port(); } - - for(auto row : rows) - { + + for (row_collection_t::iterator riter = rows.begin(); riter != rows.end(); ++riter) { + row_t row = *riter; cql_host_t::ip_address_t host_address = row.get<0>(); - std::string data_center = row.get<1>(), - rack = row.get<2>(), - tokens = row.get<3>(); - + std::string data_center = row.get<1>(); + std::string rack = row.get<2>(); + std::string tokens = row.get<3>(); + cql_endpoint_t peer_endpoint(host_address, port_number); boost::shared_ptr host = clusters_metadata->get_host(peer_endpoint); - if(!host) host = clusters_metadata->add_host(peer_endpoint); - + if (!host) { + host = clusters_metadata->add_host(peer_endpoint); + } + host->set_location_info(data_center, rack); } - { + + //{ // Now we will remove dead hosts. std::map hosts_addresses_map; - for(auto row : rows) - hosts_addresses_map[row.get<0>()] = true; - + for (row_collection_t::iterator riter = rows.begin(); riter != rows.end(); ++riter) { + hosts_addresses_map[riter->get<0>()] = true; + } + std::vector > clusters_hosts; clusters_metadata->get_hosts(clusters_hosts); - - for(auto host : clusters_hosts) - { - if(hosts_addresses_map.find(host->address()) == hosts_addresses_map.end() - && host->address() != _active_connection->endpoint().address()) - clusters_metadata->remove_host(host->endpoint()); + + for (std::vector >::iterator hiter = clusters_hosts.begin(); hiter != clusters_hosts.end(); ++hiter) { + if (hosts_addresses_map.find((*hiter)->address()) == hosts_addresses_map.end() + && (*hiter)->address() != _active_connection->endpoint().address()) + { + clusters_metadata->remove_host((*hiter)->endpoint()); + } } - } + //} //TODO(JS) : clusters_metadata->rebuildTokenMap(...) - - if(_log_callback) _log_callback(CQL_LOG_INFO, "NodeList and TokenMap successfully refreshed."); + + if (_log_callback) { + _log_callback(CQL_LOG_INFO, "NodeList and TokenMap successfully refreshed."); + } } else { - if(_log_callback) + if (_log_callback) { _log_callback(CQL_LOG_ERROR, "Query timed out"); + } } } - + void -cql_control_connection_t::conn_cassandra_event(void* sender, - boost::shared_ptr event) -{// Just a stub (at this point) +cql_control_connection_t::conn_cassandra_event( + void* sender, + boost::shared_ptr event) +{ +// Just a stub (at this point) } - + bool cql_control_connection_t::refresh_hosts() { boost::mutex::scoped_lock lock(_mutex); try { - if(_is_open) { + if (_is_open) { refresh_node_list_and_token_map(); return true; } else return false; } catch(cql_exception& ex) { - if(_log_callback) + if (_log_callback) { _log_callback(CQL_LOG_ERROR, ex.what()); + } return false; } } - + void -cql_control_connection_t::setup_control_connection(bool refresh_only) +cql_control_connection_t::setup_control_connection( + bool refresh_only) { boost::mutex::scoped_lock lock(_mutex); - - if(_log_callback) _log_callback(CQL_LOG_INFO, + + if (_log_callback) { + _log_callback( + CQL_LOG_INFO, refresh_only ? "Refreshing control connection..." - : "Setting up control connection..."); - + : "Setting up control connection..."); + } + try { _timer.cancel(); - - if(!refresh_only) setup_event_listener(); + + if (!refresh_only) { + setup_event_listener(); + } refresh_node_list_and_token_map(); - + _is_open = true; - if(_log_callback) _log_callback(CQL_LOG_INFO, + if (_log_callback) { + _log_callback( + CQL_LOG_INFO, refresh_only ? "Done refreshing control connection." - : "Done setting up control connection."); + : "Done setting up control connection."); + } } catch (cql_exception& ex) { _is_open = false; - + _timer.expires_from_now(_reconnection_schedule->get_delay()); _timer.async_wait(boost::bind( - &cql_control_connection_t::reconnection_callback, this)); - - if(_log_callback) + &cql_control_connection_t::reconnection_callback, this)); + + if (_log_callback) { _log_callback(CQL_LOG_ERROR, ex.what()); + } } } void cql_control_connection_t::reconnection_callback() { - try - { + try { setup_control_connection(); } - catch (cql_exception& ex) - { - if(_log_callback) + catch (cql_exception& ex) { + if (_log_callback) { _log_callback(CQL_LOG_ERROR, ex.what()); + } } } - + } // namespace cql diff --git a/src/cql/internal/cql_hosts.cpp b/src/cql/internal/cql_hosts.cpp index fc0c3232d..8845fb5be 100644 --- a/src/cql/internal/cql_hosts.cpp +++ b/src/cql/internal/cql_hosts.cpp @@ -19,62 +19,68 @@ #include "cql/internal/cql_hosts.hpp" -::boost::shared_ptr -cql::cql_hosts_t::create( - const boost::shared_ptr& reconnection_policy, - const size_t expected_load) +boost::shared_ptr +cql::cql_hosts_t::create( + const boost::shared_ptr& reconnection_policy) { - if(!reconnection_policy) + if(!reconnection_policy) { throw std::invalid_argument("reconnection_policy cannot be null."); + } - return ::boost::shared_ptr(new - cql::cql_hosts_t(reconnection_policy, expected_load)); + return ::boost::shared_ptr(new cql::cql_hosts_t(reconnection_policy)); } void -cql::cql_hosts_t::get_hosts(std::vector* empty_vector) { - if(!empty_vector) - throw std::invalid_argument("empty_vector cannot be null."); +cql::cql_hosts_t::get_hosts( + std::vector& empty_vector) +{ + boost::mutex::scoped_lock lock(_mutex); - _hosts.get_values(std::back_inserter(*empty_vector)); + for (hosts_map_t::const_iterator it = _hosts.begin(); it != _hosts.end(); ++it) { + empty_vector.push_back(it->second); + } } -bool -cql::cql_hosts_t::bring_up(const cql::cql_endpoint_t& endpoint) +bool +cql::cql_hosts_t::bring_up( + const cql::cql_endpoint_t& endpoint) { - boost::shared_ptr new_host = - cql_host_t::create(endpoint, _reconnection_policy); - - _hosts.try_add(endpoint, new_host); + boost::mutex::scoped_lock lock(_mutex); - boost::shared_ptr host; - if(_hosts.try_get(endpoint, &host)) - return host->bring_up(); - else - return false; + boost::shared_ptr new_host = cql_host_t::create(endpoint, _reconnection_policy); + _hosts[endpoint] = new_host; + return new_host->bring_up(); } -bool -cql::cql_hosts_t::set_down(const cql::cql_endpoint_t& endpoint) +bool +cql::cql_hosts_t::set_down( + const cql::cql_endpoint_t& endpoint) { + boost::mutex::scoped_lock lock(_mutex); boost::shared_ptr host; - if (_hosts.try_get(endpoint, &host)) + if (try_get(endpoint, &host)) { return host->set_down(); - else + } + else { return false; + } } -bool -cql::cql_hosts_t::try_remove(const cql::cql_endpoint_t& endpoint) +bool +cql::cql_hosts_t::try_remove( + const cql::cql_endpoint_t& endpoint) { - return _hosts.try_erase(endpoint); + boost::mutex::scoped_lock lock(_mutex); + return _hosts.erase(endpoint); } void -cql::cql_hosts_t::get_endpoints(std::vector* empty_vector) { - if(!empty_vector) - throw std::invalid_argument("empty_vector cannot be null."); - - _hosts.get_keys(std::back_inserter(*empty_vector)); +cql::cql_hosts_t::get_endpoints( + std::vector& empty_vector) +{ + boost::mutex::scoped_lock lock(_mutex); + for (hosts_map_t::const_iterator it = _hosts.begin(); it != _hosts.end(); ++it) { + empty_vector.push_back(it->first); + } } diff --git a/src/cql/internal/cql_rand.cpp b/src/cql/internal/cql_rand.cpp index b24c7f918..805882bbd 100644 --- a/src/cql/internal/cql_rand.cpp +++ b/src/cql/internal/cql_rand.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ #include -#include #include #include diff --git a/src/cql/internal/cql_session_impl.cpp b/src/cql/internal/cql_session_impl.cpp index 25edf8d82..b8bc6ae8a 100644 --- a/src/cql/internal/cql_session_impl.cpp +++ b/src/cql/internal/cql_session_impl.cpp @@ -30,71 +30,50 @@ cql::cql_session_impl_t::cql_session_impl_t( - const cql_session_callback_info_t& callbacks, - boost::shared_ptr configuration - ) : + const cql_session_callback_info_t& callbacks, + boost::shared_ptr configuration) : _client_callback(callbacks.client_callback()), _ready_callback(callbacks.ready_callback()), _defunct_callback(callbacks.defunct_callback()), _log_callback(callbacks.log_callback()), _uuid(cql_uuid_t::create()), _configuration(configuration) -{ } +{} -cql::cql_session_impl_t::~cql_session_impl_t() { } +cql::cql_session_impl_t::~cql_session_impl_t() +{} -void -cql::cql_session_impl_t::init(boost::asio::io_service& io_service) +void +cql::cql_session_impl_t::init( + boost::asio::io_service& io_service) { _trashcan = boost::shared_ptr( new cql_trashcan_t(io_service, *this)); - + boost::shared_ptr query_plan = _configuration->policies() - .load_balancing_policy() - ->new_query_plan(boost::shared_ptr()); - + .load_balancing_policy() + ->new_query_plan(boost::shared_ptr()); + cql_stream_t stream; std::list tried_hosts; - + boost::shared_ptr conn = - connect(query_plan, &stream, &tried_hosts); + connect(query_plan, &stream, &tried_hosts); conn->release_stream(stream); } - -void -cql::cql_session_impl_t::free_connections( - cql_connections_collection_t& connections, - const std::list& connections_to_remove) -{ - for(std::list::const_iterator it = connections_to_remove.begin(); - it != connections_to_remove.end(); ++it) - { - cql_uuid_t conn_id = *it; - boost::shared_ptr conn; - - do { - if(!connections.try_get(conn_id, &conn)) - break; - } - while(!connections.try_erase(conn_id, &conn)); - - free_connection(conn); - } -} -void +void cql::cql_session_impl_t::free_connection( - boost::shared_ptr connection) + boost::shared_ptr connection) { - if(!connection) + if (!connection) { return; - - cql_endpoint_t connection_endpoint = connection->endpoint(); + } connection->close(); - - boost::shared_ptr counter; - if(_connection_counters.try_get(connection_endpoint, &counter)) { - (*counter)--; + + connections_counter_t::iterator it = _connection_counters.find(connection->endpoint()); + if (it != _connection_counters.end()) { + (*it->second)--; } } @@ -102,12 +81,12 @@ long cql::cql_session_impl_t::get_max_connections_number( const boost::shared_ptr& host) { - cql_host_distance_enum distance = host->distance(_configuration->policies()); - + cql_host_distance_enum distance = host->distance(_configuration->policies()); + long max_connections_per_host = _configuration ->pooling_options() - .max_connection_per_host(distance); - + .max_connection_per_host(distance); + return max_connections_per_host; } @@ -115,21 +94,23 @@ bool cql::cql_session_impl_t::increase_connection_counter( const boost::shared_ptr& host) { - cql_endpoint_t endpoint = host->endpoint(); - long max_connections = get_max_connections_number(host); - - boost::shared_ptr counter(new connection_counter_t(1)); - if(!_connection_counters.try_add(endpoint, counter)) { - bool get_result = _connection_counters.try_get(endpoint, &counter); - assert(get_result == true); - - (*counter)++; - if((long)(*counter) > max_connections) { - (*counter)--; + boost::mutex::scoped_lock lock(_mutex); + cql_endpoint_t endpoint = host->endpoint(); + long max_connections = get_max_connections_number(host); + + connections_counter_t::iterator it = _connection_counters.find(endpoint); + if (it == _connection_counters.end()) { + boost::shared_ptr counter(new connection_counter_t(1)); + _connection_counters[endpoint] = counter; + } + else { + (*it->second)++; + if ((long)(*it->second) > max_connections) { + (*it->second)--; return false; } } - + return true; } @@ -138,166 +119,159 @@ bool cql::cql_session_impl_t::decrease_connection_counter( const boost::shared_ptr& host) { - boost::shared_ptr counter; - - if(_connection_counters.try_get(host->endpoint(), &counter)) { - (*counter)--; + boost::mutex::scoped_lock lock(_mutex); + connections_counter_t::iterator it = _connection_counters.find(host->endpoint()); + + if (it != _connection_counters.end()) { + (*it->second)--; return true; } - + return false; } boost::shared_ptr cql::cql_session_impl_t::allocate_connection( - const boost::shared_ptr& host) + const boost::shared_ptr& host) { - if(!increase_connection_counter(host)) + if (!increase_connection_counter(host)) { throw cql_too_many_connections_per_host_exception(); - + } + boost::shared_ptr > promise( new cql_promise_t()); - + boost::shared_ptr connection(_client_callback()); connection->set_credentials(_configuration->credentials()); connection->connect(host->endpoint(), boost::bind(&cql_session_impl_t::connect_callback, this, promise, ::_1), boost::bind(&cql_session_impl_t::connect_errback, this, promise, ::_1, ::_2)); - - + boost::shared_future shared_future = promise->shared_future(); shared_future.wait(); - - if(shared_future.get().error.is_err()) { + + if (shared_future.get().error.is_err()) { decrease_connection_counter(host); throw cql_exception("cannot connect to host: " + host->endpoint().to_string()); } - + return connection; } - -cql::cql_connections_collection_t* + +cql::cql_session_impl_t::cql_connections_collection_t* cql::cql_session_impl_t::add_to_connection_pool( - const cql_endpoint_t& host_address) + cql_endpoint_t& endpoint) { - cql_connections_collection_t* result = NULL; - cql_connections_collection_t* empty_collection = NULL; - - while(!_connection_pool.try_get(host_address, &result)) { - if(!empty_collection) { - empty_collection = new cql_connections_collection_t(); - } - - _connection_pool.try_add(host_address, empty_collection); + boost::mutex::scoped_lock lock(_mutex); + connection_pool_t::iterator it = _connection_pool.find(endpoint); + if (it == _connection_pool.end()) { + it = _connection_pool.insert(endpoint, new cql_connections_collection_t()).first; } - - if(empty_collection && (result != empty_collection)) - delete empty_collection; - - return result; + + return it->second; } -void +void cql::cql_session_impl_t::try_remove_connection( cql_connections_collection_t* const connections, - const cql_uuid_t& connection_id) + const cql_uuid_t& connection_id) { // TODO: How we can guarantee that any other thread is not using // this connection object ? - - boost::shared_ptr conn; - - if(connections->try_erase(connection_id, &conn)) { - free_connection(conn); + + cql_connections_collection_t::iterator iter = connections->find(connection_id); + if (iter != connections->end()) { + free_connection(iter->second); + connections->erase(iter); } } boost::shared_ptr cql::cql_session_impl_t::try_find_free_stream( - boost::shared_ptr const& host, + boost::shared_ptr const& host, cql_connections_collection_t* const connections, cql_stream_t* stream) { - const cql_pooling_options_t& pooling_options = _configuration->pooling_options(); - cql_host_distance_enum distance = host->distance(_configuration->policies()); - - for(cql_connections_collection_t::iterator kv = connections->begin(); - kv != connections->end(); ++kv) - { + const cql_pooling_options_t& pooling_options = _configuration->pooling_options(); + cql_host_distance_enum distance = host->distance(_configuration->policies()); + + for (cql_connections_collection_t::iterator kv = connections->begin(); + kv != connections->end(); ++kv) + { cql_uuid_t conn_id = kv->first; boost::shared_ptr conn = kv->second; if (!conn->is_healthy()) { try_remove_connection(connections, conn_id); - } + } else if (!conn->is_busy(pooling_options.max_simultaneous_requests_per_connection_treshold(distance))) { *stream = conn->acquire_stream(); - if(!stream->is_invalid()) + if (!stream->is_invalid()) { return conn; - } + } + } else if ((long)connections->size() > pooling_options.core_connections_per_host(distance)) { if (conn->is_free(pooling_options.min_simultaneous_requests_per_connection_treshold(distance))) { - if(connections->try_erase(conn_id)) - _trashcan->put(conn); + _trashcan->put(conn); + connections->erase(kv); } } } - + *stream = cql_stream_t(); return boost::shared_ptr(); } boost::shared_ptr cql::cql_session_impl_t::connect( - boost::shared_ptr query_plan, - cql_stream_t* stream, - std::list* tried_hosts) + boost::shared_ptr query_plan, + cql_stream_t* stream, + std::list* tried_hosts) { assert(stream != NULL); assert(tried_hosts != NULL); - while (boost::shared_ptr host = query_plan->next_host_to_query()) - { - if (!host->is_considerably_up()) + while (boost::shared_ptr host = query_plan->next_host_to_query()) { + if (!host->is_considerably_up()) { continue; + } - const cql_endpoint_t host_address = host->endpoint(); - + cql_endpoint_t host_address = host->endpoint(); tried_hosts->push_back(host_address); - cql_connections_collection_t* connections = add_to_connection_pool(host_address); - - boost::shared_ptr conn = - try_find_free_stream(host, connections, stream); - if(conn) + + boost::shared_ptr conn = try_find_free_stream(host, connections, stream); + if (conn) { return conn; - + } + conn = _trashcan->recycle(host_address); if (conn && !conn->is_healthy()) { free_connection(conn); conn = boost::shared_ptr(); } - - if(!conn) { - if( !(conn = allocate_connection(host)) ) + + if (!conn) { + if (!(conn = allocate_connection(host))) { continue; + } } - + *stream = conn->acquire_stream(); - connections->try_add(conn->id(), conn); + (*connections)[conn->id()] = conn; return conn; } - + throw cql_exception("no host is available according to load balancing policy."); } cql::cql_stream_t cql::cql_session_impl_t::execute_operation( - const boost::shared_ptr& query, - cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback, - exec_query_method_t method) + const boost::shared_ptr& query, + cql_connection_t::cql_message_callback_t callback, + cql_connection_t::cql_message_errback_t errback, + exec_query_method_t method) { cql_stream_t stream; boost::shared_ptr conn = get_connection(query, &stream); @@ -306,7 +280,7 @@ cql::cql_session_impl_t::execute_operation( query->set_stream(stream); return ((*conn).*method)(query, callback, errback); } - + return cql_stream_t(); } @@ -314,7 +288,7 @@ cql::cql_stream_t cql::cql_session_impl_t::query( const boost::shared_ptr& query, cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback) + cql_connection_t::cql_message_errback_t errback) { return execute_operation(query, callback, errback, &cql_connection_t::query); } @@ -323,7 +297,7 @@ cql::cql_stream_t cql::cql_session_impl_t::prepare( const boost::shared_ptr& query, cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback) + cql_connection_t::cql_message_errback_t errback) { return execute_operation(query, callback, errback, &cql_connection_t::prepare); } @@ -332,24 +306,19 @@ cql::cql_stream_t cql::cql_session_impl_t::execute( const boost::shared_ptr& message, cql_connection_t::cql_message_callback_t callback, - cql_connection_t::cql_message_errback_t errback) + cql_connection_t::cql_message_errback_t errback) { cql_stream_t stream; - boost::shared_ptr conn = + boost::shared_ptr conn = get_connection(boost::shared_ptr(), &stream); assert(!"Not implemented"); - - /*if (conn) { - - return conn->execute(message, callback, errback); - }*/ - return cql_stream_t(); } boost::shared_future -cql::cql_session_impl_t::query(const boost::shared_ptr& query) +cql::cql_session_impl_t::query( + const boost::shared_ptr& query) { cql_stream_t stream; boost::shared_ptr conn = get_connection(query, &stream); @@ -359,19 +328,20 @@ cql::cql_session_impl_t::query(const boost::shared_ptr& query) return conn->query(query); } - boost::promise promise; + boost::promise promise; boost::shared_future shared_future(promise.get_future()); cql_future_result_t future_result; future_result.error.library = true; future_result.error.message = "could not obtain viable client from the pool."; promise.set_value(future_result); - + return shared_future; } boost::shared_future -cql::cql_session_impl_t::prepare(const boost::shared_ptr& query) { +cql::cql_session_impl_t::prepare( + const boost::shared_ptr& query) { cql_stream_t stream; boost::shared_ptr conn = get_connection(query, &stream); @@ -380,24 +350,24 @@ cql::cql_session_impl_t::prepare(const boost::shared_ptr& query) { return conn->query(query); } - boost::promise promise; + boost::promise promise; boost::shared_future shared_future(promise.get_future()); cql_future_result_t future_result; future_result.error.library = true; future_result.error.message = "could not obtain viable client from the pool."; promise.set_value(future_result); - + return shared_future; } boost::shared_future cql::cql_session_impl_t::execute( - const boost::shared_ptr& message) + const boost::shared_ptr& message) { cql_stream_t stream; boost::shared_ptr conn = get_connection(boost::shared_ptr(), &stream); - + assert(0); // TODO: Not implemented - change event to class and pass stream to execute @@ -416,32 +386,30 @@ cql::cql_session_impl_t::execute( } void -cql::cql_session_impl_t::close() +cql::cql_session_impl_t::close() { - if(_trashcan) { - _trashcan->remove_all(); - _trashcan = boost::shared_ptr(); - } - - for(cql_connection_pool_t::iterator host_it = _connection_pool.begin(); - host_it != _connection_pool.end(); ++host_it) + boost::mutex::scoped_lock lock(_mutex); + + for (connection_pool_t::iterator host_it = _connection_pool.begin(); + host_it != _connection_pool.end(); + ++host_it) { cql_connections_collection_t* connections = host_it->second; - if(!_connection_pool.try_erase(host_it->first)) - continue; - - for(cql_connections_collection_t::iterator conn_it = connections->begin(); - conn_it != connections->end(); ++conn_it) + for (cql_connections_collection_t::iterator conn_it = connections->begin(); + conn_it != connections->end(); + ++conn_it) { - boost::shared_ptr conn; - if(connections->try_erase(conn_it->first, &conn)) - free_connection(conn); + free_connection(conn_it->second); } - - delete connections; + connections->clear(); } - - log(0, "size of session::_connection_poll is " + _connection_pool.clear(); + + if (_trashcan) { + _trashcan = boost::shared_ptr(); + } + + log(0, "size of session::_connection_poll is " + boost::lexical_cast(_connection_pool.size())); } @@ -457,7 +425,7 @@ cql::cql_session_impl_t::log( void cql::cql_session_impl_t::connect_callback( boost::shared_ptr > promise, - cql_connection_t& client) + cql_connection_t& client) { promise->set_value(cql_future_connection_t(&client)); if (_ready_callback) { @@ -468,12 +436,12 @@ cql::cql_session_impl_t::connect_callback( void cql::cql_session_impl_t::connect_errback( boost::shared_ptr > promise, - cql_connection_t& connection, - const cql_error_t& error) + cql_connection_t& connection, + const cql_error_t& error) { // when connection breaks this will be called two times // one for async read, and one for asyn write requests - + promise->set_value(cql_future_connection_t(&connection, error)); if (_connect_errback) { @@ -483,14 +451,14 @@ cql::cql_session_impl_t::connect_errback( boost::shared_ptr cql::cql_session_impl_t::get_connection( - const boost::shared_ptr& query, - cql_stream_t* stream) + const boost::shared_ptr& query, + cql_stream_t* stream) { boost::shared_ptr query_plan = _configuration - ->policies() - .load_balancing_policy() - ->new_query_plan(query); - + ->policies() + .load_balancing_policy() + ->new_query_plan(query); + std::list tried_hosts; return connect(query_plan, stream, &tried_hosts); } diff --git a/src/cql/internal/cql_trashcan.cpp b/src/cql/internal/cql_trashcan.cpp index 343a1a266..130b8984f 100644 --- a/src/cql/internal/cql_trashcan.cpp +++ b/src/cql/internal/cql_trashcan.cpp @@ -20,30 +20,23 @@ #include "cql/internal/cql_trashcan.hpp" #include "cql/internal/cql_session_impl.hpp" -cql::cql_trashcan_t::~cql_trashcan_t() { } - void -cql::cql_trashcan_t::put(const boost::shared_ptr& connection) { +cql::cql_trashcan_t::put( + const boost::shared_ptr& connection) +{ + boost::mutex::scoped_lock lock(_mutex); cql_endpoint_t endpoint = connection->endpoint(); - - cql_connections_collection_t* conn = NULL; - cql_connections_collection_t* result = NULL; - - while(!_trashcan.try_get(endpoint, &result)) { - if(!conn) { - conn = new cql_connections_collection_t(); - } - - _trashcan.try_add(endpoint, conn); - } - - if(conn && (result != conn)) - delete conn; - - if(result->try_add(connection->id(), connection)) { - _timer.expires_from_now(timer_expires_time()); - _timer.async_wait(boost::bind(&cql_trashcan_t::timeout, this, _1)); + + connection_pool_t::iterator it = _trashcan.find(endpoint); + if (it == _trashcan.end()) { + it = _trashcan.insert(endpoint, new cql_connections_collection_t()).first; } + + (*it->second)[connection->id()] = connection; + + // TODO XXX WTF + // _timer.expires_from_now(timer_expires_time()); + // _timer.async_wait(boost::bind(&cql_trashcan_t::timeout, this, _1)); } boost::posix_time::time_duration @@ -52,84 +45,50 @@ cql::cql_trashcan_t::timer_expires_time() const { } boost::shared_ptr -cql::cql_trashcan_t::recycle(const cql_endpoint_t& endpoint) +cql::cql_trashcan_t::recycle( + const cql_endpoint_t& endpoint) { - cql_connections_collection_t* connectons; - - if(!_trashcan.try_get(endpoint, &connectons)) - return boost::shared_ptr(); - - boost::shared_ptr conn; - - for(cql_connections_collection_t::iterator it = connectons->begin(); - it != connectons->end(); ++it) - { - if(connectons->try_erase(it->first, &conn)) - return conn; - } - - return boost::shared_ptr(); -} + boost::mutex::scoped_lock lock(_mutex); -void -cql::cql_trashcan_t::cleanup( - const cql_uuid_t& connection_id, - cql_connections_collection_t* const connections) -{ - boost::shared_ptr conn; - - if(connections->try_erase(connection_id, &conn)) { - if(conn->is_empty()) { - _session.free_connection(conn); - } - else { - connections->try_add(connection_id, conn); - } + connection_pool_t::iterator it = _trashcan.find(endpoint); + if (it == _trashcan.end()) { + return boost::shared_ptr(); } -} -void -cql::cql_trashcan_t::cleanup() { - for(cql_connection_pool_t::iterator host_it = _trashcan.begin(); - host_it != _trashcan.end(); ++host_it) + cql_connections_collection_t* connections = it->second; + for (cql_connections_collection_t::iterator it = connections->begin(); + it != connections->end(); + ++it) { - cql_connections_collection_t* connections = host_it->second; - if(!_trashcan.try_erase(host_it->first)) - continue; - - for(cql_connections_collection_t::iterator conn_it = connections->begin(); - conn_it != connections->end(); ++conn_it) - { - cleanup(/* connection id: */ conn_it->first, - /* all connections: */ connections); - } - - delete connections; + boost::shared_ptr conn = it->second; + connections->erase(it); + return conn; } + + return boost::shared_ptr(); } void cql::cql_trashcan_t::timeout(const boost::system::error_code& error) { - if(!error) - cleanup(); + if (!error) { + // cleanup(); + } } void cql::cql_trashcan_t::remove_all() { + boost::mutex::scoped_lock lock(_mutex); _timer.cancel(); - - for(cql_connection_pool_t::iterator host_it = _trashcan.begin(); - host_it != _trashcan.end(); ++host_it) + + for (connection_pool_t::iterator host_it = _trashcan.begin(); + host_it != _trashcan.end(); ++host_it) { - cql_connections_collection_t* connections = host_it->second; - if(!_trashcan.try_erase(host_it->first)) - continue; - - for(cql_connections_collection_t::iterator conn_it = connections->begin(); - conn_it != connections->end(); ++conn_it) + for (cql_connections_collection_t::iterator conn_it = host_it->second->begin(); + conn_it != host_it->second->end(); ++conn_it) { - if(connections->try_erase(conn_it->first)) - _session.free_connection(conn_it->second); + _session.free_connection(conn_it->second); + host_it->second->erase(conn_it); } } + _trashcan.clear(); } diff --git a/src/cql/internal/cql_util.cpp b/src/cql/internal/cql_util.cpp index da65c3956..c845e4766 100644 --- a/src/cql/internal/cql_util.cpp +++ b/src/cql/internal/cql_util.cpp @@ -18,10 +18,10 @@ #include "cql/internal/cql_util.hpp" -char* +char* cql::safe_strncpy(char* dest, const char* src, const size_t count) { assert(count > 0); - + strncpy(dest, src, count - 1); // null terminate destination dest[count - 1] = '\0'; @@ -29,34 +29,24 @@ cql::safe_strncpy(char* dest, const char* src, const size_t count) { return dest; } -bool +bool cql::to_ipaddr(const std::string& str, boost::asio::ip::address* const result) { boost::system::error_code err; - + boost::asio::ip::address tmp = boost::asio::ip::address::from_string(str, err); if(err) return false; - + if(result) *result = tmp; - + return true; } -boost::posix_time::ptime +boost::posix_time::ptime cql::utc_now() { return boost::posix_time::microsec_clock::universal_time(); } - -bool -cql::try_acquire_lock(const boost::shared_ptr& lock) { - bool expected = false; - bool changed = lock->compare_exchange_strong(expected, true, - boost::memory_order_seq_cst, - boost::memory_order_seq_cst); - - return (true == changed); -} diff --git a/src/cql/policies/cql_round_rubin_policy.cpp b/src/cql/policies/cql_round_rubin_policy.cpp index e587026ae..8abe2acfb 100644 --- a/src/cql/policies/cql_round_rubin_policy.cpp +++ b/src/cql/policies/cql_round_rubin_policy.cpp @@ -16,32 +16,35 @@ #include #include -#include "cql/policies/cql_round_robin_policy.hpp" #include "cql/cql_host.hpp" #include "cql/cql_cluster.hpp" #include "cql/cql_metadata.hpp" +#include "cql/internal/cql_rand.hpp" + +#include "cql/policies/cql_round_robin_policy.hpp" cql::cql_round_robin_query_plan_t::cql_round_robin_query_plan_t( - const cql_cluster_t* cluster, + const cql_cluster_t* cluster, unsigned index) { - cluster->metadata() - ->get_hosts(_hosts); - + boost::mutex::scoped_lock lock(_mutex); + cluster->metadata()->get_hosts(_hosts); _index = index; _current = 0; } boost::shared_ptr -cql::cql_round_robin_query_plan_t::next_host_to_query() { - - while(_current < _hosts.size()) { +cql::cql_round_robin_query_plan_t::next_host_to_query() +{ + boost::mutex::scoped_lock lock(_mutex); + while (_current < _hosts.size()) { unsigned host_to_try = (_index + _current) % _hosts.size(); _current++; boost::shared_ptr host = _hosts[host_to_try]; - if(host->is_considerably_up()) + if (host->is_considerably_up()) { return host; + } } return boost::shared_ptr(); @@ -50,19 +53,23 @@ cql::cql_round_robin_query_plan_t::next_host_to_query() { void cql::cql_round_robin_policy_t::init(cql_cluster_t* cluster) { + boost::mutex::scoped_lock lock(_mutex); _cluster = cluster; - _index = (unsigned)cql_rand(); + _index = (unsigned) cql_rand(); } -cql::cql_host_distance_enum -cql::cql_round_robin_policy_t::distance(const cql::cql_host_t& host) { +cql::cql_host_distance_enum +cql::cql_round_robin_policy_t::distance( + const cql::cql_host_t& host) +{ return cql::CQL_HOST_DISTANCE_LOCAL; } -boost::shared_ptr +boost::shared_ptr cql::cql_round_robin_policy_t::new_query_plan( const boost::shared_ptr&) { + boost::mutex::scoped_lock lock(_mutex); _index++; return boost::shared_ptr( diff --git a/test/libcds_demo/CMakeLists.txt b/test/libcds_demo/CMakeLists.txt deleted file mode 100644 index 0e805782c..000000000 --- a/test/libcds_demo/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -#------------------- -# Demo -#------------------- -cmake_minimum_required(VERSION 2.8.11) - -set(LIBCDS_DEMO libcds_demo) -project(${LIBCDS_DEMO} C CXX) - -file(GLOB LIBCDS_DEMO_SRC_FILES *.cpp *.hpp) -add_executable(${LIBCDS_DEMO} ${LIBCDS_DEMO_SRC_FILES}) - -# change -std=c++03 into -std=c++0x for linux - -set(DEFAULT_COMPILER_FLAGS ${PROJECT_COMPILER_FLAGS}) -string(REPLACE "-std=c++03" "-std=c++0x" CHANGED_COMPILER_FLAGS ${DEFAULT_COMPILER_FLAGS}) -set(PROJECT_COMPILER_FLAGS ${CHANGED_COMPILER_FLAGS}) - -set_property( - TARGET ${LIBCDS_DEMO} - APPEND PROPERTY COMPILE_FLAGS "${PROJECT_COMPILER_FLAGS}") - -target_include_directories( ${LIBCDS_DEMO} PUBLIC ${INCLUDES}) -target_link_libraries(${LIBCDS_DEMO} ${LIBS}) diff --git a/test/libcds_demo/lockfree_hash_map.hpp b/test/libcds_demo/lockfree_hash_map.hpp deleted file mode 100644 index 4f3462b6b..000000000 --- a/test/libcds_demo/lockfree_hash_map.hpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * File: lockfree_hash_map.hpp - * Author: mc - * - * Created on September 18, 2013, 1:20 PM - */ - -#ifndef LOCKFREE_HASH_MAP_HPP_ -#define LOCKFREE_HASH_MAP_HPP_ - -// -// REQUIRES NEW C++11 STANDARD -// -#include -#include -#include -#include - -#include -#include -#include - -namespace cql { - template - struct lockfree_hash_map_traits_t - : public cds::container::split_list::type_traits - { - - typedef cds::container::michael_list_tag ordered_list ; // what type of ordered list we want to use - typedef std::hash hash ; // hash functor for the key stored in split-list map - - // Type traits for our MichaelList class - struct ordered_list_traits: public cds::container::michael_list::type_traits { - typedef std::less less; // comparer that specifies order of list nodes - }; - }; - - template - class lockfree_hash_map_t { - public: - typedef - cds::container::SplitListMap > - base_hash_map; - - private: - - // Functor copies value associated with given key - // in hash_map to storage pointed by param storage. - struct copy_value_functor_t { - inline - copy_value_functor_t(TValue* storage) - : _storage(storage) - { - assert(storage != NULL); - }; - - inline void - operator ()(std::pair const& pair) { - *_storage = pair.second; - } - - inline void - operator ()(bool is_new, std::pair const& pair) { - // is_new is true when this function is called for newly - // inserted item - *_storage = pair.second; - } - - private: - TValue* const _storage; - }; - - public: - - lockfree_hash_map_t() - : _map() { } - - lockfree_hash_map_t(size_t expected_items_count, size_t load_factor = 1) - : _map(expected_items_count, load_factor) { } - - inline size_t - size() const { - return _map.size(); - } - - inline bool - try_add(TKey const& key, TValue const& value) { - return _map.insert(key, value); - } - - inline bool - try_erase(TKey const& key, TValue* const value) { - assert(value != NULL); - copy_value_functor_t f(value); - return _map.erase(key, f); - } - - inline bool - try_erase(TKey const& key) { - return _map.erase(key); - } - - inline bool - try_get(TKey const& key, TValue* const value) { - assert(value != NULL); - copy_value_functor_t f(value); - return _map.find(key, f); - } - - // Inserts hash map key to container using back inserter. - // How to use: - // std::vector keys; - // map.unsafe_get_keys(back_inserter(keys)); - // - // Warning: This is called unsafe because it may not return all keys - // contained in map. - template - inline void - unsafe_get_keys(TOutputIterator b_inserter) { - typename base_hash_map::iterator it = _map.begin(); - for(; it != _map.end(); ++it) { - *b_inserter++ = it->first; // copy key - } - } - - template - inline void - unsafe_get_values(TOutputIterator b_inserter) { - typename base_hash_map::iterator it = _map.begin(); - for(; it != _map.end(); ++it) { - *b_inserter++ = it->second; // copy key - } - } - - public: - base_hash_map _map; - }; -} - -#endif /* LOCKFREE_HASH_MAP_HPP_ */ - diff --git a/test/libcds_demo/main.cpp b/test/libcds_demo/main.cpp deleted file mode 100644 index ee70fe4e6..000000000 --- a/test/libcds_demo/main.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -namespace cc = cds::container; - - - -#include "lockfree_hash_map.hpp" -using namespace cql; - -namespace std { - - template<> - struct hash<::boost::asio::ip::address> { - public: - typedef - ::boost::asio::ip::address - argument_type; - - typedef - ::std::size_t - result_type; - - private: - template - inline result_type - get_hash(const TBytesType& ip_bytes) const { - // implemented using djb2 algorithm - // see: http://www.cse.yorku.ca/~oz/hash.html - - unsigned long hash = 5381; - - for(TBytesType::const_iterator it = ip_bytes.cbegin(); - it != ip_bytes.cend(); ++it) - { - hash = ((hash << 5) + hash) + *it; - } - - return static_cast(hash); - } - - public: - inline result_type - operator ()(const argument_type& address) const { - if(address.is_v4()) { - return get_hash(address.to_v4().to_bytes()); - } - else { - return get_hash(address.to_v6().to_bytes()); - } - } - }; - - template<> - struct less<::boost::asio::ip::address> { - public: - typedef - ::boost::asio::ip::address - ip_addr; - - typedef - ip_addr - first_argument_type; - - typedef - ip_addr - second_argument_type; - - typedef - bool - result_type; - - private: - typedef - ::boost::asio::ip::address_v6 - ip_v6; - - inline ip_v6 - to_ip_v6(const ip_addr& address) const { - return address.is_v6() - ? address.to_v6() - : ip_v6::v4_mapped(address.to_v4()); - } - - public: - inline result_type - operator ()(const ip_addr& first, const ip_addr& second) const { - ip_v6 first_v6 = to_ip_v6(first); - ip_v6 second_v6 = to_ip_v6(second); - - ip_v6::bytes_type first_bytes = first_v6.to_bytes(); - ip_v6::bytes_type second_bytes = second_v6.to_bytes(); - - ip_v6::bytes_type::const_iterator first_it = first_bytes.cbegin(); - ip_v6::bytes_type::const_iterator second_it = second_bytes.cbegin(); - - for(; first_it != first_bytes.cend(); ++first_it, ++second_it) { - int delta = (int)*first_it - (int)*second_it; - if(delta != 0) - return delta < 0; - } - - // both addresses are equal - return false; - } - }; -} - -#define IP4(b1, b2, b3, b4) ip4(b4 + 256U * (b3 + 256U * (b2 + 256U * b1))) - - -void -do_job() { - typedef - ::boost::asio::ip::address - ip_addr; - - typedef - ::boost::asio::ip::address_v4 - ip4; - - using boost::shared_ptr; - - lockfree_hash_map_t > h; - - ip_addr a1(IP4(10, 0, 8, 1)); - ip_addr a2(IP4(10, 0, 8, 2)); - ip_addr a3(IP4(10, 8, 2, 1)); - ip_addr a4(IP4(192, 168, 0, 1)); - - h.try_add(a1, shared_ptr(new std::string("a1"))); - h.try_add(a2, shared_ptr(new std::string("a2"))); - h.try_add(a3, shared_ptr(new std::string("a3"))); - h.try_add(a4, shared_ptr(new std::string("a4"))); - - std::cout << "h.size() = " << h.size() << std::endl; - - std::cout << "keys: " << std::endl; - std::vector ips; - h.unsafe_get_keys(back_inserter(ips)); - for(auto it = ips.begin(); it != ips.end(); ++it) - std::cout << it->to_string() << std::endl; - - std::vector> names; - h.unsafe_get_values(back_inserter(names)); - for(auto it = names.begin(); it != names.end(); ++it) { - std::cout << **it << std::endl; - } - - shared_ptr result; - h.try_get(a1, &result); - std::cout << "h[a1]: " << *result << std::endl; - - std::cout << "h[non-ex] " << h.try_get(ip_addr(IP4(100,100,0,0)), &result) << std::endl; -} - -int -main(int argc, char* argv[]) { - cds::Initialize(); - { - cds::gc::HP hp_infrastructure; - cds::gc::HP::thread_gc hp_thread_gc; - - do_job(); - } - cds::Terminate(); -}