├── .gitignore ├── CMakeLists.txt ├── tests ├── basic_test.cpp ├── CTestTestfile.cmake ├── CMakeLists.txt └── test_runner.cpp ├── etcdcpp ├── CMakeLists.txt ├── etcdcpp.h └── etcdcpp.cpp └── etcdcppdemo ├── CMakeLists.txt └── etcdcppdemo.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | CMakeCache.txt 3 | CMakeFiles 4 | Makefile 5 | cmake_install.cmake 6 | install_manifest.txt 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | add_definitions(-std=c++11) 3 | project (etcdcpp) 4 | 5 | add_subdirectory (etcdcpp) 6 | add_subdirectory (etcdcppdemo) 7 | add_subdirectory (tests) 8 | 9 | #set(CMAKE_BUILD_TYPE Debug) 10 | 11 | -------------------------------------------------------------------------------- /tests/basic_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | class basic_test : public CppUnit::TestFixture { 3 | CPPUNIT_TEST_SUITE( basic_test ); 4 | CPPUNIT_TEST( testEmpty ); 5 | CPPUNIT_TEST_SUITE_END(); 6 | public: 7 | void testEmpty () { int i=5; CPPUNIT_ASSERT(i==5); } 8 | }; 9 | CPPUNIT_TEST_SUITE_REGISTRATION( basic_test ); 10 | -------------------------------------------------------------------------------- /etcdcpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #set(CMAKE_BUILD_TYPE Debug) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -pedantic") 5 | 6 | add_library (etcdcpp etcdcpp.cpp etcdcpp.h) 7 | 8 | install (FILES etcdcpp.h DESTINATION include/etcdcpp) 9 | 10 | install ( 11 | TARGETS etcdcpp 12 | ARCHIVE DESTINATION lib 13 | LIBRARY DESTINATION lib 14 | ) 15 | 16 | -------------------------------------------------------------------------------- /tests/CTestTestfile.cmake: -------------------------------------------------------------------------------- 1 | # CMake generated Testfile for 2 | # Source directory: /home/edward/Documents/java/etcdcpp/tests 3 | # Build directory: /home/edward/Documents/java/etcdcpp/tests 4 | # 5 | # This file includes the relevent testing commands required for 6 | # testing this directory and lists subdirectories to be tested as well. 7 | ADD_TEST(basic_test "UnitTester" "basic_test") 8 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | enable_testing() 3 | #set(CMAKE_BUILD_TYPE Debug) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") 6 | 7 | FILE(GLOB UnitTests_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*_test.cpp" ) 8 | ADD_EXECUTABLE(UnitTester test_runner.cpp ${UnitTests_SRCS}) 9 | FOREACH(test ${UnitTests_SRCS}) 10 | GET_FILENAME_COMPONENT(TestName ${test} NAME_WE) 11 | add_test(${TestName} UnitTester ${TestName}) 12 | ENDFOREACH(test) 13 | 14 | 15 | target_link_libraries (UnitTester cppunit) 16 | -------------------------------------------------------------------------------- /etcdcppdemo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | # Make sure the compiler can find include files from our library. 4 | include_directories (${PROJECT_SOURCE_DIR}/etcdcpp) 5 | 6 | # Make sure the linker can find the Hello library once it is built. 7 | link_directories (${PROJECT_SOURCE_DIR}/etcdcpp) 8 | 9 | # Add executable that is built from the source files 10 | add_executable (etcdcppdemo etcdcppdemo.cpp) 11 | 12 | # Link the executable to the library. 13 | target_link_libraries (etcdcppdemo etcdcpp curl) 14 | 15 | set(CMAKE_BUILD_TYPE Debug) 16 | -------------------------------------------------------------------------------- /tests/test_runner.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace CppUnit; 5 | 6 | int main (int argc, char* argv[]) { 7 | TextUi::TestRunner runner; 8 | TestFactoryRegistry& registry = TestFactoryRegistry::getRegistry(); 9 | 10 | // run all tests if none specified on command line 11 | Test* test_to_run = registry.makeTest(); 12 | if (argc>1) 13 | test_to_run = test_to_run->findTest(argv[1]); 14 | 15 | runner.addTest( test_to_run ); 16 | bool failed = runner.run("", false); 17 | return !failed; 18 | } 19 | -------------------------------------------------------------------------------- /etcdcppdemo/etcdcppdemo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "rapidjson/document.h" 6 | #include "rapidjson/writer.h" 7 | #include "rapidjson/stringbuffer.h" 8 | 9 | using namespace std; 10 | using namespace etcdcpp; 11 | 12 | int main () { 13 | try { 14 | vector host_list { etcd_host("localhost", 4001l) }; 15 | etcd_session s(host_list); 16 | 17 | std::unique_ptr setA = s.set("/message/a", "bla", 60); 18 | s.set("/message/b", "dah"); 19 | s.set("/message", "???"); 20 | s.get("/message"); 21 | s.get("/message/b"); 22 | s.set("/c", "5" ); 23 | 24 | std::unique_ptr result = s.get("/c"); 25 | 26 | // write result to stdout 27 | StringBuffer buffer; 28 | Writer writer(buffer); 29 | result->Accept(writer); 30 | std::cout << buffer.GetString() << std::endl; 31 | } catch (exception& e) { 32 | cerr << e.what() << endl; 33 | } catch (const char* message) { 34 | cerr << message << endl; 35 | } 36 | 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /etcdcpp/etcdcpp.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LIBETCDCPP_cxx_ 3 | #define LIBETCDCPP_cxx_ 4 | 5 | #include 6 | #include 7 | #include "rapidjson/document.h" 8 | #include 9 | 10 | using namespace std; 11 | using namespace rapidjson; 12 | 13 | namespace etcdcpp { 14 | 15 | class etcd_host { 16 | public: 17 | etcd_host(string host, short port): host(host), port(port) {}; 18 | 19 | string get_host() { return host; } 20 | 21 | unsigned short get_port() { return port; } 22 | 23 | private: 24 | string host; 25 | unsigned short port; 26 | }; 27 | 28 | class etcd_session { 29 | public: 30 | etcd_session(vector server_list); 31 | 32 | etcd_session(etcd_host host); 33 | 34 | /** 35 | * User must free returned Document * 36 | */ 37 | std::unique_ptr get(string key); 38 | 39 | /** 40 | * User must free returned Document * 41 | */ 42 | std::unique_ptr set(string key, string value, int ttl); 43 | 44 | /** 45 | * User must free returned Document * 46 | */ 47 | std::unique_ptr set(string key, string value); 48 | 49 | private: 50 | vector server_list; 51 | }; 52 | 53 | } //end namespace 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /etcdcpp/etcdcpp.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "rapidjson/document.h" 8 | #include "rapidjson/writer.h" 9 | #include "rapidjson/stringbuffer.h" 10 | #include 11 | #include "etcdcpp.h" 12 | 13 | using namespace std; 14 | using namespace rapidjson; 15 | using namespace etcdcpp; 16 | 17 | template 18 | string sappend(string s, T t) { 19 | ostringstream sstream; 20 | sstream << s << t; 21 | return sstream.str(); 22 | } 23 | 24 | /* curl uses a callback to read urls. It passes the result buffer reference as an argument */ 25 | int writer(char *data, size_t size, size_t nmemb, string *buffer){ 26 | int result = 0; 27 | if(buffer != NULL) { 28 | buffer -> append(data, size * nmemb); 29 | result = size * nmemb; 30 | } 31 | return result; 32 | } 33 | 34 | template 35 | std::unique_ptr with_curl(vector server_list, fun process) { 36 | CURL *curl; 37 | CURLcode res; 38 | curl = curl_easy_init(); 39 | string result; 40 | if (curl) { 41 | for (auto server : server_list) { 42 | process(server, curl); 43 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writer); 44 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result); 45 | res = curl_easy_perform(curl); 46 | if (res != CURLE_OK){ 47 | cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << endl; 48 | throw res; 49 | } 50 | curl_easy_cleanup(curl); 51 | 52 | Document *d = new Document; 53 | d->Parse(result.c_str()); 54 | return std::unique_ptr(std::move(d)); 55 | } 56 | } 57 | throw "Curl failed to initialize"; 58 | } 59 | 60 | 61 | string build_url(etcd_host &host, string key) { 62 | ostringstream url; 63 | url << "http://" << host.get_host() << ":" << host.get_port() << "/v2/keys" << key; 64 | return url.str(); 65 | } 66 | 67 | etcd_session::etcd_session(vector server_list) { 68 | if (server_list.size() == 0) { 69 | throw "Startup failed: At least one host is required"; 70 | } 71 | this->server_list = server_list; 72 | curl_global_init(CURL_GLOBAL_ALL); 73 | } 74 | 75 | etcd_session::etcd_session(etcd_host host) { 76 | vector hosts; 77 | hosts.push_back(host); 78 | this->server_list = hosts; 79 | curl_global_init(CURL_GLOBAL_ALL); 80 | } 81 | 82 | std::unique_ptr etcd_session::get(string key) { 83 | return with_curl(server_list, [=](etcd_host server, CURL *curl) { 84 | string url = build_url(server, key) + "?sorted=true&recursive=true"; 85 | curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); 86 | }); 87 | } 88 | 89 | 90 | std::unique_ptr etcd_session::set(string key, string value, int ttl) { 91 | string buffer = value + sappend("&ttl=", ttl); 92 | return this->set(key, buffer); 93 | } 94 | 95 | std::unique_ptr etcd_session::set(string key, string value) { 96 | return with_curl(server_list, [=] (etcd_host server, CURL *curl) { 97 | string url = build_url(server, key); 98 | string buffer = "value=" + value; 99 | curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); 100 | curl_easy_setopt(curl, CURLOPT_POST,1); 101 | curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, buffer.c_str()); 102 | }); 103 | } 104 | 105 | --------------------------------------------------------------------------------