From c0e8b6fd332cfd09d55caf89b332fb15a4e12ade Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Fri, 29 Nov 2013 20:08:41 -0500 Subject: [PATCH 01/17] Adding migration-related stuff --- Makefile.am | 36 ++++++ admin/admin.cc | 42 ++++++ admin/admin.h | 2 + admin/c.cc | 12 ++ common/configuration.cc | 22 +++- common/configuration.h | 2 + common/ids.cc | 1 + common/ids.h | 1 + common/migration.cc | 78 +++++++++++ common/migration.h | 66 ++++++++++ coordinator/coordinator.cc | 79 +++++++++++- coordinator/coordinator.h | 11 ++ coordinator/symtable.c | 1 + coordinator/transitions.cc | 30 +++++ coordinator/transitions.h | 1 + hyperdex-migrate | 228 +++++++++++++++++++++++++++++++++ hyperdex-migrate-data | 228 +++++++++++++++++++++++++++++++++ hyperdex.cc | 1 + include/hyperdex/admin.h | 6 + include/hyperdex/admin.hpp | 4 + man/hyperdex-migrate-data.1.md | 23 ++++ tools/migrate_data.cc | 102 +++++++++++++++ 22 files changed, 974 insertions(+), 2 deletions(-) create mode 100644 common/migration.cc create mode 100644 common/migration.h create mode 100755 hyperdex-migrate create mode 100755 hyperdex-migrate-data create mode 100644 man/hyperdex-migrate-data.1.md create mode 100644 tools/migrate_data.cc diff --git a/Makefile.am b/Makefile.am index 4316db038..74dcfd99b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -139,6 +139,7 @@ noinst_HEADERS += common/schema.h noinst_HEADERS += common/serialization.h noinst_HEADERS += common/server.h noinst_HEADERS += common/transfer.h +noinst_HEADERS += common/migration.h noinst_HEADERS += tools/common.h check_PROGRAMS += common/test/ordered_encoding @@ -233,6 +234,7 @@ hyperdex_daemon_SOURCES += common/serialization.cc hyperdex_daemon_SOURCES += common/server.cc hyperdex_daemon_SOURCES += common/transfer.cc hyperdex_daemon_SOURCES += cityhash/city.cc +hyperdex_daemon_SOURCES += common/migration.cc hyperdex_daemon_SOURCES += daemon/communication.cc hyperdex_daemon_SOURCES += daemon/coordinator_link_wrapper.cc hyperdex_daemon_SOURCES += daemon/daemon.cc @@ -308,6 +310,7 @@ libhyperdex_coordinator_la_SOURCES += common/schema.cc libhyperdex_coordinator_la_SOURCES += common/serialization.cc libhyperdex_coordinator_la_SOURCES += common/server.cc libhyperdex_coordinator_la_SOURCES += common/transfer.cc +libhyperdex_coordinator_la_SOURCES += common/migration.cc libhyperdex_coordinator_la_SOURCES += coordinator/coordinator.cc libhyperdex_coordinator_la_SOURCES += coordinator/replica_sets.cc libhyperdex_coordinator_la_SOURCES += coordinator/server_barrier.cc @@ -388,6 +391,7 @@ libhyperdex_client_la_SOURCES += common/server.cc libhyperdex_client_la_SOURCES += common/serialization.cc libhyperdex_client_la_SOURCES += common/transfer.cc libhyperdex_client_la_SOURCES += cityhash/city.cc +libhyperdex_client_la_SOURCES += common/migration.cc libhyperdex_client_la_SOURCES += client/c.cc libhyperdex_client_la_SOURCES += client/client.cc libhyperdex_client_la_SOURCES += client/datastructures.cc @@ -473,6 +477,7 @@ libhyperdex_admin_la_SOURCES += common/serialization.cc libhyperdex_admin_la_SOURCES += common/server.cc libhyperdex_admin_la_SOURCES += common/transfer.cc libhyperdex_admin_la_SOURCES += cityhash/city.cc +libhyperdex_admin_la_SOURCES += common/migration.cc libhyperdex_admin_la_SOURCES += admin/admin.cc libhyperdex_admin_la_SOURCES += admin/backup_state_machine.cc libhyperdex_admin_la_SOURCES += admin/c.cc @@ -714,6 +719,7 @@ endif check_PROGRAMS += test/replication-stress-test check_PROGRAMS += test/search-stress-test +<<<<<<< HEAD shell_wrappers = @@ -954,6 +960,8 @@ EXTRA_DIST += test/ruby/MultiAttribute.rb EXTRA_DIST += test/ruby/RangeSearchInt.rb EXTRA_DIST += test/ruby/RangeSearchString.rb EXTRA_DIST += test/ruby/RegexSearch.rb +======= +>>>>>>> Adding migration-related stuff test_replication_stress_test_SOURCES = test/replication-stress-test.cc test_replication_stress_test_LDADD = libhyperdex-client.la -le @@ -966,6 +974,7 @@ test_search_stress_test_LDADD = libhyperdex-client.la -le ################################################################################ if ENABLE_TOOLS +<<<<<<< HEAD hyperdexexec_PROGRAMS += hyperdex-add-space hyperdexexec_PROGRAMS += hyperdex-rm-space hyperdexexec_PROGRAMS += hyperdex-list-spaces @@ -983,6 +992,23 @@ hyperdexexec_PROGRAMS += hyperdex-wait-until-stable hyperdexexec_PROGRAMS += hyperdex-backup hyperdexexec_PROGRAMS += hyperdex-backup-manager hyperdexexec_PROGRAMS += hyperdex-raw-backup +======= +bin_PROGRAMS += hyperdex-add-space +bin_PROGRAMS += hyperdex-rm-space +bin_PROGRAMS += hyperdex-list-spaces +bin_PROGRAMS += hyperdex-validate-space +bin_PROGRAMS += hyperdex-show-config +bin_PROGRAMS += hyperdex-server-register +bin_PROGRAMS += hyperdex-server-online +bin_PROGRAMS += hyperdex-server-offline +bin_PROGRAMS += hyperdex-server-kill +bin_PROGRAMS += hyperdex-server-forget +bin_PROGRAMS += hyperdex-perf-counters +bin_PROGRAMS += hyperdex-set-read-only +bin_PROGRAMS += hyperdex-set-read-write +bin_PROGRAMS += hyperdex-raw-backup +bin_PROGRAMS += hyperdex-migrate-data +>>>>>>> Adding migration-related stuff dist_man_MANS += man/hyperdex-add-space.1 dist_man_MANS += man/hyperdex-rm-space.1 dist_man_MANS += man/hyperdex-list-spaces.1 @@ -1000,6 +1026,7 @@ dist_man_MANS += man/hyperdex-wait-until-stable.1 dist_man_MANS += man/hyperdex-backup.1 dist_man_MANS += man/hyperdex-backup-manager.1 dist_man_MANS += man/hyperdex-raw-backup.1 +dist_man_MANS += man/hyperdex-migrate-data.1 endif # hyperdex @@ -1167,6 +1194,15 @@ man/hyperdex-raw-backup.1: man/hyperdex-raw-backup.1.h2m tools/raw-backup.cc @$(MAKE) --silent $(AM_MAKEFLAGS) hyperdex-raw-backup$(EXEEXT) $(help2man_verbose)help2man $(HELP2MAN_FLAGS) --section 1 --output $@ --include $< ${abs_top_builddir}/hyperdex-raw-backup$(EXEEXT) +# hyperdex-migrate-data +EXTRA_DIST += man/hyperdex-migrate-data.1.md +EXTRA_DIST += man/hyperdex-migrate-data.1.h2m +hyperdex_migrate_data_SOURCES = tools/migrate_data.cc +hyperdex_migrate_data_LDADD = libhyperdex-admin.la -lpopt +man/hyperdex-migrate-data.1: man/hyperdex-migrate-data.1.h2m tools/migrate_data.cc + @$(MAKE) --silent $(AM_MAKEFLAGS) hyperdex-migrate-data$(EXEEXT) + $(help2man_verbose)help2man $(HELP2MAN_FLAGS) --section 1 --output $@ --include $< ${abs_top_builddir}/hyperdex-migrate-data$(EXEEXT) + ################################################################################ ################################# Documentation ################################ ################################################################################ diff --git a/admin/admin.cc b/admin/admin.cc index f8eda920b..886dbd277 100644 --- a/admin/admin.cc +++ b/admin/admin.cc @@ -193,6 +193,48 @@ admin :: fault_tolerance(const char* space, uint64_t ft, } } +int64_t +admin :: migrate_data(const char* space_from, const char* space_to, + enum hyperdex_admin_returncode* status) +{ + if (!maintain_coord_connection(status)) + { + return -1; + } + + int64_t id = m_next_admin_id; + ++m_next_admin_id; + e::intrusive_ptr op = new coord_rpc_generic(id, status, "migrate"); + uint64_t space_from_sz = strlen(space_from); + uint64_t space_to_sz = strlen(space_to); + + // Pack + size_t total_sz = sizeof(uint64_t) * 2 + space_from_sz + space_to_sz; + char buf[total_sz]; + char* pos = buf; + e::pack64be(space_from_sz, pos); + pos += sizeof(uint64_t); + memcpy(pos, space_from, space_from_sz); + pos += space_from_sz; + e::pack64be(space_to_sz, pos); + pos += sizeof(uint64_t); + memcpy(pos, space_to, space_to_sz); + + int64_t cid = m_coord.rpc("migrate", buf, total_sz, + &op->repl_status, &op->repl_output, &op->repl_output_sz); + + if (cid >= 0) + { + m_coord_ops[cid] = op; + return op->admin_visible_id(); + } + else + { + interpret_rpc_request_failure(op->repl_status, status); + return -1; + } +} + int admin :: validate_space(const char* description, hyperdex_admin_returncode* status) diff --git a/admin/admin.h b/admin/admin.h index b76e64b43..b1b53f574 100644 --- a/admin/admin.h +++ b/admin/admin.h @@ -72,6 +72,8 @@ class admin enum hyperdex_admin_returncode* status); int64_t list_spaces(enum hyperdex_admin_returncode* status, const char** spaces); + int64_t migrate_data(const char* space_from, const char* space_to, + enum hyperdex_admin_returncode* status); // manage servers int64_t server_register(uint64_t token, const char* address, enum hyperdex_admin_returncode* status); diff --git a/admin/c.cc b/admin/c.cc index d3016218c..ffc792f93 100644 --- a/admin/c.cc +++ b/admin/c.cc @@ -173,6 +173,18 @@ hyperdex_admin_list_spaces(struct hyperdex_admin* _adm, ); } +HYPERDEX_API int64_t +hyperdex_admin_migrate_data(struct hyperdex_admin* _adm, + const char* space_from, + const char* space_to, + enum hyperdex_admin_returncode* status) +{ + C_WRAP_EXCEPT( + hyperdex::admin* adm = reinterpret_cast(_adm); + return adm->migrate_data(space_from, space_to, status); + ); +} + HYPERDEX_API int64_t hyperdex_admin_server_register(struct hyperdex_admin* _adm, uint64_t token, const char* address, diff --git a/common/configuration.cc b/common/configuration.cc index 4574c8ca1..cc43da831 100644 --- a/common/configuration.cc +++ b/common/configuration.cc @@ -66,6 +66,7 @@ configuration :: configuration() , m_point_leaders_by_virtual() , m_spaces() , m_transfers() + , m_migrations() { refill_cache(); } @@ -88,6 +89,7 @@ configuration :: configuration(const configuration& other) , m_point_leaders_by_virtual(other.m_point_leaders_by_virtual) , m_spaces(other.m_spaces) , m_transfers(other.m_transfers) + , m_migrations(other.m_migrations) { refill_cache(); } @@ -876,6 +878,11 @@ configuration :: dump() const out << m_transfers[i] << std::endl; } + for (size_t i = 0; i < m_migrations.size(); ++i) + { + out << m_migrations[i] << std::endl; + } + return out.str(); } @@ -917,6 +924,7 @@ configuration :: operator = (const configuration& rhs) m_point_leaders_by_virtual = rhs.m_point_leaders_by_virtual; m_spaces = rhs.m_spaces; m_transfers = rhs.m_transfers; + m_migrations = rhs.m_migrations; refill_cache(); return *this; } @@ -1022,9 +1030,11 @@ hyperdex :: operator >> (e::unpacker up, configuration& c) uint64_t num_servers; uint64_t num_spaces; uint64_t num_transfers; + uint64_t num_migrations; up = up >> c.m_cluster >> c.m_version >> c.m_flags >> num_servers >> num_spaces - >> num_transfers; + >> num_transfers >> num_migrations; + c.m_servers.clear(); c.m_servers.reserve(num_servers); @@ -1055,6 +1065,16 @@ hyperdex :: operator >> (e::unpacker up, configuration& c) c.m_transfers.push_back(xfer); } + c.m_migrations.clear(); + c.m_migrations.reserve(num_migrations); + + for (size_t i = 0; !up.error() && i < num_migrations; ++i) + { + migration m; + up = up >> m; + c.m_migrations.push_back(m); + } + c.refill_cache(); return up; } diff --git a/common/configuration.h b/common/configuration.h index ce824800b..437d6bf3d 100755 --- a/common/configuration.h +++ b/common/configuration.h @@ -47,6 +47,7 @@ #include "common/schema.h" #include "common/server.h" #include "common/transfer.h" +#include "common/migration.h" BEGIN_HYPERDEX_NAMESPACE @@ -155,6 +156,7 @@ class configuration std::vector m_point_leaders_by_virtual; std::vector m_spaces; std::vector m_transfers; + std::vector m_migrations; }; e::buffer::packer diff --git a/common/ids.cc b/common/ids.cc index ff8bee80c..57286c6a3 100644 --- a/common/ids.cc +++ b/common/ids.cc @@ -56,6 +56,7 @@ CREATE_ID(server) CREATE_ID(space) CREATE_ID(subspace) CREATE_ID(transfer) +CREATE_ID(migration) CREATE_ID(virtual_server) END_HYPERDEX_NAMESPACE diff --git a/common/ids.h b/common/ids.h index 826a720de..5d0ad98d8 100644 --- a/common/ids.h +++ b/common/ids.h @@ -86,6 +86,7 @@ CREATE_ID(server) CREATE_ID(space) CREATE_ID(subspace) CREATE_ID(transfer) +CREATE_ID(migration) CREATE_ID(virtual_server) END_HYPERDEX_NAMESPACE diff --git a/common/migration.cc b/common/migration.cc new file mode 100644 index 000000000..09e276710 --- /dev/null +++ b/common/migration.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// HyperDex +#include "common/migration.h" + +using hyperdex::migration; + +migration :: migration() + : id() + , space_from() + , space_to() +{ +} + +migration :: migration(migration_id _id, + space_id _space_from, + space_id _space_to) + : id(id) + , space_from(_space_from) + , space_to(_space_to) +{ +} + +std::ostream& +hyperdex :: operator << (std::ostream& lhs, const migration& rhs) +{ + return lhs << "migration(id=" << rhs.id + << ", space_from=" << rhs.space_from + << ", space_to=" << rhs.space_to; +} + +e::buffer::packer +hyperdex :: operator << (e::buffer::packer pa, const migration& m) +{ + pa = pa << m.space_from << m.space_to; + return pa; +} + +e::unpacker +hyperdex :: operator >> (e::unpacker up, migration& m) +{ + space_id s_space_from, s_space_to; + up >> s_space_from >> s_space_to; + m.space_from = s_space_from; + m.space_to = s_space_to; + return up; +} + +size_t +hyperdex :: pack_size(const migration&) +{ + return 2 * sizeof(uint64_t); +} diff --git a/common/migration.h b/common/migration.h new file mode 100644 index 000000000..7fbeff9e8 --- /dev/null +++ b/common/migration.h @@ -0,0 +1,66 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef hyperdex_common_migration_h_ +#define hyperdex_common_migration_h_ + +// HyperDex +#include "namespace.h" +#include "common/ids.h" + +BEGIN_HYPERDEX_NAMESPACE + +class migration +{ + public: + migration(); + migration(migration_id id, + space_id space_from, + space_id space_to); + + public: + migration_id id; + space_id space_from; + space_id space_to; +}; + +std::ostream& +operator << (std::ostream& lhs, const migration& rhs); + +e::buffer::packer +operator << (e::buffer::packer, const migration& t); + +e::unpacker +operator >> (e::unpacker, migration& t); + +size_t +pack_size(const migration&); + + +END_HYPERDEX_NAMESPACE + +#endif // hyperdex_common_migration_h_ \ No newline at end of file diff --git a/coordinator/coordinator.cc b/coordinator/coordinator.cc index 7037483d3..d7ec774bc 100644 --- a/coordinator/coordinator.cc +++ b/coordinator/coordinator.cc @@ -49,6 +49,7 @@ using hyperdex::region; using hyperdex::region_intent; using hyperdex::server; using hyperdex::transfer; +using hyperdex::migration; // ASSUME: I'm assuming only one server ever changes state at a time for a // given transition. If you violate this assumption, fixup @@ -1637,6 +1638,71 @@ coordinator :: del_transfer(const transfer_id& xid) } } +void +coordinator :: new_migration(replicant_state_machine_context* ctx, + const char* space_from, + const char* space_to) +{ + FILE* log = replicant_state_machine_log_stream(ctx); + + // Make sure the spaces exist + space_map_t::iterator it; + it = m_spaces.find(std::string(space_from)); + if (it == m_spaces.end()) + { + fprintf(log, "could not migrate from space \"%s\" because it doesn't exist\n", space_from); + return generate_response(ctx, COORD_NOT_FOUND); + } + + space_id space_from_id = it->second->id; + + it = m_spaces.find(std::string(space_to)); + if (it == m_spaces.end()) + { + fprintf(log, "could not migrate to space \"%s\" because it doesn't exist\n", space_to); + return generate_response(ctx, COORD_NOT_FOUND); + } + + space_id space_to_id = it->second->id; + + m_migrations.push_back(migration(migration_id(m_counter++), + space_from_id, space_to_id)); + generate_next_configuration(ctx); +} + +migration* +coordinator :: get_migration(space_id space_from, + space_id space_to) +{ + for (size_t i = 0; i < m_migrations.size(); ++i) + { + if (m_migrations[i].space_from == space_from && m_migrations[i].space_to == space_to) + { + return &m_migrations[i]; + } + } + + return NULL; +} + +void +coordinator :: del_migration(space_id space_from, + space_id space_to) +{ + for (size_t i = 0; i < m_migrations.size(); ++i) + { + if (m_migrations[i].space_from == space_from && m_migrations[i].space_to == space_to) + { + for (size_t j = i + 1; j < m_migrations.size(); ++j) + { + m_migrations[j - 1] = m_migrations[j]; + } + m_migrations.pop_back(); + break; + } + } +} + void coordinator :: check_ack_condition(replicant_state_machine_context* ctx) { @@ -1712,12 +1778,18 @@ coordinator :: generate_cached_configuration(replicant_state_machine_context*) sz += pack_size(m_transfers[i]); } + for (size_t i = 0; i < m_migrations.size(); ++i) + { + sz += pack_size(m_migrations[i]); + } + std::auto_ptr new_config(e::buffer::create(sz)); e::buffer::packer pa = new_config->pack_at(0); pa = pa << m_cluster << m_version << m_flags << uint64_t(m_servers.size()) << uint64_t(m_spaces.size()) - << uint64_t(m_transfers.size()); + << uint64_t(m_transfers.size()) + << uint64_t(m_migrations.size()); for (size_t i = 0; i < m_servers.size(); ++i) { @@ -1735,6 +1807,11 @@ coordinator :: generate_cached_configuration(replicant_state_machine_context*) pa = pa << m_transfers[i]; } + for (size_t i = 0; i < m_migrations.size(); ++i) + { + pa = pa << m_migrations[i]; + } + m_latest_config = new_config; } diff --git a/coordinator/coordinator.h b/coordinator/coordinator.h index 56efbec4a..66e9fc525 100644 --- a/coordinator/coordinator.h +++ b/coordinator/coordinator.h @@ -44,6 +44,7 @@ #include "common/ids.h" #include "common/server.h" #include "common/transfer.h" +#include "common/migration.h" #include "coordinator/offline_server.h" #include "coordinator/region_intent.h" #include "coordinator/replica_sets.h" @@ -67,6 +68,14 @@ class coordinator void read_only(replicant_state_machine_context* ctx, bool ro); void fault_tolerance(replicant_state_machine_context* ctx, const char* space, uint64_t consistency); + // migrations + void new_migration(replicant_state_machine_context* ctx, + const char* space_from, + const char* space_to); + migration* get_migration(space_id space_from, + space_id space_to); + void del_migration(space_id space_from, + space_id space_to); // server management public: @@ -203,6 +212,8 @@ class coordinator std::vector m_offline; // transfers std::vector m_transfers; + // migrations + std::vector m_migrations; // barriers uint64_t m_config_ack_through; server_barrier m_config_ack_barrier; diff --git a/coordinator/symtable.c b/coordinator/symtable.c index 4e55c32a9..2af782bb7 100644 --- a/coordinator/symtable.c +++ b/coordinator/symtable.c @@ -60,6 +60,7 @@ struct replicant_state_machine HYPERDEX_API rsm = { {"alarm", hyperdex_coordinator_alarm}, {"read_only", hyperdex_coordinator_read_only}, {"fault_tolerance", hyperdex_coordinator_fault_tolerance}, + {"migrate", hyperdex_coordinator_migrate_data}, {"debug_dump", hyperdex_coordinator_debug_dump}, {"init", hyperdex_coordinator_init}, {NULL, NULL}} diff --git a/coordinator/transitions.cc b/coordinator/transitions.cc index 34b453070..251c4bde8 100644 --- a/coordinator/transitions.cc +++ b/coordinator/transitions.cc @@ -193,6 +193,36 @@ hyperdex_coordinator_fault_tolerance(struct replicant_state_machine_context* ctx c->fault_tolerance(ctx, data, ft); } +void +hyperdex_coordinator_migrate_data(struct replicant_state_machine_context* ctx, + void *obj, const char* data, size_t data_sz) +{ + PROTECT_UNINITIALIZED; + FILE* log = replicant_state_machine_log_stream(ctx); + coordinator* c = static_cast(obj); + + char* pos = const_cast(data); + + uint64_t space_from_sz; + e::unpacker up_one(pos, sizeof(uint64_t)); + up_one >> space_from_sz; + pos += sizeof(uint64_t); + char space_from[space_from_sz + 1]; + memcpy(space_from, pos, space_from_sz); + pos += space_from_sz; + space_from[space_from_sz] = '\0'; + + uint64_t space_to_sz; + e::unpacker up_two(pos, sizeof(uint64_t)); + up_two >> space_to_sz; + pos += sizeof(uint64_t); + char space_to[space_to_sz + 1]; + memcpy(space_to, pos, space_to_sz); + space_to[space_to_sz] = '\0'; + + c->new_migration(ctx, space_from, space_to); +} + void hyperdex_coordinator_config_get(struct replicant_state_machine_context* ctx, void* obj, const char*, size_t) diff --git a/coordinator/transitions.h b/coordinator/transitions.h index dfb606036..7aae39633 100644 --- a/coordinator/transitions.h +++ b/coordinator/transitions.h @@ -59,6 +59,7 @@ TRANSITION(init); TRANSITION(read_only); TRANSITION(fault_tolerance); +TRANSITION(migrate_data); TRANSITION(config_get); TRANSITION(config_ack); diff --git a/hyperdex-migrate b/hyperdex-migrate new file mode 100755 index 000000000..97402e3be --- /dev/null +++ b/hyperdex-migrate @@ -0,0 +1,228 @@ +#! /bin/bash + +# hyperdex-migrate - temporary wrapper script for .libs/hyperdex-migrate +# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu1 +# +# The hyperdex-migrate program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="(cd /media/Work_Study/CS/workspace/HyperDex/HyperDex; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/derek/.rvm/gems/ruby-2.0.0-p0/bin:/home/derek/.rvm/gems/ruby-2.0.0-p0@global/bin:/home/derek/.rvm/rubies/ruby-2.0.0-p0/bin:/home/derek/.rvm/bin:/usr/lib/mipsel-linux/bin:/usr/local/heroku/bin:/home/derek/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/go/bin:/home/derek/go/bin:/home/derek/Dropbox/CS/workspace/go:/usr/lib/scala/bin:/usr/lib/akka/bin:/media/Work_Study/CS/workspace/Play:/home/derek/.cabal/bin:/usr/lib/vertx/bin:/usr/lib/jvm/jdk1.7.0/bin:/home/derek/Dropbox/CS/workspace/go/bin; export PATH; g++ -fvisibility=hidden -fvisibility-inlines-hidden -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -g -O2 -o \$progdir/\$file tools/migrate.o ./.libs/libhyperdex-admin.so /usr/lib/x86_64-linux-gnu/libpopt.so -Wl,-rpath -Wl,/media/Work_Study/CS/workspace/HyperDex/HyperDex/.libs)" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.2' + notinst_deplibs=' libhyperdex-admin.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ./libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "hyperdex-migrate:hyperdex-migrate:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu1" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "hyperdex-migrate:hyperdex-migrate:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "hyperdex-migrate:hyperdex-migrate:${LINENO}: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'hyperdex-migrate' + progdir="$thisdir/.libs" + + if test ! -f "$progdir/$program" || + { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \ + test "X$file" != "X$progdir/$program"; }; then + + file="$$-$program" + + if test ! -d "$progdir"; then + mkdir "$progdir" + else + rm -f "$progdir/$file" + fi + + # relink executable if necessary + if test -n "$relink_command"; then + if relink_command_output=`eval $relink_command 2>&1`; then : + else + printf %s\n "$relink_command_output" >&2 + rm -f "$progdir/$file" + exit 1 + fi + fi + + mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || + { rm -f "$progdir/$program"; + mv -f "$progdir/$file" "$progdir/$program"; } + rm -f "$progdir/$file" + fi + + if test -f "$progdir/$program"; then + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/hyperdex-migrate-data b/hyperdex-migrate-data new file mode 100755 index 000000000..7e52a1e1e --- /dev/null +++ b/hyperdex-migrate-data @@ -0,0 +1,228 @@ +#! /bin/bash + +# hyperdex-migrate-data - temporary wrapper script for .libs/hyperdex-migrate-data +# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu1 +# +# The hyperdex-migrate-data program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="(cd /media/Work_Study/CS/workspace/HyperDex/HyperDex; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/derek/.rvm/gems/ruby-2.0.0-p0/bin:/home/derek/.rvm/gems/ruby-2.0.0-p0@global/bin:/home/derek/.rvm/rubies/ruby-2.0.0-p0/bin:/home/derek/.rvm/bin:/usr/lib/mipsel-linux/bin:/usr/local/heroku/bin:/home/derek/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/go/bin:/home/derek/go/bin:/home/derek/Dropbox/CS/workspace/go:/usr/lib/scala/bin:/usr/lib/akka/bin:/media/Work_Study/CS/workspace/Play:/home/derek/.cabal/bin:/usr/lib/vertx/bin:/usr/lib/jvm/jdk1.7.0/bin:/home/derek/Dropbox/CS/workspace/go/bin; export PATH; g++ -fvisibility=hidden -fvisibility-inlines-hidden -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -g -O2 -o \$progdir/\$file tools/migrate_data.o ./.libs/libhyperdex-admin.so /usr/lib/x86_64-linux-gnu/libpopt.so -Wl,-rpath -Wl,/media/Work_Study/CS/workspace/HyperDex/HyperDex/.libs)" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.2' + notinst_deplibs=' libhyperdex-admin.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ./libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "hyperdex-migrate-data:hyperdex-migrate-data:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu1" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "hyperdex-migrate-data:hyperdex-migrate-data:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "hyperdex-migrate-data:hyperdex-migrate-data:${LINENO}: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'hyperdex-migrate-data' + progdir="$thisdir/.libs" + + if test ! -f "$progdir/$program" || + { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \ + test "X$file" != "X$progdir/$program"; }; then + + file="$$-$program" + + if test ! -d "$progdir"; then + mkdir "$progdir" + else + rm -f "$progdir/$file" + fi + + # relink executable if necessary + if test -n "$relink_command"; then + if relink_command_output=`eval $relink_command 2>&1`; then : + else + printf %s\n "$relink_command_output" >&2 + rm -f "$progdir/$file" + exit 1 + fi + fi + + mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || + { rm -f "$progdir/$program"; + mv -f "$progdir/$file" "$progdir/$program"; } + rm -f "$progdir/$file" + fi + + if test -f "$progdir/$program"; then + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/hyperdex.cc b/hyperdex.cc index 29866de10..6ad37d64c 100644 --- a/hyperdex.cc +++ b/hyperdex.cc @@ -45,6 +45,7 @@ main(int argc, const char* argv[]) cmds.push_back(e::subcommand("rm-space", "Remove an existing HyperDex space")); cmds.push_back(e::subcommand("list-spaces", "List the names of all spaces")); cmds.push_back(e::subcommand("validate-space", "Validate a HyperDex space description")); + cmds.push_back(e::subcommand("migrate-data", "Migrate data from one space to another")); cmds.push_back(e::subcommand("server-register", "Manually register a new HyperDex server")); cmds.push_back(e::subcommand("server-offline", "Manually take a daemon offline")); cmds.push_back(e::subcommand("server-online", "Manually bring a daemon online")); diff --git a/include/hyperdex/admin.h b/include/hyperdex/admin.h index 50b2dd85b..05d0b2029 100644 --- a/include/hyperdex/admin.h +++ b/include/hyperdex/admin.h @@ -119,6 +119,12 @@ hyperdex_admin_list_spaces(struct hyperdex_admin* admin, enum hyperdex_admin_returncode* status, const char** spaces); +int64_t +hyperdex_admin_migrate_data(struct hyperdex_admin* admin, + const char* space_from, + const char* space_to, + enum hyperdex_admin_returncode* status); + int64_t hyperdex_admin_server_register(struct hyperdex_admin* admin, uint64_t token, const char* address, diff --git a/include/hyperdex/admin.hpp b/include/hyperdex/admin.hpp index 9a93dca13..8bb6f84cd 100644 --- a/include/hyperdex/admin.hpp +++ b/include/hyperdex/admin.hpp @@ -73,6 +73,10 @@ class Admin int64_t list_spaces(enum hyperdex_admin_returncode* status, const char** spaces) { return hyperdex_admin_list_spaces(m_adm, status, spaces); } + int64_t migrate_data(const char* space_from, + const char* space_to, + enum hyperdex_admin_returncode* status) + { return hyperdex_admin_migrate_data(m_adm, space_from, space_to, status); }; int64_t server_register(uint64_t token, const char* address, enum hyperdex_admin_returncode* status) { return hyperdex_admin_server_register(m_adm, token, address, status); } diff --git a/man/hyperdex-migrate-data.1.md b/man/hyperdex-migrate-data.1.md new file mode 100644 index 000000000..f347bccbe --- /dev/null +++ b/man/hyperdex-migrate-data.1.md @@ -0,0 +1,23 @@ +.TH "" "" +[NAME] +[SYNOPSIS] +[DESCRIPTION] +[OPTIONS] +[ENVIRONMENT] +[FILES] +[EXAMPLES] +[AUTHORS] + +HyperDex is an open source project started by Cornell University and +currently maintained by Cornell University and United Networks, LLC. +For a complete list of contributors, see the AUTHORS file included in +the HyperDex distribution. +[REPORTING BUGS] + +Report bugs to the HyperDex mailing list + where the developers can help +troubleshoot problems and file bug reports. +[COPYRIGHT] + +Copyright (c) 2011-2013, The HyperDex Authors +[SEE ALSO] diff --git a/tools/migrate_data.cc b/tools/migrate_data.cc new file mode 100644 index 000000000..9d247d307 --- /dev/null +++ b/tools/migrate_data.cc @@ -0,0 +1,102 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Replicant nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// C +#include +#include + +// HyperDex +#include +#include "tools/common.h" + +int +main(int argc, const char* argv[]) +{ + hyperdex::connect_opts conn; + e::argparser ap; + ap.autohelp(); + ap.add("Connect to a cluster:", conn.parser()); + + if (!ap.parse(argc, argv)) + { + return EXIT_FAILURE; + } + + if (!conn.validate()) + { + std::cerr << "invalid host:port specification\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + + try + { + if (ap.args_sz() != 2) { + std::cerr << "invalid arguments: expecting exactly two space names\n" << std::endl; + ap.usage(); + return EXIT_FAILURE; + } + + + + hyperdex::Admin h(conn.host(), conn.port()); + hyperdex_admin_returncode rrc; + + int64_t rid = h.migrate_data(ap.args()[0], ap.args()[1], &rrc); + + if (rid < 0) + { + std::cerr << "could not migrate data: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + + hyperdex_admin_returncode lrc; + int64_t lid = h.loop(-1, &lrc); + + if (lid < 0) + { + std::cerr << "could not migrate data: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + + assert(rid == lid); + + if (rrc != HYPERDEX_ADMIN_SUCCESS) + { + std::cerr << "could not migrate_data: " << h.error_message() << std::endl; + return EXIT_FAILURE; + } + + std::cout << "migration in process..." << std::endl; + return EXIT_SUCCESS; + } + catch (std::exception& e) + { + std::cerr << "error: " << e.what() << std::endl; + return EXIT_FAILURE; + } +} From 1124b1742778259f078fde8f2627b720aeb06dcd Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Sat, 14 Dec 2013 21:28:41 -0500 Subject: [PATCH 02/17] Got things to compile --- Makefile.am | 4 + common/configuration.cc | 51 ++++++++ common/configuration.h | 6 + daemon/daemon.cc | 6 + daemon/daemon.h | 3 + daemon/migration_manager.cc | 236 ++++++++++++++++++++++++++++++++++ daemon/migration_manager.h | 137 ++++++++++++++++++++ daemon/migration_out_state.cc | 50 +++++++ daemon/migration_out_state.h | 79 ++++++++++++ 9 files changed, 572 insertions(+) create mode 100644 daemon/migration_manager.cc create mode 100644 daemon/migration_manager.h create mode 100644 daemon/migration_out_state.cc create mode 100644 daemon/migration_out_state.h diff --git a/Makefile.am b/Makefile.am index 74dcfd99b..ea807a446 100644 --- a/Makefile.am +++ b/Makefile.am @@ -202,6 +202,8 @@ noinst_HEADERS += daemon/state_transfer_manager.h noinst_HEADERS += daemon/state_transfer_manager_pending.h noinst_HEADERS += daemon/state_transfer_manager_transfer_in_state.h noinst_HEADERS += daemon/state_transfer_manager_transfer_out_state.h +noinst_HEADERS += daemon/migration_manager.h +noinst_HEADERS += daemon/migration_out_state.h EXTRA_DIST += man/hyperdex-daemon.1.md EXTRA_DIST += man/hyperdex-daemon.1.h2m @@ -262,6 +264,8 @@ hyperdex_daemon_SOURCES += daemon/state_transfer_manager.cc hyperdex_daemon_SOURCES += daemon/state_transfer_manager_pending.cc hyperdex_daemon_SOURCES += daemon/state_transfer_manager_transfer_in_state.cc hyperdex_daemon_SOURCES += daemon/state_transfer_manager_transfer_out_state.cc +hyperdex_daemon_SOURCES += daemon/migration_manager.cc +hyperdex_daemon_SOURCES += daemon/migration_out_state.cc hyperdex_daemon_CXXFLAGS = $(AM_CXXFLAGS) $(CXXFLAGS) hyperdex_daemon_LDADD = hyperdex_daemon_LDADD += $(E_LIBS) diff --git a/common/configuration.cc b/common/configuration.cc index cc43da831..be642ee84 100644 --- a/common/configuration.cc +++ b/common/configuration.cc @@ -45,6 +45,7 @@ using hyperdex::schema; using hyperdex::server; using hyperdex::server_id; using hyperdex::subspace; +using hyperdex::space_id; using hyperdex::subspace_id; using hyperdex::virtual_server_id; @@ -284,6 +285,21 @@ configuration :: get_virtual(const region_id& ri, const server_id& si) const return virtual_server_id(); } +space_id +configuration :: space_of(const region_id& ri) const +{ + subspace_id ssid = subspace_of(ri); + for (size_t s = 0; s < m_spaces.size(); ++s) + { + for (size_t ss = 0; ss < m_spaces[s].subspaces.size(); ++ss) + { + if (m_spaces[s].subspaces[ss].id == ssid) { + return m_spaces[s].id; + } + } + } +} + subspace_id configuration :: subspace_of(const region_id& ri) const { @@ -616,6 +632,41 @@ configuration :: transfers_out_regions(const server_id& si, std::vector* migrations) const +{ + +} + +void configuration :: migrations_out(const server_id& sid, std::vector* migrations) const +{ + for (size_t m = 0; m < m_migrations.size(); ++m) + { + const migration& mi(m_migrations[m]); + for (size_t w = 0; w < m_spaces.size(); ++w) + { + const space& s(m_spaces[w]); + if (s.id == mi.space_from) { + for (size_t x = 0; x < s.subspaces.size(); ++x) + { + const subspace& ss(s.subspaces[x]); + for (size_t y = 0; y < ss.regions.size(); ++y) + { + const region& r(ss.regions[y]); + for (size_t z = 0; z < r.replicas.size(); ++z) + { + const replica& rr(r.replicas[z]); + if (rr.si == sid) + { + migrations->push_back(mi); + } + } + } + } + } + } + } +} + void configuration :: lookup_region(const subspace_id& ssid, const std::vector& hashes, diff --git a/common/configuration.h b/common/configuration.h index 437d6bf3d..97e472ecc 100755 --- a/common/configuration.h +++ b/common/configuration.h @@ -79,6 +79,7 @@ class configuration const schema* get_schema(const region_id& ri) const; const subspace* get_subspace(const region_id& ri) const; virtual_server_id get_virtual(const region_id& ri, const server_id& si) const; + space_id space_of(const region_id& ri) const; subspace_id subspace_of(const region_id& ri) const; subspace_id subspace_prev(const subspace_id& ss) const; subspace_id subspace_next(const subspace_id& ss) const; @@ -110,6 +111,11 @@ class configuration void transfers_in_regions(const server_id& s, std::vector* transfers) const; void transfers_out_regions(const server_id& s, std::vector* transfers) const; + // migrations + public: + void migrations_in(const server_id& s, std::vector* migrations) const; + void migrations_out(const server_id& s, std::vector* migrations) const; + // hashing functions public: void lookup_region(const subspace_id& subspace, diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 695a1118c..fb9423990 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -105,6 +105,7 @@ daemon :: daemon() , m_comm(this) , m_repl(this) , m_stm(this) + , m_mm(this) , m_sm(this) , m_config() , m_perf_req_get() @@ -324,6 +325,7 @@ daemon :: run(bool daemonize, m_comm.setup(bind_to, threads); m_repl.setup(); m_stm.setup(); + m_mm.setup(); m_sm.setup(); for (size_t i = 0; i < threads; ++i) @@ -429,6 +431,7 @@ daemon :: run(bool daemonize, << "; pausing all activity while we reconfigure"; m_sm.pause(); m_stm.pause(); + m_mm.pause(); m_repl.pause(); m_data.pause(); m_comm.pause(); @@ -436,12 +439,14 @@ daemon :: run(bool daemonize, m_data.reconfigure(old_config, new_config, m_us); m_repl.reconfigure(old_config, new_config, m_us); m_stm.reconfigure(old_config, new_config, m_us); + m_mm.reconfigure(old_config, new_config, m_us); m_sm.reconfigure(old_config, new_config, m_us); m_config = new_config; m_comm.unpause(); m_data.unpause(); m_repl.unpause(); m_stm.unpause(); + m_mm.unpause(); m_sm.unpause(); LOG(INFO) << "reconfiguration complete; resuming normal operation"; @@ -479,6 +484,7 @@ daemon :: run(bool daemonize, m_sm.teardown(); m_stm.teardown(); + m_mm.teardown(); m_repl.teardown(); m_comm.teardown(); m_data.teardown(); diff --git a/daemon/daemon.h b/daemon/daemon.h index a5dcfaedb..53e9948e5 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -51,6 +51,7 @@ #include "daemon/replication_manager.h" #include "daemon/search_manager.h" #include "daemon/state_transfer_manager.h" +#include "daemon/migration_manager.h" BEGIN_HYPERDEX_NAMESPACE @@ -108,6 +109,7 @@ class daemon friend class replication_manager; friend class search_manager; friend class state_transfer_manager; + friend class migration_manager; private: server_id m_us; @@ -119,6 +121,7 @@ class daemon communication m_comm; replication_manager m_repl; state_transfer_manager m_stm; + migration_manager m_mm; search_manager m_sm; configuration m_config; // counters diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc new file mode 100644 index 000000000..8221d1e1f --- /dev/null +++ b/daemon/migration_manager.cc @@ -0,0 +1,236 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// POSIX +#include + +// STL +#include + +// Google Log +#include + +// HyperDex +#include "common/serialization.h" +#include "daemon/daemon.h" +#include "daemon/datalayer_iterator.h" +#include "daemon/migration_manager.h" +// #include "daemon/migration_manager_pending.h" +// #include "daemon/migration_manager_migration_in_state.h" +#include "daemon/migration_out_state.h" +#include "daemon/leveldb.h" + +using hyperdex::reconfigure_returncode; +using hyperdex::migration_manager; +using hyperdex::migration_id; + +migration_manager :: migration_manager(daemon* d) + : m_daemon(d) + // , m_migrations_in() + , m_migrations_out() + , m_kickstarter(std::tr1::bind(&migration_manager::kickstarter, this)) + , m_block_kickstarter() + , m_wakeup_kickstarter(&m_block_kickstarter) + , m_wakeup_reconfigurer(&m_block_kickstarter) + , m_need_kickstart(false) + , m_shutdown(true) + , m_need_pause(false) + , m_paused(false) +{ +} + +migration_manager :: ~migration_manager() throw () +{ + shutdown(); +} + +bool +migration_manager :: setup() +{ + po6::threads::mutex::hold hold(&m_block_kickstarter); + m_kickstarter.start(); + m_shutdown = false; + return true; +} + +void +migration_manager :: teardown() +{ + shutdown(); + // m_migrations_in.clear(); + m_migrations_out.clear(); +} + +void +migration_manager :: pause() +{ + po6::threads::mutex::hold hold(&m_block_kickstarter); + assert(!m_need_pause); + m_need_pause = true; +} + +void +migration_manager :: unpause() +{ + po6::threads::mutex::hold hold(&m_block_kickstarter); + assert(m_need_pause); + m_wakeup_kickstarter.broadcast(); + m_need_pause = false; + m_need_kickstart = true; +} + +void +migration_manager :: reconfigure(const configuration&, + const configuration& new_config, + const server_id& sid) +{ + { + po6::threads::mutex::hold hold(&m_block_kickstarter); + assert(m_need_pause); + + while (!m_paused) + { + m_wakeup_reconfigurer.wait(); + } + } + + // TODO + // // Setup migrations in + // std::vector migrations_in; + // new_config.migrations_in(m_daemon->m_us, &migrations_in); + // std::sort(migrations_in.begin(), migrations_in.end()); + // setup_migration_state("incoming", migrations_in, &m_migrations_in); + + // Setup migrations out + std::vector migrations_out; + new_config.migrations_out(sid, &migrations_out); + + std::vector regions; + new_config.mapped_regions(sid, ®ions); + + leveldb_snapshot_ptr s = m_daemon->m_data.make_snapshot(); + + std::vector::iterator m_iter; + for (m_iter = migrations_out.begin(); m_iter != migrations_out.end(); m_iter++) { + std::vector::iterator r_iter; + for (r_iter = regions.begin(); r_iter != regions.end(); r_iter++) { + region_id rid = (*r_iter); + if (new_config.space_of(rid) == (*m_iter).space_from) { + datalayer::returncode err; + datalayer::iterator* data_iter = m_daemon->m_data.make_region_iterator(s, rid, &err); + if (err != datalayer::SUCCESS) { + return; + } + } + } + } + + // setup_migration_state("outgoing", migrations_out, &m_migrations_out); +} + +void +migration_manager :: kickstarter() +{ + LOG(INFO) << "state transfer thread started"; + sigset_t ss; + + if (sigfillset(&ss) < 0) + { + PLOG(ERROR) << "sigfillset"; + return; + } + + if (pthread_sigmask(SIG_BLOCK, &ss, NULL) < 0) + { + PLOG(ERROR) << "could not block signals"; + return; + } + + while (true) + { + { + po6::threads::mutex::hold hold(&m_block_kickstarter); + + while ((!m_need_kickstart && !m_shutdown) || m_need_pause) + { + m_paused = true; + + if (m_need_pause) + { + m_wakeup_reconfigurer.signal(); + } + + m_wakeup_kickstarter.wait(); + m_paused = false; + } + + if (m_shutdown) + { + break; + } + + m_need_kickstart = false; + } + + size_t idx = 0; + + // while (true) + // { + // po6::threads::mutex::hold hold(&m_block_kickstarter); + + // if (idx >= m_transfers_out.size()) + // { + // break; + // } + + // po6::threads::mutex::hold hold2(&m_transfers_out[idx]->mtx); + // retransmit(m_transfers_out[idx].get()); + // transfer_more_state(m_transfers_out[idx].get()); + // ++idx; + // } + } + + LOG(INFO) << "state transfer thread shutting down"; +} + +void +migration_manager :: shutdown() +{ + bool is_shutdown; + + { + po6::threads::mutex::hold hold(&m_block_kickstarter); + m_wakeup_kickstarter.broadcast(); + is_shutdown = m_shutdown; + m_shutdown = true; + } + + if (!is_shutdown) + { + m_kickstarter.join(); + } +} diff --git a/daemon/migration_manager.h b/daemon/migration_manager.h new file mode 100644 index 000000000..caefa9857 --- /dev/null +++ b/daemon/migration_manager.h @@ -0,0 +1,137 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef hyperdex_daemon_migration_manager_h_ +#define hyperdex_daemon_migration_manager_h_ + +// STL +#include + +// po6 +#include +#include +#include + +// e +#include + +// HyperDex +#include "namespace.h" +#include "common/configuration.h" +#include "daemon/reconfigure_returncode.h" + +BEGIN_HYPERDEX_NAMESPACE +class daemon; + +class migration_manager +{ + public: + migration_manager(daemon*); + ~migration_manager() throw (); + + public: + bool setup(); + void teardown(); + void pause(); + void unpause(); + void reconfigure(const configuration& old_config, + const configuration& new_config, + const server_id&); + + // public: + // void handshake_syn(const virtual_server_id& from, + // const migration_id& xid); + // void handshake_synack(const server_id& from, + // const virtual_server_id& to, + // const migration_id& xid, + // uint64_t timestamp); + // void handshake_ack(const virtual_server_id& from, + // const migration_id& xid, + // bool wipe); + // void handshake_wiped(const server_id& from, + // const virtual_server_id& to, + // const migration_id& xid); + // void report_wiped(const migration_id& xid); + // void xfer_op(const virtual_server_id& from, + // const migration_id& xid, + // uint64_t seq_no, + // bool has_value, + // uint64_t version, + // std::auto_ptr msg, + // const e::slice& key, + // const std::vector& value); + // void xfer_ack(const server_id& from, + // const virtual_server_id& to, + // const migration_id& xid, + // uint64_t seq_no); + + private: + // class pending; + // class migration_in_state; + class migration_out_state; + + private: + // // get the appropriate state + // migration_in_state* get_mis(const migration_id& mid); + // migration_out_state* get_mos(const migration_id& mid); + // // caller must hold mtx on tos + // void migration_more_state(migration_out_state* tos); + // void retransmit(migration_out_state* tos); + // // caller must hold mtx on tis + // void put_to_disk_and_send_acks(migration_in_state* tis); + // // caller must hold mtx on tos + // // send the last object in tos + // void send_handshake_syn(const migration& xfer); + // void send_handshake_synack(const migration& xfer, uint64_t timestamp); + // void send_handshake_ack(const migration& xfer, bool wipe); + // void send_handshake_wiped(const migration& xfer); + // void send_object(const migration& xfer, pending* op); + // void send_ack(const migration& xfer, uint64_t seq_id); + void kickstarter(); + void shutdown(); + + private: + migration_manager(const migration_manager&); + migration_manager& operator = (const migration_manager&); + + private: + daemon* m_daemon; + // std::vector> m_migrations_in; + std::vector > m_migrations_out; + po6::threads::thread m_kickstarter; + po6::threads::mutex m_block_kickstarter; + po6::threads::cond m_wakeup_kickstarter; + po6::threads::cond m_wakeup_reconfigurer; + bool m_need_kickstart; + bool m_shutdown; + bool m_need_pause; + bool m_paused; +}; + +END_HYPERDEX_NAMESPACE + +#endif // hyperdex_daemon_migration_manager_h_ \ No newline at end of file diff --git a/daemon/migration_out_state.cc b/daemon/migration_out_state.cc new file mode 100644 index 000000000..4677aa6d3 --- /dev/null +++ b/daemon/migration_out_state.cc @@ -0,0 +1,50 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// HyperDex +#include "daemon/datalayer_iterator.h" +#include "daemon/migration_out_state.h" + +using hyperdex::migration_manager; + +migration_manager :: migration_out_state :: migration_out_state(const migration& _mgt) + : mgt(_mgt) + , mtx() + , next_seq_no(1) + // , window() + // , window_sz(1) + , iter() + , handshake_syn(false) + , handshake_ack(false) + , wipe(false) + , m_ref(0) +{ +} + +migration_manager :: migration_out_state :: ~migration_out_state() throw () +{ +} diff --git a/daemon/migration_out_state.h b/daemon/migration_out_state.h new file mode 100644 index 000000000..c3f9f0e4b --- /dev/null +++ b/daemon/migration_out_state.h @@ -0,0 +1,79 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef hyperdex_daemon_migration_manager_migration_out_state_h_ +#define hyperdex_daemon_migration_manager_migration_out_state_h_ + +// STL +#include +#include + +// po6 +#include + +// e +#include + +// HyperDex +#include "daemon/datalayer.h" +#include "daemon/migration_manager.h" + +using hyperdex::migration_manager; + +class migration_manager::migration_out_state +{ + public: + migration_out_state(const migration& xfer); + ~migration_out_state() throw (); + + public: + migration mgt; + po6::threads::mutex mtx; + uint64_t next_seq_no; + // std::list > window; + // size_t window_sz; + std::auto_ptr iter; + bool handshake_syn; // do we know the other end got a syn? + bool handshake_ack; // do we know the other end got a ack? + bool wipe; + + private: + friend class e::intrusive_ptr; + + private: + void inc() { __sync_add_and_fetch(&m_ref, 1); } + void dec() { if (__sync_sub_and_fetch(&m_ref, 1) == 0) delete this; } + + private: + size_t m_ref; + + private: + migration_out_state(const migration_out_state&); + migration_out_state& operator = (const migration_out_state&); +}; + +#endif // hyperdex_daemon_migration_manager_migration_out_state_h_ From 17e532be1088718c6da5fcd1464b67f2c21ce48a Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Tue, 17 Dec 2013 19:35:11 -0500 Subject: [PATCH 03/17] Some shit --- Makefile.am | 32 ++++------------------ daemon/migration_manager.cc | 10 +++++++ tools/{migrate_data.cc => migrate-data.cc} | 0 3 files changed, 16 insertions(+), 26 deletions(-) rename tools/{migrate_data.cc => migrate-data.cc} (100%) diff --git a/Makefile.am b/Makefile.am index ea807a446..ac73988b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -235,8 +235,8 @@ hyperdex_daemon_SOURCES += common/schema.cc hyperdex_daemon_SOURCES += common/serialization.cc hyperdex_daemon_SOURCES += common/server.cc hyperdex_daemon_SOURCES += common/transfer.cc -hyperdex_daemon_SOURCES += cityhash/city.cc hyperdex_daemon_SOURCES += common/migration.cc +hyperdex_daemon_SOURCES += cityhash/city.cc hyperdex_daemon_SOURCES += daemon/communication.cc hyperdex_daemon_SOURCES += daemon/coordinator_link_wrapper.cc hyperdex_daemon_SOURCES += daemon/daemon.cc @@ -394,8 +394,8 @@ libhyperdex_client_la_SOURCES += common/schema.cc libhyperdex_client_la_SOURCES += common/server.cc libhyperdex_client_la_SOURCES += common/serialization.cc libhyperdex_client_la_SOURCES += common/transfer.cc -libhyperdex_client_la_SOURCES += cityhash/city.cc libhyperdex_client_la_SOURCES += common/migration.cc +libhyperdex_client_la_SOURCES += cityhash/city.cc libhyperdex_client_la_SOURCES += client/c.cc libhyperdex_client_la_SOURCES += client/client.cc libhyperdex_client_la_SOURCES += client/datastructures.cc @@ -480,8 +480,8 @@ libhyperdex_admin_la_SOURCES += common/schema.cc libhyperdex_admin_la_SOURCES += common/serialization.cc libhyperdex_admin_la_SOURCES += common/server.cc libhyperdex_admin_la_SOURCES += common/transfer.cc -libhyperdex_admin_la_SOURCES += cityhash/city.cc libhyperdex_admin_la_SOURCES += common/migration.cc +libhyperdex_admin_la_SOURCES += cityhash/city.cc libhyperdex_admin_la_SOURCES += admin/admin.cc libhyperdex_admin_la_SOURCES += admin/backup_state_machine.cc libhyperdex_admin_la_SOURCES += admin/c.cc @@ -723,7 +723,6 @@ endif check_PROGRAMS += test/replication-stress-test check_PROGRAMS += test/search-stress-test -<<<<<<< HEAD shell_wrappers = @@ -964,8 +963,6 @@ EXTRA_DIST += test/ruby/MultiAttribute.rb EXTRA_DIST += test/ruby/RangeSearchInt.rb EXTRA_DIST += test/ruby/RangeSearchString.rb EXTRA_DIST += test/ruby/RegexSearch.rb -======= ->>>>>>> Adding migration-related stuff test_replication_stress_test_SOURCES = test/replication-stress-test.cc test_replication_stress_test_LDADD = libhyperdex-client.la -le @@ -978,7 +975,6 @@ test_search_stress_test_LDADD = libhyperdex-client.la -le ################################################################################ if ENABLE_TOOLS -<<<<<<< HEAD hyperdexexec_PROGRAMS += hyperdex-add-space hyperdexexec_PROGRAMS += hyperdex-rm-space hyperdexexec_PROGRAMS += hyperdex-list-spaces @@ -996,23 +992,7 @@ hyperdexexec_PROGRAMS += hyperdex-wait-until-stable hyperdexexec_PROGRAMS += hyperdex-backup hyperdexexec_PROGRAMS += hyperdex-backup-manager hyperdexexec_PROGRAMS += hyperdex-raw-backup -======= -bin_PROGRAMS += hyperdex-add-space -bin_PROGRAMS += hyperdex-rm-space -bin_PROGRAMS += hyperdex-list-spaces -bin_PROGRAMS += hyperdex-validate-space -bin_PROGRAMS += hyperdex-show-config -bin_PROGRAMS += hyperdex-server-register -bin_PROGRAMS += hyperdex-server-online -bin_PROGRAMS += hyperdex-server-offline -bin_PROGRAMS += hyperdex-server-kill -bin_PROGRAMS += hyperdex-server-forget -bin_PROGRAMS += hyperdex-perf-counters -bin_PROGRAMS += hyperdex-set-read-only -bin_PROGRAMS += hyperdex-set-read-write -bin_PROGRAMS += hyperdex-raw-backup -bin_PROGRAMS += hyperdex-migrate-data ->>>>>>> Adding migration-related stuff +hyperdexexec_PROGRAMS += hyperdex-migrate-data dist_man_MANS += man/hyperdex-add-space.1 dist_man_MANS += man/hyperdex-rm-space.1 dist_man_MANS += man/hyperdex-list-spaces.1 @@ -1201,9 +1181,9 @@ man/hyperdex-raw-backup.1: man/hyperdex-raw-backup.1.h2m tools/raw-backup.cc # hyperdex-migrate-data EXTRA_DIST += man/hyperdex-migrate-data.1.md EXTRA_DIST += man/hyperdex-migrate-data.1.h2m -hyperdex_migrate_data_SOURCES = tools/migrate_data.cc +hyperdex_migrate_data_SOURCES = tools/migrate-data.cc hyperdex_migrate_data_LDADD = libhyperdex-admin.la -lpopt -man/hyperdex-migrate-data.1: man/hyperdex-migrate-data.1.h2m tools/migrate_data.cc +man/hyperdex-migrate-data.1: man/hyperdex-migrate-data.1.h2m tools/migrate-data.cc @$(MAKE) --silent $(AM_MAKEFLAGS) hyperdex-migrate-data$(EXEEXT) $(help2man_verbose)help2man $(HELP2MAN_FLAGS) --section 1 --output $@ --include $< ${abs_top_builddir}/hyperdex-migrate-data$(EXEEXT) diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index 8221d1e1f..fcc9d41fa 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -108,6 +108,7 @@ migration_manager :: reconfigure(const configuration&, const configuration& new_config, const server_id& sid) { + std::cout << "reconfiguring!!!" << std::endl; { po6::threads::mutex::hold hold(&m_block_kickstarter); assert(m_need_pause); @@ -134,21 +135,30 @@ migration_manager :: reconfigure(const configuration&, leveldb_snapshot_ptr s = m_daemon->m_data.make_snapshot(); + int data_counter = 0; std::vector::iterator m_iter; for (m_iter = migrations_out.begin(); m_iter != migrations_out.end(); m_iter++) { + std::cout << "BP1" << std::endl; std::vector::iterator r_iter; for (r_iter = regions.begin(); r_iter != regions.end(); r_iter++) { + std::cout << "BP2" << std::endl; region_id rid = (*r_iter); if (new_config.space_of(rid) == (*m_iter).space_from) { + std::cout << "migrating data!!!" << std::endl; datalayer::returncode err; datalayer::iterator* data_iter = m_daemon->m_data.make_region_iterator(s, rid, &err); if (err != datalayer::SUCCESS) { return; } + while (data_iter->valid()) { + data_counter++; + data_iter->next(); + } } } } + std::cout << "Number of objects: " << data_counter << std::endl; // setup_migration_state("outgoing", migrations_out, &m_migrations_out); } diff --git a/tools/migrate_data.cc b/tools/migrate-data.cc similarity index 100% rename from tools/migrate_data.cc rename to tools/migrate-data.cc From afc85d4044bcfcfc134a4120404bc786687df255 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 23 Jan 2014 15:52:03 -0500 Subject: [PATCH 04/17] Lots of tweaking --- common/configuration.cc | 38 ++++++++-- common/configuration.h | 2 +- common/funcall.cc | 5 ++ daemon/migration_manager.cc | 131 +++++++++++++++++++++++----------- daemon/migration_manager.h | 20 +----- daemon/migration_out_state.cc | 13 +--- daemon/migration_out_state.h | 12 +--- daemon/replication_manager.cc | 7 ++ 8 files changed, 141 insertions(+), 87 deletions(-) diff --git a/common/configuration.cc b/common/configuration.cc index be642ee84..c403fc988 100644 --- a/common/configuration.cc +++ b/common/configuration.cc @@ -472,6 +472,39 @@ configuration :: point_leader(const char* sname, const e::slice& key) const return virtual_server_id(); } +virtual_server_id +configuration :: point_leader(const space_id& sid, const e::slice& key) const +{ + for (size_t s = 0; s < m_spaces.size(); ++s) + { + if (sid != m_spaces[s].id) + { + continue; + } + + uint64_t h; + hash(m_spaces[s].sc, key, &h); + + for (size_t pl = 0; pl < m_spaces[s].subspaces[0].regions.size(); ++pl) + { + if (m_spaces[s].subspaces[0].regions[pl].lower_coord[0] <= h && + h <= m_spaces[s].subspaces[0].regions[pl].upper_coord[0]) + { + if (m_spaces[s].subspaces[0].regions[pl].replicas.empty()) + { + return virtual_server_id(); + } + + return m_spaces[s].subspaces[0].regions[pl].replicas[0].vsi; + } + } + + abort(); + } + + return virtual_server_id(); +} + virtual_server_id configuration :: point_leader(const region_id& rid, const e::slice& key) const { @@ -632,11 +665,6 @@ configuration :: transfers_out_regions(const server_id& si, std::vector* migrations) const -{ - -} - void configuration :: migrations_out(const server_id& sid, std::vector* migrations) const { for (size_t m = 0; m < m_migrations.size(); ++m) diff --git a/common/configuration.h b/common/configuration.h index 97e472ecc..7f16fff88 100755 --- a/common/configuration.h +++ b/common/configuration.h @@ -90,6 +90,7 @@ class configuration void key_regions(const server_id& s, std::vector* servers) const; bool is_point_leader(const virtual_server_id& e) const; virtual_server_id point_leader(const char* space, const e::slice& key) const; + virtual_server_id point_leader(const space_id& sid, const e::slice& key) const; // point leader for this key in the same space as ri virtual_server_id point_leader(const region_id& ri, const e::slice& key) const; // lhs and rhs are in adjacent subspaces such that lhs sends CHAIN_PUT @@ -113,7 +114,6 @@ class configuration // migrations public: - void migrations_in(const server_id& s, std::vector* migrations) const; void migrations_out(const server_id& s, std::vector* migrations) const; // hashing functions diff --git a/common/funcall.cc b/common/funcall.cc index 0a934da8b..ddd12f1df 100644 --- a/common/funcall.cc +++ b/common/funcall.cc @@ -52,6 +52,7 @@ hyperdex :: validate_func(const schema& sc, const funcall& func) { if (func.attr >= sc.attrs_sz) { + std::cout << "sup1" << std::endl; return false; } @@ -59,6 +60,10 @@ hyperdex :: validate_func(const schema& sc, const funcall& func) if (!di || !di->check_args(func)) { + std::cout << __FILE__ ":" << __LINE__ << " attr=" << func.attr << " name=" << func.name << " arg1=" << func.arg1.hex() << " arg1_datatype="< migrations_in; - // new_config.migrations_in(m_daemon->m_us, &migrations_in); - // std::sort(migrations_in.begin(), migrations_in.end()); - // setup_migration_state("incoming", migrations_in, &m_migrations_in); - - // Setup migrations out std::vector migrations_out; new_config.migrations_out(sid, &migrations_out); std::vector regions; new_config.mapped_regions(sid, ®ions); - leveldb_snapshot_ptr s = m_daemon->m_data.make_snapshot(); - - int data_counter = 0; std::vector::iterator m_iter; for (m_iter = migrations_out.begin(); m_iter != migrations_out.end(); m_iter++) { - std::cout << "BP1" << std::endl; + migration_out_state* new_state = NULL; std::vector::iterator r_iter; for (r_iter = regions.begin(); r_iter != regions.end(); r_iter++) { - std::cout << "BP2" << std::endl; region_id rid = (*r_iter); if (new_config.space_of(rid) == (*m_iter).space_from) { - std::cout << "migrating data!!!" << std::endl; - datalayer::returncode err; - datalayer::iterator* data_iter = m_daemon->m_data.make_region_iterator(s, rid, &err); - if (err != datalayer::SUCCESS) { - return; - } - while (data_iter->valid()) { - data_counter++; - data_iter->next(); + if (new_state == NULL) { + new_state = new migration_out_state(); } + new_state->region_iters.push_back(new std::pair((*m_iter).space_to, rid)); } } + if (new_state != NULL) { + e::intrusive_ptr ptr(new_state); + m_migrations_out.push_back(ptr); + } } - - std::cout << "Number of objects: " << data_counter << std::endl; - // setup_migration_state("outgoing", migrations_out, &m_migrations_out); } void migration_manager :: kickstarter() { - LOG(INFO) << "state transfer thread started"; + LOG(INFO) << "migration thread started"; sigset_t ss; if (sigfillset(&ss) < 0) @@ -208,20 +186,87 @@ migration_manager :: kickstarter() size_t idx = 0; - // while (true) - // { - // po6::threads::mutex::hold hold(&m_block_kickstarter); + leveldb_snapshot_ptr snapshot_ptr = m_daemon->m_data.make_snapshot(); - // if (idx >= m_transfers_out.size()) - // { - // break; - // } + while (true) + { + po6::threads::mutex::hold hold(&m_block_kickstarter); - // po6::threads::mutex::hold hold2(&m_transfers_out[idx]->mtx); - // retransmit(m_transfers_out[idx].get()); - // transfer_more_state(m_transfers_out[idx].get()); - // ++idx; - // } + if (idx >= m_migrations_out.size()) + { + break; + } + + po6::threads::mutex::hold hold2(&m_migrations_out[idx]->mtx); + + // send data + migration_out_state* mos = m_migrations_out[idx].get(); + for (size_t i; i < mos->region_iters.size(); i++) { + space_id sid = mos->region_iters[i]->first; + region_id rid = mos->region_iters[i]->second; + datalayer::returncode err; + datalayer::iterator* iter = m_daemon->m_data.make_region_iterator(snapshot_ptr, rid, &err); + if (err != datalayer::SUCCESS) { + LOG(ERROR) << "failed to create region iterator"; + break; + } + + if (iter->valid()) + { + e::slice key; + std::vector val; + uint64_t ver; + datalayer::reference tmp; + m_daemon->m_data.get_from_iterator(rid, iter, &key, &val, &ver, &tmp); + virtual_server_id to = m_daemon->m_config.point_leader(sid, key); + + const schema* sc = m_daemon->m_config.get_schema(rid); + std::vector funcs; + std::vector checks; + funcs.reserve(val.size()); + + for (size_t i = 0; i < val.size(); ++i) + { + uint16_t attrnum = i; + + hyperdatatype datatype = sc->attrs[attrnum + 1].type; + std::cout << "datatype " << i << ": " << datatype << std::endl; + + funcall o; + o.attr = attrnum + 1; + o.name = FUNC_SET; + o.arg1 = val[i]; + o.arg1_datatype = datatype; + funcs.push_back(o); + } + + std::cout << "funcs size: " << funcs.size() << std::endl; + + size_t HEADER_SIZE = BUSYBEE_HEADER_SIZE + + sizeof(uint8_t) /*mt*/ \ + + sizeof(uint8_t) /*flags*/ \ + + sizeof(uint64_t) /*version*/ \ + + sizeof(uint64_t); /*vidt*/ + + size_t sz = HEADER_SIZE + + sizeof(uint64_t) /*nonce*/ + + sizeof(uint8_t) + + pack_size(key) + + pack_size(checks) + + pack_size(funcs); + std::cout << "sent size: " << sz << std::endl; + std::auto_ptr msg(e::buffer::create(sz)); + uint8_t flags = (0 | 0 | 128); + uint64_t nonce = 0; // TODO: what should it be? + msg->pack_at(HEADER_SIZE) + << nonce << key << flags << checks << funcs; + m_daemon->m_comm.send(to, REQ_ATOMIC, msg); + iter->next(); + } + } + + ++idx; + } } LOG(INFO) << "state transfer thread shutting down"; diff --git a/daemon/migration_manager.h b/daemon/migration_manager.h index caefa9857..4684285e5 100644 --- a/daemon/migration_manager.h +++ b/daemon/migration_manager.h @@ -43,6 +43,7 @@ #include "namespace.h" #include "common/configuration.h" #include "daemon/reconfigure_returncode.h" +#include "daemon/datalayer.h" BEGIN_HYPERDEX_NAMESPACE class daemon; @@ -90,27 +91,9 @@ class migration_manager // uint64_t seq_no); private: - // class pending; - // class migration_in_state; class migration_out_state; private: - // // get the appropriate state - // migration_in_state* get_mis(const migration_id& mid); - // migration_out_state* get_mos(const migration_id& mid); - // // caller must hold mtx on tos - // void migration_more_state(migration_out_state* tos); - // void retransmit(migration_out_state* tos); - // // caller must hold mtx on tis - // void put_to_disk_and_send_acks(migration_in_state* tis); - // // caller must hold mtx on tos - // // send the last object in tos - // void send_handshake_syn(const migration& xfer); - // void send_handshake_synack(const migration& xfer, uint64_t timestamp); - // void send_handshake_ack(const migration& xfer, bool wipe); - // void send_handshake_wiped(const migration& xfer); - // void send_object(const migration& xfer, pending* op); - // void send_ack(const migration& xfer, uint64_t seq_id); void kickstarter(); void shutdown(); @@ -120,7 +103,6 @@ class migration_manager private: daemon* m_daemon; - // std::vector> m_migrations_in; std::vector > m_migrations_out; po6::threads::thread m_kickstarter; po6::threads::mutex m_block_kickstarter; diff --git a/daemon/migration_out_state.cc b/daemon/migration_out_state.cc index 4677aa6d3..7cc0ab78f 100644 --- a/daemon/migration_out_state.cc +++ b/daemon/migration_out_state.cc @@ -31,16 +31,9 @@ using hyperdex::migration_manager; -migration_manager :: migration_out_state :: migration_out_state(const migration& _mgt) - : mgt(_mgt) - , mtx() - , next_seq_no(1) - // , window() - // , window_sz(1) - , iter() - , handshake_syn(false) - , handshake_ack(false) - , wipe(false) +migration_manager :: migration_out_state :: migration_out_state() + : mtx() + , region_iters() , m_ref(0) { } diff --git a/daemon/migration_out_state.h b/daemon/migration_out_state.h index c3f9f0e4b..ca8c9ef09 100644 --- a/daemon/migration_out_state.h +++ b/daemon/migration_out_state.h @@ -39,6 +39,7 @@ #include // HyperDex +#include "common/ids.h" #include "daemon/datalayer.h" #include "daemon/migration_manager.h" @@ -47,19 +48,12 @@ using hyperdex::migration_manager; class migration_manager::migration_out_state { public: - migration_out_state(const migration& xfer); + migration_out_state(); ~migration_out_state() throw (); public: - migration mgt; po6::threads::mutex mtx; - uint64_t next_seq_no; - // std::list > window; - // size_t window_sz; - std::auto_ptr iter; - bool handshake_syn; // do we know the other end got a syn? - bool handshake_ack; // do we know the other end got a ack? - bool wipe; + std::vector* > region_iters; private: friend class e::intrusive_ptr; diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index 6fbffb421..becb42c6a 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -246,6 +246,11 @@ replication_manager :: client_atomic(const server_id& from, const region_id ri(m_daemon->m_config.get_region_id(to)); const schema& sc(*m_daemon->m_config.get_schema(ri)); + std::cout << !datatype_info::lookup(sc.attrs[0].type)->validate(key) << std::endl; + std::cout << (validate_attribute_checks(sc, checks) != checks.size()) << std::endl; + std::cout << (validate_funcs(sc, funcs) != funcs.size()) << std::endl; + std::cout << (erase && !funcs.empty()) << std::endl; + if (!datatype_info::lookup(sc.attrs[0].type)->validate(key) || validate_attribute_checks(sc, checks) != checks.size() || validate_funcs(sc, funcs) != funcs.size() || @@ -272,6 +277,7 @@ replication_manager :: client_atomic(const server_id& from, if (!ks->check_against_latest_version(sc, erase, fail_if_not_found, fail_if_found, checks, &nrc)) { respond_to_client(to, from, nonce, nrc); + std::cout << "BP1" << std::endl; return; } @@ -288,6 +294,7 @@ replication_manager :: client_atomic(const server_id& from, if (!ks->put_from_funcs(sc, ri, seq_id, funcs, from, nonce)) { respond_to_client(to, from, nonce, NET_OVERFLOW); + std::cout << "BP2" << std::endl; return; } } From 9aed1489cb56ce9019ca6e633efba4a2e7464f87 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 23 Jan 2014 16:03:54 -0500 Subject: [PATCH 05/17] Update gitignore --- .gitignore | 1 + bindings/python/_hyperdex_admin.pyx | 343 ++++++++++++++++++++++++++++ hyperdex-migrate-data | 228 ------------------ m4/.gitignore | 0 m4/anal_warnings.m4 | 121 ---------- m4/ax_check_compile_flag.m4 | 72 ------ m4/ax_check_link_flag.m4 | 71 ------ m4/ax_check_preproc_flag.m4 | 72 ------ m4/ax_python_devel.m4 | 324 -------------------------- m4/ax_ruby_ext.m4 | 191 ---------------- test-driver | 127 ++++++++++ 11 files changed, 471 insertions(+), 1079 deletions(-) create mode 100644 bindings/python/_hyperdex_admin.pyx delete mode 100755 hyperdex-migrate-data delete mode 100644 m4/.gitignore delete mode 100644 m4/anal_warnings.m4 delete mode 100644 m4/ax_check_compile_flag.m4 delete mode 100644 m4/ax_check_link_flag.m4 delete mode 100644 m4/ax_check_preproc_flag.m4 delete mode 100644 m4/ax_python_devel.m4 delete mode 100644 m4/ax_ruby_ext.m4 create mode 100755 test-driver diff --git a/.gitignore b/.gitignore index f4f91fcb3..b470804f3 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,4 @@ /test/replication-stress-test /test/search-stress-test /ylwrap +hyperdex-migrate-data diff --git a/bindings/python/_hyperdex_admin.pyx b/bindings/python/_hyperdex_admin.pyx new file mode 100644 index 000000000..e132d19b0 --- /dev/null +++ b/bindings/python/_hyperdex_admin.pyx @@ -0,0 +1,343 @@ +# Copyright (c) 2013, Cornell University +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of HyperDex nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from cpython cimport bool + +cdef extern from "stdint.h": + + ctypedef short int int16_t + ctypedef unsigned short int uint16_t + ctypedef int int32_t + ctypedef unsigned int uint32_t + ctypedef long int int64_t + ctypedef unsigned long int uint64_t + ctypedef long unsigned int size_t + +cdef extern from "stdlib.h": + + void* malloc(size_t size) + void free(void* ptr) + +cdef extern from "sys/socket.h": + + ctypedef uint16_t in_port_t + cdef struct sockaddr + +cdef extern from "../../include/hyperdex/admin.h": + + cdef struct hyperdex_admin + + cdef struct hyperdex_admin_perf_counter: + uint64_t id + uint64_t time + char* property + uint64_t measurement + + cdef enum hyperdex_admin_returncode: + HYPERDEX_ADMIN_SUCCESS = 8704 + HYPERDEX_ADMIN_NOMEM = 8768 + HYPERDEX_ADMIN_NONEPENDING = 8769 + HYPERDEX_ADMIN_POLLFAILED = 8770 + HYPERDEX_ADMIN_TIMEOUT = 8771 + HYPERDEX_ADMIN_INTERRUPTED = 8772 + HYPERDEX_ADMIN_COORDFAIL = 8774 + HYPERDEX_ADMIN_SERVERERROR = 8773 + HYPERDEX_ADMIN_INTERNAL = 8829 + HYPERDEX_ADMIN_EXCEPTION = 8830 + HYPERDEX_ADMIN_GARBAGE = 8831 + + hyperdex_admin* hyperdex_admin_create(char* coordinator, uint16_t port) + void hyperdex_admin_destroy(hyperdex_admin* admin) + int64_t hyperdex_admin_add_space(hyperdex_admin* admin, char* description, hyperdex_admin_returncode* status) + int64_t hyperdex_admin_rm_space(hyperdex_admin* admin, char* space, hyperdex_admin_returncode* status) + int64_t hyperdex_admin_dump_config(hyperdex_admin* admin, hyperdex_admin_returncode* status, char** config) + int64_t hyperdex_admin_enable_perf_counters(hyperdex_admin* admin, hyperdex_admin_returncode* status, hyperdex_admin_perf_counter* pc) + void hyperdex_admin_disable_perf_counters(hyperdex_admin* admin) + int64_t hyperdex_admin_loop(hyperdex_admin* admin, int timeout, hyperdex_admin_returncode* status) nogil + +import collections +import struct + +class HyperDexAdminException(Exception): + def __init__(self, status, attr=None): + self._status = status + self._s = {HYPERDEX_ADMIN_SUCCESS: 'Success' + ,HYPERDEX_ADMIN_NOMEM: 'Memory allocation failed' + ,HYPERDEX_ADMIN_NONEPENDING: 'None pending' + ,HYPERDEX_ADMIN_POLLFAILED: 'Polling Failed' + ,HYPERDEX_ADMIN_TIMEOUT: 'Timeout' + ,HYPERDEX_ADMIN_INTERRUPTED: 'Interrupted by a signal' + ,HYPERDEX_ADMIN_COORDFAIL: 'Coordinator Failure' + ,HYPERDEX_ADMIN_SERVERERROR: 'Server Error' + ,HYPERDEX_ADMIN_INTERNAL: 'Internal Error (file a bug)' + ,HYPERDEX_ADMIN_EXCEPTION: 'Internal Exception (file a bug)' + ,HYPERDEX_ADMIN_GARBAGE: 'Internal Corruption (file a bug)' + }.get(status, 'Unknown Error (file a bug)') + self.e = {HYPERDEX_ADMIN_SUCCESS: 'HYPERDEX_ADMIN_SUCCESS' + ,HYPERDEX_ADMIN_NOMEM: 'HYPERDEX_ADMIN_NOMEM' + ,HYPERDEX_ADMIN_NONEPENDING: 'HYPERDEX_ADMIN_NONEPENDING' + ,HYPERDEX_ADMIN_POLLFAILED: 'HYPERDEX_ADMIN_POLLFAILED' + ,HYPERDEX_ADMIN_TIMEOUT: 'HYPERDEX_ADMIN_TIMEOUT' + ,HYPERDEX_ADMIN_INTERRUPTED: 'HYPERDEX_ADMIN_INTERRUPTED' + ,HYPERDEX_ADMIN_COORDFAIL: 'HYPERDEX_ADMIN_COORDFAIL' + ,HYPERDEX_ADMIN_SERVERERROR: 'HYPERDEX_ADMIN_SERVERERROR' + ,HYPERDEX_ADMIN_INTERNAL: 'HYPERDEX_ADMIN_INTERNAL' + ,HYPERDEX_ADMIN_EXCEPTION: 'HYPERDEX_ADMIN_EXCEPTION' + ,HYPERDEX_ADMIN_GARBAGE: 'HYPERDEX_ADMIN_GARBAGE' + }.get(status, 'BUG') + + def status(self): + return self._status + + def symbol(self): + return self._e + + def __str__(self): + return 'HyperDexAdminException(%s, %s)' % (self._e, self._s) + + def __repr__(self): + return str(self) + + def __eq__(self, other): + if self.__class__ != other.__class__: + return False + return self._status == other._status + + def __ne__(self, other): + return not (self == other) + +cdef class DeferredAddSpace: + + cdef Admin _admin + cdef int64_t _reqid + cdef hyperdex_admin_returncode _status + cdef bint _finished + + def __cinit__(self, Admin admin, bytes space): + self._admin = admin + self._reqid = 0 + self._status = HYPERDEX_ADMIN_GARBAGE + self._finished = False + self._reqid = hyperdex_admin_add_space(self._admin._admin, + space, &self._status) + if self._reqid < 0: + raise HyperDexAdminException(self._status) + self._admin._ops[self._reqid] = self + + def _callback(self): + self._finished = True + del self._admin._ops[self._reqid] + + def wait(self): + while not self._finished and self._reqid > 0: + self._admin.loop() + self._finished = True + if self._status == HYPERDEX_ADMIN_SUCCESS: + return True + else: + raise HyperDexAdminException(self._status) + +cdef class DeferredRmSpace: + + cdef Admin _admin + cdef int64_t _reqid + cdef hyperdex_admin_returncode _status + cdef bint _finished + + def __cinit__(self, Admin admin, bytes space): + self._admin = admin + self._reqid = 0 + self._status = HYPERDEX_ADMIN_GARBAGE + self._finished = False + self._reqid = hyperdex_admin_rm_space(self._admin._admin, + space, &self._status) + if self._reqid < 0: + raise HyperDexAdminException(self._status) + self._admin._ops[self._reqid] = self + + def _callback(self): + self._finished = True + del self._admin._ops[self._reqid] + + def wait(self): + while not self._finished and self._reqid > 0: + self._admin.loop() + self._finished = True + if self._status == HYPERDEX_ADMIN_SUCCESS: + return True + else: + raise HyperDexAdminException(self._status) + +cdef class DeferredString: + + cdef Admin _admin + cdef int64_t _reqid + cdef hyperdex_admin_returncode _status + cdef char* _cstr + cdef str _pstr + cdef bint _finished + + def __cinit__(self, Admin admin, *args): + self._admin = admin + self._reqid = 0 + self._status = HYPERDEX_ADMIN_GARBAGE + self._cstr = NULL + self._pstr = "" + self._finished = False + self._reqid = hyperdex_admin_dump_config(self._admin._admin, + &self._status, + &self._cstr) + if self._reqid < 0: + raise HyperDexAdminException(self._status) + self._admin._ops[self._reqid] = self + + def _callback(self): + if self._cstr: + self._pstr = self._cstr + self._finished = True + del self._admin._ops[self._reqid] + + def wait(self): + while not self._finished and self._reqid > 0: + self._admin.loop() + self._finished = True + if self._status == HYPERDEX_ADMIN_SUCCESS: + ret = {'cluster': 0, 'version': 0, 'servers': []} + for line in self._pstr.split('\n'): + if line.startswith('cluster'): + ret['cluster'] = int(line.split(' ')[1]) + if line.startswith('version'): + ret['version'] = int(line.split(' ')[1]) + if line.startswith('server'): + sid, loc, state = line.split(' ')[1:] + server = {'id': sid, 'location': loc, 'state': state} + ret['servers'].append(server) + return ret + else: + raise HyperDexAdminException(self._status) + +cdef class DeferredPerfCounter: + + cdef Admin _admin + cdef int64_t _reqid + cdef hyperdex_admin_returncode _status + cdef hyperdex_admin_perf_counter _pc + cdef bint _finished + cdef list _backlogged + + def __cinit__(self, Admin admin, *args): + self._admin = admin + self._reqid = 0 + self._status = HYPERDEX_ADMIN_GARBAGE + self._finished = False + self._backlogged = [] + + def __iter__(self): + return self + + def __next__(self): + while not self._finished and not self._backlogged: + self._admin.loop() + if self._backlogged: + return self._backlogged.pop() + raise StopIteration() + + def _callback(self): + if self._status == HYPERDEX_ADMIN_SUCCESS: + self._backlogged.append({'server': self._pc.id + ,'time': self._pc.time + ,'property': self._pc.property + ,'measurement': self._pc.measurement}) + else: + self._backlogged.append(HyperDexAdminException(self._status)) + +cdef class Admin: + cdef hyperdex_admin* _admin + cdef dict _ops + cdef DeferredPerfCounter _pc + + def __cinit__(self, address, port): + self._admin = hyperdex_admin_create(address, port) + self._ops = {} + self._pc = None + + def __dealloc__(self): + if self._admin: + hyperdex_admin_destroy(self._admin) + + def async_dump_config(self): + return DeferredString(self) + + def dump_config(self): + return self.async_dump_config().wait() + + def async_add_space(self, space): + return DeferredAddSpace(self, space) + + def add_space(self, space): + return self.async_add_space(space).wait() + + def async_rm_space(self, space): + return DeferredRmSpace(self, space) + + def rm_space(self, space): + return self.async_rm_space(space).wait() + + def enable_perf_counters(self): + cdef hyperdex_admin_returncode rc + if self._pc: + return self._pc + self._pc = DeferredPerfCounter(self) + self._pc._reqid = hyperdex_admin_enable_perf_counters(self._admin, + &self._pc._status, + &self._pc._pc) + if self._pc._reqid < 0: + rc = self._pc._status + self._pc = None + raise HyperDexAdminException(rc) + self._ops[self._pc._reqid] = self._pc + return self._pc + + def disable_perf_counters(self): + hyperdex_admin_disable_perf_counters(self._admin) + self._pc._finished = True + del self._ops[self._pc._reqid] + self._pc = None + + def loop(self): + cdef hyperdex_admin_returncode rc + with nogil: + ret = hyperdex_admin_loop(self._admin, -1, &rc) + if ret < 0: + raise HyperDexAdminException(rc) + else: + assert ret in self._ops + op = self._ops[ret] + # We cannot refer to self._ops[ret] after this call as + # _callback() may remove ret from self._ops. + op._callback() + return op diff --git a/hyperdex-migrate-data b/hyperdex-migrate-data deleted file mode 100755 index 7e52a1e1e..000000000 --- a/hyperdex-migrate-data +++ /dev/null @@ -1,228 +0,0 @@ -#! /bin/bash - -# hyperdex-migrate-data - temporary wrapper script for .libs/hyperdex-migrate-data -# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu1 -# -# The hyperdex-migrate-data program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="(cd /media/Work_Study/CS/workspace/HyperDex/HyperDex; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/derek/.rvm/gems/ruby-2.0.0-p0/bin:/home/derek/.rvm/gems/ruby-2.0.0-p0@global/bin:/home/derek/.rvm/rubies/ruby-2.0.0-p0/bin:/home/derek/.rvm/bin:/usr/lib/mipsel-linux/bin:/usr/local/heroku/bin:/home/derek/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/go/bin:/home/derek/go/bin:/home/derek/Dropbox/CS/workspace/go:/usr/lib/scala/bin:/usr/lib/akka/bin:/media/Work_Study/CS/workspace/Play:/home/derek/.cabal/bin:/usr/lib/vertx/bin:/usr/lib/jvm/jdk1.7.0/bin:/home/derek/Dropbox/CS/workspace/go/bin; export PATH; g++ -fvisibility=hidden -fvisibility-inlines-hidden -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -g -O2 -o \$progdir/\$file tools/migrate_data.o ./.libs/libhyperdex-admin.so /usr/lib/x86_64-linux-gnu/libpopt.so -Wl,-rpath -Wl,/media/Work_Study/CS/workspace/HyperDex/HyperDex/.libs)" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.2' - notinst_deplibs=' libhyperdex-admin.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="$0" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options which match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ./libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=$0 - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "hyperdex-migrate-data:hyperdex-migrate-data:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu1" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "hyperdex-migrate-data:hyperdex-migrate-data:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "hyperdex-migrate-data:hyperdex-migrate-data:${LINENO}: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "$0: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "$0" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program=lt-'hyperdex-migrate-data' - progdir="$thisdir/.libs" - - if test ! -f "$progdir/$program" || - { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \ - test "X$file" != "X$progdir/$program"; }; then - - file="$$-$program" - - if test ! -d "$progdir"; then - mkdir "$progdir" - else - rm -f "$progdir/$file" - fi - - # relink executable if necessary - if test -n "$relink_command"; then - if relink_command_output=`eval $relink_command 2>&1`; then : - else - printf %s\n "$relink_command_output" >&2 - rm -f "$progdir/$file" - exit 1 - fi - fi - - mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || - { rm -f "$progdir/$program"; - mv -f "$progdir/$file" "$progdir/$program"; } - rm -f "$progdir/$file" - fi - - if test -f "$progdir/$program"; then - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/m4/.gitignore b/m4/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/m4/anal_warnings.m4 b/m4/anal_warnings.m4 deleted file mode 100644 index a5f13066c..000000000 --- a/m4/anal_warnings.m4 +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (c) 2012-2013, Robert Escriva -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of this project nor the names of its contributors may -# be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# This macro enables many compiler warnings for C++ that generally catch bugs in -# code. It offers the "--enable-wanal-flags" option which defaults to "no". - -AC_DEFUN([ANAL_WARNINGS], - [WANAL_CFLAGS="" - WANAL_CXXFLAGS="" - WANAL_CFLAGS_ONLY="" - AC_ARG_ENABLE([wanal-flags], - [AS_HELP_STRING([--enable-wanal-flags], [enable many warnings @<:@default: no@:>@])], - [wanal_flags=${enableval}], [wanal_flags=no]) - if test x"${wanal_flags}" = xyes; then - AX_CHECK_COMPILE_FLAG([-pedantic],[WANAL_CFLAGS="${WANAL_CFLAGS} -pedantic"],,) - AX_CHECK_COMPILE_FLAG([-Wabi],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wabi"],,) - AX_CHECK_COMPILE_FLAG([-Waddress],[WANAL_CFLAGS="${WANAL_CFLAGS} -Waddress"],,) - AX_CHECK_COMPILE_FLAG([-Wall],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wall"],,) - AX_CHECK_COMPILE_FLAG([-Warray-bounds],[WANAL_CFLAGS="${WANAL_CFLAGS} -Warray-bounds"],,) - AX_CHECK_COMPILE_FLAG([-Wc++0x-compat],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wc++0x-compat"],,) - AX_CHECK_COMPILE_FLAG([-Wcast-align],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wcast-align"],,) - AX_CHECK_COMPILE_FLAG([-Wcast-qual],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wcast-qual"],,) - AX_CHECK_COMPILE_FLAG([-Wchar-subscripts],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wchar-subscripts"],,) - AX_CHECK_COMPILE_FLAG([-Wclobbered],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wclobbered"],,) - AX_CHECK_COMPILE_FLAG([-Wcomment],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wcomment"],,) - #AX_CHECK_COMPILE_FLAG([-Wconversion],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wconversion"],,) - AX_CHECK_COMPILE_FLAG([-Wctor-dtor-privacy],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wctor-dtor-privacy"],,) - AX_CHECK_COMPILE_FLAG([-Wdisabled-optimization],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wdisabled-optimization"],,) - AX_CHECK_COMPILE_FLAG([-Weffc++],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Weffc++"],,) - AX_CHECK_COMPILE_FLAG([-Wempty-body],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wempty-body"],,) - AX_CHECK_COMPILE_FLAG([-Wenum-compare],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wenum-compare"],,) - AX_CHECK_COMPILE_FLAG([-Wextra],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wextra"],,) - AX_CHECK_COMPILE_FLAG([-Wfloat-equal],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wfloat-equal"],,) - AX_CHECK_COMPILE_FLAG([-Wformat=2],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wformat=2"],,) - AX_CHECK_COMPILE_FLAG([-Wformat-nonliteral],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wformat-nonliteral"],,) - AX_CHECK_COMPILE_FLAG([-Wformat-security],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wformat-security"],,) - AX_CHECK_COMPILE_FLAG([-Wformat],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wformat"],,) - AX_CHECK_COMPILE_FLAG([-Wformat-y2k],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wformat-y2k"],,) - dnl AX_CHECK_COMPILE_FLAG([-Wframe-larger-than=8192],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wframe-larger-than=8192"],,) - AX_CHECK_COMPILE_FLAG([-Wignored-qualifiers],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wignored-qualifiers"],,) - AX_CHECK_COMPILE_FLAG([-Wimplicit],[WANAL_CFLAGS_ONLY="${WANAL_CFLAGS} -Wimplicit"],,) - AX_CHECK_COMPILE_FLAG([-Winit-self],[WANAL_CFLAGS="${WANAL_CFLAGS} -Winit-self"],,) - AX_CHECK_COMPILE_FLAG([-Winline],[WANAL_CFLAGS="${WANAL_CFLAGS} -Winline"],,) - AX_CHECK_COMPILE_FLAG([-Wlarger-than=4096],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wlarger-than=4096"],,) - AX_CHECK_COMPILE_FLAG([-Wlogical-op],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wlogical-op"],,) - AX_CHECK_COMPILE_FLAG([-Wmain],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wmain"],,) - AX_CHECK_COMPILE_FLAG([-Wmissing-braces],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wmissing-braces"],,) - #AX_CHECK_COMPILE_FLAG([-Wmissing-declarations],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wmissing-declarations"],,) - AX_CHECK_COMPILE_FLAG([-Wmissing-field-initializers],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wmissing-field-initializers"],,) - AX_CHECK_COMPILE_FLAG([-Wmissing-format-attribute],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wmissing-format-attribute"],,) - AX_CHECK_COMPILE_FLAG([-Wmissing-include-dirs],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wmissing-include-dirs"],,) - dnl AX_CHECK_COMPILE_FLAG([-Wmissing-noreturn],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wmissing-noreturn"],,) - AX_CHECK_COMPILE_FLAG([-Wno-long-long],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wno-long-long"],,) - AX_CHECK_COMPILE_FLAG([-Wnon-virtual-dtor],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wnon-virtual-dtor"],,) - #AX_CHECK_COMPILE_FLAG([-Wold-style-cast],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wold-style-cast"],,) - AX_CHECK_COMPILE_FLAG([-Woverlength-strings],[WANAL_CFLAGS="${WANAL_CFLAGS} -Woverlength-strings"],,) - AX_CHECK_COMPILE_FLAG([-Woverloaded-virtual],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Woverloaded-virtual"],,) - AX_CHECK_COMPILE_FLAG([-Wpacked-bitfield-compat],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wpacked-bitfield-compat"],,) - AX_CHECK_COMPILE_FLAG([-Wpacked],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wpacked"],,) - #AX_CHECK_COMPILE_FLAG([-Wpadded],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wpadded"],,) - AX_CHECK_COMPILE_FLAG([-Wparentheses],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wparentheses"],,) - AX_CHECK_COMPILE_FLAG([-Wpointer-arith],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wpointer-arith"],,) - AX_CHECK_COMPILE_FLAG([-Wredundant-decls],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wredundant-decls"],,) - AX_CHECK_COMPILE_FLAG([-Wreorder],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wreorder"],,) - AX_CHECK_COMPILE_FLAG([-Wreturn-type],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wreturn-type"],,) - AX_CHECK_COMPILE_FLAG([-Wsequence-point],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wsequence-point"],,) - AX_CHECK_COMPILE_FLAG([-Wshadow],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wshadow"],,) - AX_CHECK_COMPILE_FLAG([-Wsign-compare],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wsign-compare"],,) - #AX_CHECK_COMPILE_FLAG([-Wsign-conversion],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wsign-conversion"],,) - AX_CHECK_COMPILE_FLAG([-Wsign-promo],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wsign-promo"],,) - AX_CHECK_COMPILE_FLAG([-Wstack-protector],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wstack-protector"],,) - AX_CHECK_COMPILE_FLAG([-Wstrict-aliasing=3],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wstrict-aliasing=3"],,) - AX_CHECK_COMPILE_FLAG([-Wstrict-aliasing],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wstrict-aliasing"],,) - AX_CHECK_COMPILE_FLAG([-Wstrict-null-sentinel],[WANAL_CXXFLAGS="${WANAL_CXXFLAGS} -Wstrict-null-sentinel"],,) - #AX_CHECK_COMPILE_FLAG([-Wstrict-overflow=4],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wstrict-overflow=4"],,) - #AX_CHECK_COMPILE_FLAG([-Wstrict-overflow],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wstrict-overflow"],,) - AX_CHECK_COMPILE_FLAG([-Wswitch-default],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wswitch-default"],,) - AX_CHECK_COMPILE_FLAG([-Wswitch-enum],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wswitch-enum"],,) - AX_CHECK_COMPILE_FLAG([-Wswitch],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wswitch"],,) - AX_CHECK_COMPILE_FLAG([-Wtrigraphs],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wtrigraphs"],,) - AX_CHECK_COMPILE_FLAG([-Wtype-limits],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wtype-limits"],,) - AX_CHECK_COMPILE_FLAG([-Wundef],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wundef"],,) - AX_CHECK_COMPILE_FLAG([-Wuninitialized],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wuninitialized"],,) - AX_CHECK_COMPILE_FLAG([-Wunsafe-loop-optimizations],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wunsafe-loop-optimizations"],,) - AX_CHECK_COMPILE_FLAG([-Wunused-function],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wunused-function"],,) - AX_CHECK_COMPILE_FLAG([-Wunused-label],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wunused-label"],,) - AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wunused-parameter"],,) - AX_CHECK_COMPILE_FLAG([-Wunused-value],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wunused-value"],,) - AX_CHECK_COMPILE_FLAG([-Wunused-variable],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wunused-variable"],,) - AX_CHECK_COMPILE_FLAG([-Wunused],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wunused"],,) - AX_CHECK_COMPILE_FLAG([-Wvolatile-register-var],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wvolatile-register-var"],,) - AX_CHECK_COMPILE_FLAG([-Wwrite-strings],[WANAL_CFLAGS="${WANAL_CFLAGS} -Wwrite-strings"],,) - fi - WANAL_CXXFLAGS="${WANAL_CFLAGS} ${WANAL_CXXFLAGS}" - WANAL_CFLAGS="${WANAL_CFLAGS} ${WANAL_CFLAGS_ONLY}" - AC_SUBST([WANAL_CFLAGS], [${WANAL_CFLAGS}]) - AC_SUBST([WANAL_CXXFLAGS], [${WANAL_CXXFLAGS}]) -]) diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 deleted file mode 100644 index c3a8d695a..000000000 --- a/m4/ax_check_compile_flag.m4 +++ /dev/null @@ -1,72 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the current language's compiler -# or gives an error. (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the current language's default -# flags (e.g. CFLAGS) when the check is done. The check is thus made with -# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to -# force the compiler to issue an error when a bad flag is given. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 2 - -AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ - ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS - _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 deleted file mode 100644 index e2d0d363e..000000000 --- a/m4/ax_check_link_flag.m4 +++ /dev/null @@ -1,71 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the linker or gives an error. -# (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the linker's default flags -# when the check is done. The check is thus made with the flags: "LDFLAGS -# EXTRA-FLAGS FLAG". This can for example be used to force the linker to -# issue an error when a bad flag is given. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 2 - -AC_DEFUN([AX_CHECK_LINK_FLAG], -[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl -AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ - ax_check_save_flags=$LDFLAGS - LDFLAGS="$LDFLAGS $4 $1" - AC_LINK_IFELSE([AC_LANG_PROGRAM()], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - LDFLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_LINK_FLAGS diff --git a/m4/ax_check_preproc_flag.m4 b/m4/ax_check_preproc_flag.m4 deleted file mode 100644 index b1cfef6b8..000000000 --- a/m4/ax_check_preproc_flag.m4 +++ /dev/null @@ -1,72 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the current language's -# preprocessor or gives an error. (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the preprocessor's default -# flags when the check is done. The check is thus made with the flags: -# "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the -# preprocessor to issue an error when a bad flag is given. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 2 - -AC_DEFUN([AX_CHECK_PREPROC_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [ - ax_check_save_flags=$CPPFLAGS - CPPFLAGS="$CPPFLAGS $4 $1" - AC_PREPROC_IFELSE([AC_LANG_PROGRAM()], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - CPPFLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_PREPROC_FLAGS diff --git a/m4/ax_python_devel.m4 b/m4/ax_python_devel.m4 deleted file mode 100644 index cf2163c9b..000000000 --- a/m4/ax_python_devel.m4 +++ /dev/null @@ -1,324 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PYTHON_DEVEL([version]) -# -# DESCRIPTION -# -# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it -# in your configure.ac. -# -# This macro checks for Python and tries to get the include path to -# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) -# output variables. It also exports $(PYTHON_EXTRA_LIBS) and -# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. -# -# You can search for some particular version of Python by passing a -# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please -# note that you *have* to pass also an operator along with the version to -# match, and pay special attention to the single quotes surrounding the -# version number. Don't use "PYTHON_VERSION" for this: that environment -# variable is declared as precious and thus reserved for the end-user. -# -# This macro should work for all versions of Python >= 2.1.0. As an end -# user, you can disable the check for the python version by setting the -# PYTHON_NOVERSIONCHECK environment variable to something else than the -# empty string. -# -# If you need to use this macro for an older Python version, please -# contact the authors. We're always open for feedback. -# -# LICENSE -# -# Copyright (c) 2009 Sebastian Huber -# Copyright (c) 2009 Alan W. Irwin -# Copyright (c) 2009 Rafael Laboissiere -# Copyright (c) 2009 Andrew Collier -# Copyright (c) 2009 Matteo Settenvini -# Copyright (c) 2009 Horst Knorr -# Copyright (c) 2013 Daniel Mullner -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 16 - -AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) -AC_DEFUN([AX_PYTHON_DEVEL],[ - # - # Allow the use of a (user set) custom python version - # - AC_ARG_VAR([PYTHON_VERSION],[The installed Python - version to use, for example '2.3'. This string - will be appended to the Python interpreter - canonical name.]) - - AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) - if test -z "$PYTHON"; then - AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) - PYTHON_VERSION="" - fi - - # - # Check for a version of Python >= 2.1.0 - # - AC_MSG_CHECKING([for a version of Python >= '2.1.0']) - ac_supports_python_ver=`$PYTHON -c "import sys; \ - ver = sys.version.split ()[[0]]; \ - print (ver >= '2.1.0')"` - if test "$ac_supports_python_ver" != "True"; then - if test -z "$PYTHON_NOVERSIONCHECK"; then - AC_MSG_RESULT([no]) - AC_MSG_FAILURE([ -This version of the AC@&t@_PYTHON_DEVEL macro -doesn't work properly with versions of Python before -2.1.0. You may need to re-run configure, setting the -variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, -PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. -Moreover, to disable this check, set PYTHON_NOVERSIONCHECK -to something else than an empty string. -]) - else - AC_MSG_RESULT([skip at user request]) - fi - else - AC_MSG_RESULT([yes]) - fi - - # - # if the macro parameter ``version'' is set, honour it - # - if test -n "$1"; then - AC_MSG_CHECKING([for a version of Python $1]) - ac_supports_python_ver=`$PYTHON -c "import sys; \ - ver = sys.version.split ()[[0]]; \ - print (ver $1)"` - if test "$ac_supports_python_ver" = "True"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_ERROR([this package requires Python $1. -If you have it installed, but it isn't the default Python -interpreter in your system path, please pass the PYTHON_VERSION -variable to configure. See ``configure --help'' for reference. -]) - PYTHON_VERSION="" - fi - fi - - # - # Check if you have distutils, else fail - # - AC_MSG_CHECKING([for the distutils Python package]) - ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` - if test -z "$ac_distutils_result"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_ERROR([cannot import Python module "distutils". -Please check your Python installation. The error was: -$ac_distutils_result]) - PYTHON_VERSION="" - fi - - # - # Check for Python include path - # - AC_MSG_CHECKING([for Python include path]) - if test -z "$PYTHON_CPPFLAGS"; then - python_path=`$PYTHON -c "import distutils.sysconfig; \ - print (distutils.sysconfig.get_python_inc ());"` - plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ - print (distutils.sysconfig.get_python_inc (plat_specific=1));"` - if test -n "${python_path}"; then - if test "${plat_python_path}" != "${python_path}"; then - python_path="-I$python_path -I$plat_python_path" - else - python_path="-I$python_path" - fi - fi - PYTHON_CPPFLAGS=$python_path - fi - AC_MSG_RESULT([$PYTHON_CPPFLAGS]) - AC_SUBST([PYTHON_CPPFLAGS]) - - # - # Check for Python library path - # - AC_MSG_CHECKING([for Python library path]) - if test -z "$PYTHON_LDFLAGS"; then - # (makes two attempts to ensure we've got a version number - # from the interpreter) - ac_python_version=`cat<]], - [[Py_Initialize();]]) - ],[pythonexists=yes],[pythonexists=no]) - AC_LANG_POP([C]) - # turn back to default flags - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - - AC_MSG_RESULT([$pythonexists]) - - if test ! "x$pythonexists" = "xyes"; then - AC_MSG_FAILURE([ - Could not link test program to Python. Maybe the main Python library has been - installed in some non-standard library path. If so, pass it to configure, - via the LDFLAGS environment variable. - Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" - ============================================================================ - ERROR! - You probably have to install the development version of the Python package - for your distribution. The exact name of this package varies among them. - ============================================================================ - ]) - PYTHON_VERSION="" - fi - - # - # all done! - # -]) diff --git a/m4/ax_ruby_ext.m4 b/m4/ax_ruby_ext.m4 deleted file mode 100644 index 8d5e5b0d1..000000000 --- a/m4/ax_ruby_ext.m4 +++ /dev/null @@ -1,191 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_ruby_ext.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_RUBY_EXT -# -# DESCRIPTION -# -# Fetches the linker flags and C compiler flags for compiling and linking -# Ruby binary extensions. The macro substitutes RUBY_VERSION, -# RUBY_EXT_INC, RUBY_EXT_LIB, RUBY_EXT_CPPFLAGS, RUBY_EXT_LDFLAGS and -# RUBY_EXT_DLEXT variables if Ruby executable has been found. It also -# checks the same variables before trying to retrieve them from the Ruby -# configuration. -# -# RUBY_VERSION: version of the Ruby interpreter -# RUBY_EXT_INC: Ruby include directory -# RUBY_EXT_LIB: Ruby extensions destination directory -# RUBY_EXT_CPPFLAGS: C preprocessor flags to compile extensions -# RUBY_EXT_LDFLAGS: linker flags to build extensions -# RUBY_EXT_DLEXT: extensions suffix for ruby modules (e.g. "so") -# -# Examples: -# -# AX_RUBY_EXT -# if test x"$RUBY" = x; then -# AC_ERROR(["cannot find Ruby"]) -# fi -# -# LICENSE -# -# Copyright (c) 2011 Stanislav Sedov -# Copyright (c) 2013 Robert Escriva -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. - -#serial 1 - -AC_DEFUN([AX_RUBY_EXT],[ - - # - # Check if ruby executable exists. - # - AC_PATH_PROGS(RUBY, ["${RUBY-ruby}"], []) - - if test -n "$RUBY" ; then - - AC_MSG_NOTICE([Ruby executable: '$RUBY']) - - # - # Check Ruby version. - # - AC_MSG_CHECKING([for Ruby version]) - [RUBY_VERSION=`$RUBY -e 'puts RUBY_VERSION'`]; - AC_MSG_RESULT([$RUBY_VERSION]) - AC_SUBST(RUBY_VERSION) - - # - # Check for Ruby extensions include path. - # - AC_ARG_VAR(RUBY_EXT_INC, [Directory to include ruby headers from]) - AC_MSG_CHECKING([for Ruby headers include path]) - if test -z "$RUBY_EXT_INC" ; then - [RUBY_EXT_INC=`$RUBY -rrbconfig -e 'puts RbConfig::CONFIG["rubyhdrdir"]'`]; - fi - AC_MSG_RESULT([$RUBY_EXT_INC]) - AC_SUBST(RUBY_EXT_INC) - - # - # Check for Ruby config.h include path. - # - AC_ARG_VAR(RUBY_EXT_ARCHINC, [Another directory to include ruby headers from]) - AC_MSG_CHECKING([for other Ruby headers include path]) - if test -z "$RUBY_EXT_ARCHINC" ; then - [RUBY_EXT_ARCHINC=`$RUBY -rrbconfig -e 'puts RbConfig::CONFIG["rubyhdrdir"] + "/" + RbConfig::CONFIG["arch"]'`]; - fi - AC_MSG_RESULT([$RUBY_EXT_ARCHINC]) - AC_SUBST(RUBY_EXT_ARCHINC) - - # - # Check for Ruby CPP flags. - # - AC_ARG_VAR(RUBY_EXT_CPPFLAGS, [CPPFLAGS to compile Ruby extensions]) - AC_MSG_CHECKING([for Ruby extensions C preprocessor flags]) - if test -z "$RUBY_EXT_CPPFLAGS" ; then - [RUBY_EXT_CPPFLAGS=`$RUBY -rrbconfig -e 'puts RbConfig::CONFIG["CPPFLAGS"]'`]; - fi - AC_MSG_RESULT([$RUBY_EXT_CPPFLAGS]) - AC_SUBST(RUBY_EXT_CPPFLAGS) - - # - # Check for Ruby extensions link flags. - # - AC_ARG_VAR(RUBY_EXT_LDFLAGS, [LDFLAGS to build Ruby extensions]) - AC_MSG_CHECKING([for Ruby extensions linker flags]) - if test -z "$RUBY_EXT_LDFLAGS" ; then - [RUBY_EXT_LDFLAGS=`$RUBY -rrbconfig -e 'puts RbConfig::CONFIG["LDFLAGS"]'`]; - fi - # Fix LDFLAGS for OS X. We don't want any -arch flags here, otherwise - # linking might fail. We also including the proper flags to create a bundle. - case "$host" in - *darwin*) - RUBY_EXT_LDFLAGS=`echo ${RUBY_EXT_LDFLAGS} | sed -e "s,-arch [[^ ]]*,,g"` - RUBY_EXT_LDFLAGS="${RUBY_EXT_LDFLAGS} -bundle -undefined dynamic_lookup" - ;; - esac - AC_MSG_RESULT([$RUBY_EXT_LDFLAGS]) - AC_SUBST(RUBY_EXT_LDFLAGS) - - # - # Check for Ruby dynamic library extension. - # - AC_ARG_VAR(RUBY_EXT_DLEXT, [Ruby dynamic library extension]) - AC_MSG_CHECKING([for Ruby dynamic library extension]) - if test -z "$RUBY_EXT_DLEXT" ; then - [RUBY_EXT_DLEXT=`$RUBY -rrbconfig -e 'puts RbConfig::CONFIG["DLEXT"]'`]; - RUBY_EXT_DLEXT=".${RUBY_EXT_DLEXT}" - fi - AC_MSG_RESULT([$RUBY_EXT_DLEXT]) - AC_SUBST(RUBY_EXT_DLEXT) - - # - # Check for the site arch dir - # - AC_ARG_VAR(RUBY_EXT_SITEARCH, [Ruby site arch dir]) - AC_MSG_CHECKING([for Ruby extensions site arch dir]) - if test -z "$RUBY_EXT_SITEARCH" ; then - [RUBY_EXT_SITEARCH=`$RUBY -rrbconfig -e 'puts RbConfig::CONFIG["sitearchdir"]'`]; - elif test -z "$RUBY_EXT_LIB" ; then - [RUBY_EXT_LIB="${RUBY_EXT_SITEARCH}"]; - fi - AC_MSG_RESULT([$RUBY_EXT_SITEARCH]) - AC_SUBST(RUBY_EXT_SITEARCH) - - # - # Check for the vendor arch dir - # - AC_ARG_VAR(RUBY_EXT_VENDORARCH, [Ruby vendor arch dir]) - AC_MSG_CHECKING([for Ruby extensions vendor arch dir]) - if test -z "$RUBY_EXT_VENDORARCH" ; then - [RUBY_EXT_VENDORARCH=`$RUBY -rrbconfig -e 'puts RbConfig::CONFIG["vendorarchdir"]'`]; - elif test -z "$RUBY_EXT_LIB" ; then - [RUBY_EXT_LIB="$RUBY_EXT_VENDORARCH"]; - fi - AC_MSG_RESULT([$RUBY_EXT_VENDORARCH]) - AC_SUBST(RUBY_EXT_VENDORARCH) - - AC_ARG_VAR(RUBY_EXT_LIB, [Ruby extension dir]) - if test -z "$RUBY_EXT_LIB" ; then - test "_$prefix" = _NONE && prefix="$ac_default_prefix" - if echo $RUBY_EXT_VENDORARCH | sed -e "s:^${prefix}:.:" | grep '^\.' >/dev/null; then - RUBY_EXT_LIB='$(prefix)'/`echo $RUBY_EXT_VENDORARCH | sed -e "s:^${prefix}:.:"` - elif echo $RUBY_EXT_SITEARCH | sed -e "s:^${prefix}:.:" | grep '^\.' >/dev/null; then - RUBY_EXT_LIB='$(prefix)'/`echo $RUBY_EXT_SITEARCH | sed -e "s:^${prefix}:.:"` - fi - fi - if test -z "$RUBY_EXT_LIB" ; then - AC_MSG_ERROR([ -------------------------------------------------- -Could not auto-detect the Ruby extension dir -Set RUBY_EXT_SITEARCH or RUBY_EXT_VENDORARCH --------------------------------------------------]) - fi - AC_SUBST(RUBY_EXT_LIB) - fi -]) diff --git a/test-driver b/test-driver new file mode 100755 index 000000000..32bf39e83 --- /dev/null +++ b/test-driver @@ -0,0 +1,127 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2012-06-27.10; # UTC + +# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? +if test $enable_hard_errors = no && test $estatus -eq 99; then + estatus=1 +fi + +case $estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: From cbd698cfdf4c078b0b74e76d9961fcf75d301d99 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Fri, 24 Jan 2014 17:21:58 -0500 Subject: [PATCH 06/17] Get rid of useless log messages --- common/funcall.cc | 5 ----- daemon/migration_manager.cc | 4 ---- daemon/replication_manager.cc | 7 ------- 3 files changed, 16 deletions(-) diff --git a/common/funcall.cc b/common/funcall.cc index ddd12f1df..0a934da8b 100644 --- a/common/funcall.cc +++ b/common/funcall.cc @@ -52,7 +52,6 @@ hyperdex :: validate_func(const schema& sc, const funcall& func) { if (func.attr >= sc.attrs_sz) { - std::cout << "sup1" << std::endl; return false; } @@ -60,10 +59,6 @@ hyperdex :: validate_func(const schema& sc, const funcall& func) if (!di || !di->check_args(func)) { - std::cout << __FILE__ ":" << __LINE__ << " attr=" << func.attr << " name=" << func.name << " arg1=" << func.arg1.hex() << " arg1_datatype="<attrs[attrnum + 1].type; - std::cout << "datatype " << i << ": " << datatype << std::endl; funcall o; o.attr = attrnum + 1; @@ -240,8 +239,6 @@ migration_manager :: kickstarter() funcs.push_back(o); } - std::cout << "funcs size: " << funcs.size() << std::endl; - size_t HEADER_SIZE = BUSYBEE_HEADER_SIZE + sizeof(uint8_t) /*mt*/ \ + sizeof(uint8_t) /*flags*/ \ @@ -254,7 +251,6 @@ migration_manager :: kickstarter() + pack_size(key) + pack_size(checks) + pack_size(funcs); - std::cout << "sent size: " << sz << std::endl; std::auto_ptr msg(e::buffer::create(sz)); uint8_t flags = (0 | 0 | 128); uint64_t nonce = 0; // TODO: what should it be? diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index becb42c6a..6fbffb421 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -246,11 +246,6 @@ replication_manager :: client_atomic(const server_id& from, const region_id ri(m_daemon->m_config.get_region_id(to)); const schema& sc(*m_daemon->m_config.get_schema(ri)); - std::cout << !datatype_info::lookup(sc.attrs[0].type)->validate(key) << std::endl; - std::cout << (validate_attribute_checks(sc, checks) != checks.size()) << std::endl; - std::cout << (validate_funcs(sc, funcs) != funcs.size()) << std::endl; - std::cout << (erase && !funcs.empty()) << std::endl; - if (!datatype_info::lookup(sc.attrs[0].type)->validate(key) || validate_attribute_checks(sc, checks) != checks.size() || validate_funcs(sc, funcs) != funcs.size() || @@ -277,7 +272,6 @@ replication_manager :: client_atomic(const server_id& from, if (!ks->check_against_latest_version(sc, erase, fail_if_not_found, fail_if_found, checks, &nrc)) { respond_to_client(to, from, nonce, nrc); - std::cout << "BP1" << std::endl; return; } @@ -294,7 +288,6 @@ replication_manager :: client_atomic(const server_id& from, if (!ks->put_from_funcs(sc, ri, seq_id, funcs, from, nonce)) { respond_to_client(to, from, nonce, NET_OVERFLOW); - std::cout << "BP2" << std::endl; return; } } From 22e2fca9888a22710b960a048e837006bde6491c Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 13 Mar 2014 03:33:09 -0400 Subject: [PATCH 07/17] This is a huge commit. Sorry. Anyway, it adds the feature that allows for migrating objects in one spaces to another space. And the process is fault-tolerant. It's not ready to be merged yet, since there hasn't been much testing. --- Makefile.am | 2 + common/configuration.cc | 62 +++-- common/migration.cc | 26 ++ common/migration.h | 5 + common/network_msgtype.h | 3 + daemon/communication.cc | 16 ++ daemon/daemon.cc | 86 ++++++- daemon/daemon.h | 6 + daemon/datalayer_iterator.h | 2 + daemon/migration_manager.cc | 324 ++++++++++++++++++------ daemon/migration_manager.h | 16 +- daemon/migration_manager_pending.cc | 48 ++++ daemon/migration_manager_pending.h | 62 +++++ daemon/migration_out_state.cc | 25 +- daemon/migration_out_state.h | 14 +- daemon/replication_manager.cc | 123 +++++++-- daemon/replication_manager.h | 17 ++ daemon/replication_manager_key_state.cc | 9 +- daemon/replication_manager_key_state.h | 4 +- daemon/replication_manager_pending.cc | 6 + daemon/replication_manager_pending.h | 5 + 21 files changed, 731 insertions(+), 130 deletions(-) create mode 100644 daemon/migration_manager_pending.cc create mode 100644 daemon/migration_manager_pending.h diff --git a/Makefile.am b/Makefile.am index ac73988b3..2b0663d58 100644 --- a/Makefile.am +++ b/Makefile.am @@ -203,6 +203,7 @@ noinst_HEADERS += daemon/state_transfer_manager_pending.h noinst_HEADERS += daemon/state_transfer_manager_transfer_in_state.h noinst_HEADERS += daemon/state_transfer_manager_transfer_out_state.h noinst_HEADERS += daemon/migration_manager.h +noinst_HEADERS += daemon/migration_manager_pending.h noinst_HEADERS += daemon/migration_out_state.h EXTRA_DIST += man/hyperdex-daemon.1.md @@ -265,6 +266,7 @@ hyperdex_daemon_SOURCES += daemon/state_transfer_manager_pending.cc hyperdex_daemon_SOURCES += daemon/state_transfer_manager_transfer_in_state.cc hyperdex_daemon_SOURCES += daemon/state_transfer_manager_transfer_out_state.cc hyperdex_daemon_SOURCES += daemon/migration_manager.cc +hyperdex_daemon_SOURCES += daemon/migration_manager_pending.cc hyperdex_daemon_SOURCES += daemon/migration_out_state.cc hyperdex_daemon_CXXFLAGS = $(AM_CXXFLAGS) $(CXXFLAGS) hyperdex_daemon_LDADD = diff --git a/common/configuration.cc b/common/configuration.cc index c403fc988..f22b1d45d 100644 --- a/common/configuration.cc +++ b/common/configuration.cc @@ -475,8 +475,10 @@ configuration :: point_leader(const char* sname, const e::slice& key) const virtual_server_id configuration :: point_leader(const space_id& sid, const e::slice& key) const { + std::cout << "m_spaces.size() = " << m_spaces.size() << std::endl; for (size_t s = 0; s < m_spaces.size(); ++s) { + std::cout << "sid = " << sid << " m_spaces[s].id " << m_spaces[s].id << std::endl; if (sid != m_spaces[s].id) { continue; @@ -485,6 +487,7 @@ configuration :: point_leader(const space_id& sid, const e::slice& key) const uint64_t h; hash(m_spaces[s].sc, key, &h); + std::cout << "m_spaces[s].subspaces[0].regions.size() = " << m_spaces[s].subspaces[0].regions.size() << std::endl; for (size_t pl = 0; pl < m_spaces[s].subspaces[0].regions.size(); ++pl) { if (m_spaces[s].subspaces[0].regions[pl].lower_coord[0] <= h && @@ -492,6 +495,7 @@ configuration :: point_leader(const space_id& sid, const e::slice& key) const { if (m_spaces[s].subspaces[0].regions[pl].replicas.empty()) { + std::cout << "BAD BP1" << std::endl; return virtual_server_id(); } @@ -499,9 +503,11 @@ configuration :: point_leader(const space_id& sid, const e::slice& key) const } } + std::cout << "BAD BP2" << std::endl; abort(); } + std::cout << "BAD BP3" << std::endl; return virtual_server_id(); } @@ -667,31 +673,37 @@ configuration :: transfers_out_regions(const server_id& si, std::vector* migrations) const { - for (size_t m = 0; m < m_migrations.size(); ++m) - { - const migration& mi(m_migrations[m]); - for (size_t w = 0; w < m_spaces.size(); ++w) - { - const space& s(m_spaces[w]); - if (s.id == mi.space_from) { - for (size_t x = 0; x < s.subspaces.size(); ++x) - { - const subspace& ss(s.subspaces[x]); - for (size_t y = 0; y < ss.regions.size(); ++y) - { - const region& r(ss.regions[y]); - for (size_t z = 0; z < r.replicas.size(); ++z) - { - const replica& rr(r.replicas[z]); - if (rr.si == sid) - { - migrations->push_back(mi); - } - } - } - } - } - } + // int counter = 0; + // for (size_t m = 0; m < m_migrations.size(); ++m) + // { + // const migration& mi(m_migrations[m]); + // for (size_t w = 0; w < m_spaces.size(); ++w) + // { + // const space& s(m_spaces[w]); + // if (s.id == mi.space_from) { + // for (size_t x = 0; x < s.subspaces.size(); ++x) + // { + // const subspace& ss(s.subspaces[x]); + // for (size_t y = 0; y < ss.regions.size(); ++y) + // { + // const region& r(ss.regions[y]); + // for (size_t z = 0; z < r.replicas.size(); ++z) + // { + // const replica& rr(r.replicas[z]); + // if (rr.si == sid) + // { + // counter++; + // migrations->push_back(mi); + // } + // } + // } + // } + // } + // } + // } + // std::cout << "added migrations for: " << counter << " times" << std::endl; + for (size_t m = 0; m < m_migrations.size(); ++m) { + migrations->push_back(m_migrations[m]); } } diff --git a/common/migration.cc b/common/migration.cc index 09e276710..b52ddb161 100644 --- a/common/migration.cc +++ b/common/migration.cc @@ -37,6 +37,32 @@ migration :: migration() { } +migration :: ~migration() throw () +{ +} + +migration& +migration :: operator = (const migration& rhs) +{ + id = rhs.id; + space_from = rhs.space_from; + space_to = rhs.space_to; +} + +bool migration :: operator < (const migration& rhs) const +{ + if (id < rhs.id) { return true; } + else if (id > rhs.id) { return false; } + + if (space_from < rhs.space_from) { return true; } + else if (space_from > rhs.space_from) { return false; } + + if (space_to < rhs.space_to) { return true; } + else if (space_to > rhs.space_to) { return false; } + + return false; +} + migration :: migration(migration_id _id, space_id _space_from, space_id _space_to) diff --git a/common/migration.h b/common/migration.h index 7fbeff9e8..bb7007b30 100644 --- a/common/migration.h +++ b/common/migration.h @@ -41,6 +41,11 @@ class migration migration(migration_id id, space_id space_from, space_id space_to); + ~migration() throw (); + + public: + migration& operator = (const migration&); + bool operator < (const migration&) const; public: migration_id id; diff --git a/common/network_msgtype.h b/common/network_msgtype.h index b7bbe774c..0fa1a10bd 100755 --- a/common/network_msgtype.h +++ b/common/network_msgtype.h @@ -50,6 +50,9 @@ enum network_msgtype RESP_SEARCH_ITEM = 35, RESP_SEARCH_DONE = 36, + REQ_MIGRATION = 37, + RESP_MIGRATION = 38, + REQ_SORTED_SEARCH = 40, RESP_SORTED_SEARCH = 41, diff --git a/daemon/communication.cc b/daemon/communication.cc index 3e7fc7679..452278002 100644 --- a/daemon/communication.cc +++ b/daemon/communication.cc @@ -301,6 +301,7 @@ communication :: send(const virtual_server_id& vto, network_msgtype msg_type, std::auto_ptr msg) { + LOG(INFO) << "SEND2 ->" << vto << " " << msg_type << " " << msg->hex(); assert(msg->size() >= HYPERDEX_HEADER_SIZE_SV); uint8_t mt = static_cast(msg_type); @@ -312,6 +313,7 @@ communication :: send(const virtual_server_id& vto, { return false; } + LOG(INFO) << "sending:" << mt << " " << flags << " " << m_daemon->m_config.version() << " " << vto.get(); #ifdef HD_LOG_ALL_MESSAGES LOG(INFO) << "SEND ->" << vto << " " << msg_type << " " << msg->hex(); @@ -454,18 +456,25 @@ communication :: recv(server_id* from, *from = server_id(id); *vto = virtual_server_id(vidt); + LOG(INFO) << "receiving " << *msg_type; + + LOG(INFO) << "RECV ->" << vidt << " " << *msg_type << " " << (*msg)->hex(); + if ((flags & 0x1)) { + LOG(INFO) << "BP6"; *up = *up >> vidf; *vfrom = virtual_server_id(vidf); } else { + LOG(INFO) << "BP5"; *vfrom = virtual_server_id(); } if (up->error()) { + LOG(INFO) << "BP4"; LOG(WARNING) << "dropping message that has a malformed header; here's some hex: " << (*msg)->hex(); continue; } @@ -477,12 +486,16 @@ communication :: recv(server_id* from, // If this is a virtual-virtual message if ((flags & 0x1)) { + LOG(INFO) << "BP3"; from_valid = *from == m_daemon->m_config.get_server_id(virtual_server_id(vidf)); } // No matter what, wait for the config the sender saw if (version > m_daemon->m_config.version()) { + LOG(INFO) << mt << " " << flags << " " << version << " " << vidt; + LOG(INFO) << version << " " << m_daemon->m_config.version(); + LOG(INFO) << "BP2"; early_message em(version, id, *msg); m_early_messages.push(em); continue; @@ -490,6 +503,7 @@ communication :: recv(server_id* from, if ((flags & 0x2) && version < m_daemon->m_config.version()) { + LOG(INFO) << "BP1"; continue; } @@ -501,6 +515,8 @@ communication :: recv(server_id* from, return true; } + LOG(INFO) << "we are done!"; + // Shove the message back at the client so it fails with a reconfigure. if (!(flags & 0x1)) { diff --git a/daemon/daemon.cc b/daemon/daemon.cc index fb9423990..f95da9b95 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -110,6 +110,7 @@ daemon :: daemon() , m_config() , m_perf_req_get() , m_perf_req_atomic() + , m_perf_req_migration() , m_perf_req_search_start() , m_perf_req_search_next() , m_perf_req_search_stop() @@ -129,6 +130,8 @@ daemon :: daemon() , m_perf_xfer_ack() , m_perf_backup() , m_perf_perf_counters() + , m_perf_resp_atomic() + , m_perf_resp_migration() , m_block_stat_path() , m_stat_collector(std::tr1::bind(&daemon::collect_stats, this)) , m_protect_stats() @@ -514,6 +517,7 @@ daemon :: loop(size_t thread) THREAD_AFFINITY_POLICY_COUNT); #endif + LOG(INFO) << "My server id is: " << m_us; LOG(INFO) << "network thread " << thread << " started on core " << core; if (sigfillset(&ss) < 0) @@ -552,6 +556,18 @@ daemon :: loop(size_t thread) process_req_atomic(from, vfrom, vto, msg, up); m_perf_req_atomic.tap(); break; + case RESP_ATOMIC: + process_resp_atomic(from, vfrom, vto, msg, up); + m_perf_resp_atomic.tap(); + break; + case REQ_MIGRATION: + process_req_migration(from, vfrom, vto, msg, up); + m_perf_req_migration.tap(); + break; + case RESP_MIGRATION: + process_resp_migration(from, vfrom, vto, msg, up); + m_perf_resp_migration.tap(); + break; case REQ_SEARCH_START: process_req_search_start(from, vfrom, vto, msg, up); m_perf_req_search_start.tap(); @@ -623,12 +639,12 @@ daemon :: loop(size_t thread) case BACKUP: process_backup(from, vfrom, vto, msg, up); m_perf_backup.tap(); + break; case PERF_COUNTERS: process_perf_counters(from, vfrom, vto, msg, up); m_perf_perf_counters.tap(); break; case RESP_GET: - case RESP_ATOMIC: case RESP_SEARCH_ITEM: case RESP_SEARCH_DONE: case RESP_SORTED_SEARCH: @@ -721,6 +737,74 @@ daemon :: process_req_atomic(server_id from, m_repl.client_atomic(from, vto, nonce, erase, fail_if_not_found, fail_if_found, key, checks, funcs); } +void +daemon :: process_resp_atomic(server_id from, + virtual_server_id vfrom, + virtual_server_id vto, + std::auto_ptr msg, + e::unpacker up) +{ + // TODO: get rid of this function + + // // size_t sz = HYPERDEX_HEADER_SIZE_VC + // // + sizeof(uint64_t) + // // + sizeof(uint16_t); + // // std::auto_ptr msg(e::buffer::create(sz)); + // // uint16_t result = static_cast(ret); + // // msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; + // // m_daemon->m_comm.send_client(us, client, RESP_ATOMIC, msg); + // uint64_t nonce; + // uint16_t result; + // up = up >> nonce >> result; + + // LOG(WARNING) << "nonce: " << nonce << " result: " << result << std::endl; + + // if (up.error()) + // { + // LOG(WARNING) << "unpack of REQ_ATOMIC failed; here's some hex: " << msg->hex(); + // return; + // } +} + +void daemon :: process_req_migration(server_id from, + virtual_server_id vfrom, + virtual_server_id vto, + std::auto_ptr msg, + e::unpacker up) +{ + uint8_t flags; + e::slice key; + std::vector checks; + std::vector funcs; + uint64_t mos_id; + uint64_t seq_no; + up = up >> key >> flags >> checks >> funcs >> mos_id >> seq_no; + + if (up.error()) + { + LOG(WARNING) << "unpack of REQ_MIGRATION failed; here's some hex: " << msg->hex(); + return; + } + + bool erase = !(flags & 128); + bool fail_if_not_found = flags & 1; + bool fail_if_found = flags & 2; + m_repl.request_atomic(from, vto, 0, erase, fail_if_not_found, fail_if_found, key, checks, funcs, true, mos_id, seq_no); +} + +void daemon :: process_resp_migration(server_id from, + virtual_server_id vfrom, + virtual_server_id vto, + std::auto_ptr msg, + e::unpacker up) +{ + uint64_t mos_id; + uint64_t seq_no; + uint16_t result; + up = up >> mos_id >> seq_no >> result; + m_mm.migration_ack(from, vto, mos_id, seq_no, result); +} + void daemon :: process_req_search_start(server_id from, virtual_server_id, diff --git a/daemon/daemon.h b/daemon/daemon.h index 53e9948e5..74ec64caa 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -75,6 +75,9 @@ class daemon void loop(size_t thread); void process_req_get(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_resp_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_req_migration(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); + void process_resp_migration(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_search_start(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_search_next(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_search_stop(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); @@ -127,6 +130,7 @@ class daemon // counters performance_counter m_perf_req_get; performance_counter m_perf_req_atomic; + performance_counter m_perf_req_migration; performance_counter m_perf_req_search_start; performance_counter m_perf_req_search_next; performance_counter m_perf_req_search_stop; @@ -146,6 +150,8 @@ class daemon performance_counter m_perf_xfer_ack; performance_counter m_perf_backup; performance_counter m_perf_perf_counters; + performance_counter m_perf_resp_atomic; + performance_counter m_perf_resp_migration; // iostat-like stats std::string m_block_stat_path; // historical data diff --git a/daemon/datalayer_iterator.h b/daemon/datalayer_iterator.h index 0596934d6..d8db0759a 100644 --- a/daemon/datalayer_iterator.h +++ b/daemon/datalayer_iterator.h @@ -57,6 +57,7 @@ class datalayer::iterator protected: friend class e::intrusive_ptr; + friend class std::auto_ptr; virtual ~iterator() throw (); void inc() { ++m_ref; } void dec() { --m_ref; if (m_ref == 0) delete this; } @@ -64,6 +65,7 @@ class datalayer::iterator private: leveldb_snapshot_ptr m_snap; + }; class datalayer::replay_iterator diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index d7e81bd9b..dd89ea8dc 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -39,12 +39,14 @@ #include "daemon/daemon.h" #include "daemon/datalayer_iterator.h" #include "daemon/migration_manager.h" +#include "daemon/migration_manager_pending.h" #include "daemon/migration_out_state.h" #include "daemon/leveldb.h" using hyperdex::reconfigure_returncode; using hyperdex::migration_manager; using hyperdex::migration_id; +using hyperdex::region_id; migration_manager :: migration_manager(daemon* d) : m_daemon(d) @@ -57,6 +59,7 @@ migration_manager :: migration_manager(daemon* d) , m_shutdown(true) , m_need_pause(false) , m_paused(false) + , m_next_out_state_id(1) { } @@ -104,6 +107,7 @@ migration_manager :: reconfigure(const configuration&, const configuration& new_config, const server_id& sid) { + LOG(INFO) << "reconfiguring migration_manager"; { po6::threads::mutex::hold hold(&m_block_kickstarter); assert(m_need_pause); @@ -116,28 +120,257 @@ migration_manager :: reconfigure(const configuration&, std::vector migrations_out; new_config.migrations_out(sid, &migrations_out); + std::sort(migrations_out.begin(), migrations_out.end()); + setup_migration_state(migrations_out, &m_migrations_out); + + // std::vector regions; + // new_config.mapped_regions(sid, ®ions); + + // std::vector::iterator m_iter; + // for (m_iter = migrations_out.begin(); m_iter != migrations_out.end(); m_iter++) { + // std::vector::iterator r_iter; + // for (r_iter = regions.begin(); r_iter != regions.end(); r_iter++) { + // region_id rid = (*r_iter); + // if (new_config.space_of(rid) == (*m_iter).space_from) { + // e::intrusive_ptr ptr(new migration_out_state((*m_iter).space_to, rid)); + // m_migrations_out.push_back(ptr); + // } + // } + // } +} + +void +migration_manager :: setup_migration_state(const std::vector migrations, + std::vector >* migration_states) +{ + std::vector > tmp; + // In reality, tmp probably will store way more elements than + // migrations, since one migration will likely correspond to + // many migration out states. + tmp.reserve(migrations.size()); + size_t m_idx = 0; + size_t ms_idx = 0; std::vector regions; - new_config.mapped_regions(sid, ®ions); + m_daemon->m_config.mapped_regions(m_daemon->m_us, ®ions); + + leveldb_snapshot_ptr snapshot_ptr = m_daemon->m_data.make_snapshot(); + + while (m_idx < migrations.size() && ms_idx < migration_states->size()) + { + if (migrations[m_idx].id == (*migration_states)[ms_idx]->mid) + { + tmp.push_back((*migration_states)[ms_idx]); + ++m_idx; + ++ms_idx; + } + else if (migrations[m_idx].id < (*migration_states)[ms_idx]->mid) + { + LOG(INFO) << "initiating migration out state " << migrations[m_idx]; + + std::vector::iterator r_iter; + for (r_iter = regions.begin(); r_iter != regions.end(); r_iter++) { + region_id rid = (*r_iter); + if (m_daemon->m_config.space_of(rid) == migrations[m_idx].space_from) { + datalayer::returncode err; + std::auto_ptr iter; + iter.reset(m_daemon->m_data.make_region_iterator(snapshot_ptr, rid, &err)); + if (err != datalayer::SUCCESS) { + LOG(ERROR) << "failed to create region iterator"; + continue; // TODO: should we continue? + } + e::intrusive_ptr ptr( + new migration_out_state(migrations[m_idx].id, + migrations[m_idx].space_to, + m_next_out_state_id++, + rid, + iter)); + tmp.push_back(ptr); + } + } + ++m_idx; + } + else if (migrations[m_idx].id > (*migration_states)[ms_idx]->mid) + { + LOG(INFO) << "ending migration out state " << (*migration_states)[ms_idx]->mid; + ++ms_idx; + } + } + + while (m_idx < migrations.size()) + { + LOG(INFO) << "initiating migration out state " << migrations[m_idx]; - std::vector::iterator m_iter; - for (m_iter = migrations_out.begin(); m_iter != migrations_out.end(); m_iter++) { - migration_out_state* new_state = NULL; std::vector::iterator r_iter; for (r_iter = regions.begin(); r_iter != regions.end(); r_iter++) { region_id rid = (*r_iter); - if (new_config.space_of(rid) == (*m_iter).space_from) { - if (new_state == NULL) { - new_state = new migration_out_state(); + if (m_daemon->m_config.space_of(rid) == migrations[m_idx].space_from) { + datalayer::returncode err; + std::auto_ptr iter; + iter.reset(m_daemon->m_data.make_region_iterator(snapshot_ptr, rid, &err)); + if (err != datalayer::SUCCESS) { + LOG(ERROR) << "failed to create region iterator"; + continue; // TODO: should we continue? } - new_state->region_iters.push_back(new std::pair((*m_iter).space_to, rid)); + e::intrusive_ptr ptr( + new migration_out_state(migrations[m_idx].id, + migrations[m_idx].space_to, + m_next_out_state_id++, + rid, + iter)); + tmp.push_back(ptr); } } - if (new_state != NULL) { - e::intrusive_ptr ptr(new_state); - m_migrations_out.push_back(ptr); + ++m_idx; + } + + while (ms_idx < migration_states->size()) + { + LOG(INFO) << "ending migration out state" << (*migration_states)[ms_idx]->mid; + ++ms_idx; + } + + tmp.swap(*migration_states); +} + +void +migration_manager :: migrate_more_state(migration_out_state* mos) +{ + assert(mos->iter.get()); + + while (mos->window.size() < mos->window_sz && mos->iter->valid()) + { + e::intrusive_ptr op(new pending()); + op->rid = mos->rid; + op->seq_no = mos->next_seq_no; + ++mos->next_seq_no; + + // TODO: can an object has no value? + if (m_daemon->m_data.get_from_iterator(mos->rid, mos->iter.get(), &op->key, &op->value, &op->version, &op->vref) != datalayer::SUCCESS) + { + LOG(ERROR) << "error unpacking value during migration"; + break; + } + + mos->window.push_back(op); + send_object(mos, op.get()); + mos->iter->next(); + } + + // TODO: Take a look at the corresponding method in state_transfer_manager. + // You might need to inform the coordinator about the completion of the + // migration. +} + +void +migration_manager :: retransmit(migration_out_state* mos) +{ + for (std::list >::iterator it = mos->window.begin(); + it != mos->window.end(); ++it) + { + send_object(mos, it->get()); + } +} + +void +migration_manager :: send_object(migration_out_state* mos, pending* op) +{ + virtual_server_id to = m_daemon->m_config.point_leader(mos->sid, op->key); + + const schema* sc = m_daemon->m_config.get_schema(op->rid); + std::vector funcs; + std::vector checks; + funcs.reserve(op->value.size()); + + for (size_t j = 0; j < op->value.size(); ++j) + { + uint16_t attrnum = j; + + hyperdatatype datatype = sc->attrs[attrnum + 1].type; + + funcall o; + o.attr = attrnum + 1; + o.name = FUNC_SET; + o.arg1 = op->value[j]; + o.arg1_datatype = datatype; + funcs.push_back(o); + } + + size_t sz = HYPERDEX_HEADER_SIZE_SV + + pack_size(op->key) + + sizeof(uint8_t) + + pack_size(checks) + + pack_size(funcs) + + sizeof(uint64_t) // mos_id + + sizeof(uint64_t); // seq_no + std::auto_ptr msg(e::buffer::create(sz)); + uint8_t flags = (0 | 0 | 128); + msg->pack_at(HYPERDEX_HEADER_SIZE_SV) + << op->key << flags << checks << funcs << mos->id << op->seq_no; + m_daemon->m_comm.send(to, REQ_MIGRATION, msg); + // TODO: do we need this here? m_daemon->m_comm.wake_one(); +} + +void +migration_manager :: migration_ack(const server_id& from, + const virtual_server_id& to, + uint64_t mos_id, + uint64_t seq_no, + uint16_t result) +{ + migration_out_state* mos = get_mos(mos_id); + + if (!mos) + { + LOG(INFO) << "dropping RESP_MIGRATION for " << mos_id << " which we don't know about"; + return; + } + + po6::threads::mutex::hold hold(&mos->mtx); + + // TODO: do we need to check if the ACK comes from the right server? + // The state transfer manager does that. + + std::list >::iterator it; + + for (it = mos->window.begin(); it != mos->window.end(); ++it) + { + if ((*it)->seq_no == seq_no) + { + break; + } + } + + if (it != mos->window.end()) + { + (*it)->acked = true; + + if (mos->window_sz < 1024) + { + ++mos->window_sz; + } + } + + while (!mos->window.empty() && (*mos->window.begin())->acked) + { + mos->window.pop_front(); + } + + migrate_more_state(mos); +} + +migration_manager::migration_out_state* +migration_manager :: get_mos(uint64_t out_state_id) +{ + for (size_t i = 0; i < m_migrations_out.size(); ++i) + { + if (m_migrations_out[i]->id == out_state_id) + { + return m_migrations_out[i].get(); } } + + return NULL; } void @@ -186,8 +419,6 @@ migration_manager :: kickstarter() size_t idx = 0; - leveldb_snapshot_ptr snapshot_ptr = m_daemon->m_data.make_snapshot(); - while (true) { po6::threads::mutex::hold hold(&m_block_kickstarter); @@ -198,74 +429,13 @@ migration_manager :: kickstarter() } po6::threads::mutex::hold hold2(&m_migrations_out[idx]->mtx); - - // send data - migration_out_state* mos = m_migrations_out[idx].get(); - for (size_t i; i < mos->region_iters.size(); i++) { - space_id sid = mos->region_iters[i]->first; - region_id rid = mos->region_iters[i]->second; - datalayer::returncode err; - datalayer::iterator* iter = m_daemon->m_data.make_region_iterator(snapshot_ptr, rid, &err); - if (err != datalayer::SUCCESS) { - LOG(ERROR) << "failed to create region iterator"; - break; - } - - if (iter->valid()) - { - e::slice key; - std::vector val; - uint64_t ver; - datalayer::reference tmp; - m_daemon->m_data.get_from_iterator(rid, iter, &key, &val, &ver, &tmp); - virtual_server_id to = m_daemon->m_config.point_leader(sid, key); - - const schema* sc = m_daemon->m_config.get_schema(rid); - std::vector funcs; - std::vector checks; - funcs.reserve(val.size()); - - for (size_t i = 0; i < val.size(); ++i) - { - uint16_t attrnum = i; - - hyperdatatype datatype = sc->attrs[attrnum + 1].type; - - funcall o; - o.attr = attrnum + 1; - o.name = FUNC_SET; - o.arg1 = val[i]; - o.arg1_datatype = datatype; - funcs.push_back(o); - } - - size_t HEADER_SIZE = BUSYBEE_HEADER_SIZE - + sizeof(uint8_t) /*mt*/ \ - + sizeof(uint8_t) /*flags*/ \ - + sizeof(uint64_t) /*version*/ \ - + sizeof(uint64_t); /*vidt*/ - - size_t sz = HEADER_SIZE - + sizeof(uint64_t) /*nonce*/ - + sizeof(uint8_t) - + pack_size(key) - + pack_size(checks) - + pack_size(funcs); - std::auto_ptr msg(e::buffer::create(sz)); - uint8_t flags = (0 | 0 | 128); - uint64_t nonce = 0; // TODO: what should it be? - msg->pack_at(HEADER_SIZE) - << nonce << key << flags << checks << funcs; - m_daemon->m_comm.send(to, REQ_ATOMIC, msg); - iter->next(); - } - } - + retransmit(m_migrations_out[idx].get()); + migrate_more_state(m_migrations_out[idx].get()); ++idx; } } - LOG(INFO) << "state transfer thread shutting down"; + LOG(INFO) << "migration thread shutting down"; } void diff --git a/daemon/migration_manager.h b/daemon/migration_manager.h index 4684285e5..1d4f790d0 100644 --- a/daemon/migration_manager.h +++ b/daemon/migration_manager.h @@ -43,7 +43,6 @@ #include "namespace.h" #include "common/configuration.h" #include "daemon/reconfigure_returncode.h" -#include "daemon/datalayer.h" BEGIN_HYPERDEX_NAMESPACE class daemon; @@ -63,6 +62,12 @@ class migration_manager const configuration& new_config, const server_id&); + void migration_ack(const server_id& from, + const virtual_server_id& to, + uint64_t mos_id, + uint64_t seq_no, + uint16_t result); + // public: // void handshake_syn(const virtual_server_id& from, // const migration_id& xid); @@ -91,12 +96,20 @@ class migration_manager // uint64_t seq_no); private: + class pending; class migration_out_state; private: + void setup_migration_state(const std::vector migrations, + std::vector >* migration_states); + void migrate_more_state(migration_out_state* mos); + void retransmit(migration_out_state* mos); + void send_object(migration_out_state* mos, pending* op); void kickstarter(); void shutdown(); + migration_out_state* get_mos(uint64_t out_state_id); + private: migration_manager(const migration_manager&); migration_manager& operator = (const migration_manager&); @@ -112,6 +125,7 @@ class migration_manager bool m_shutdown; bool m_need_pause; bool m_paused; + uint64_t m_next_out_state_id; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/migration_manager_pending.cc b/daemon/migration_manager_pending.cc new file mode 100644 index 000000000..fb55773e7 --- /dev/null +++ b/daemon/migration_manager_pending.cc @@ -0,0 +1,48 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// HyperDex +#include "daemon/migration_manager_pending.h" + +using hyperdex::migration_manager; + +migration_manager :: migration_manager :: pending :: pending() + : seq_no(0) + , rid(0) + , version(0) + , key() + , value() + , acked(false) + , msg() + , vref() + , m_ref(0) +{ +} + +migration_manager :: migration_manager :: pending :: ~pending() throw () +{ +} diff --git a/daemon/migration_manager_pending.h b/daemon/migration_manager_pending.h new file mode 100644 index 000000000..3539bf689 --- /dev/null +++ b/daemon/migration_manager_pending.h @@ -0,0 +1,62 @@ +// Copyright (c) 2012, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef hyperdex_daemon_migration_manager_pending_h_ +#define hyperdex_daemon_migration_manager_pending_h_ + +// hyperdex +#include "daemon/datalayer.h" +#include "daemon/migration_manager.h" + +class hyperdex::migration_manager::pending +{ + public: + pending(); + ~pending() throw (); + + public: + uint64_t seq_no; + region_id rid; + uint64_t version; + e::slice key; + std::vector value; + bool acked; + std::auto_ptr msg; + datalayer::reference vref; + + private: + friend class e::intrusive_ptr; + + private: + void inc() { ++m_ref; } + void dec() { --m_ref; if (m_ref == 0) delete this; } + + private: + size_t m_ref; +}; + +#endif // hyperdex_daemon_migration_manager_pending_h_ diff --git a/daemon/migration_out_state.cc b/daemon/migration_out_state.cc index 7cc0ab78f..ac6600a7f 100644 --- a/daemon/migration_out_state.cc +++ b/daemon/migration_out_state.cc @@ -28,12 +28,35 @@ // HyperDex #include "daemon/datalayer_iterator.h" #include "daemon/migration_out_state.h" +#include "daemon/migration_manager_pending.h" using hyperdex::migration_manager; migration_manager :: migration_out_state :: migration_out_state() : mtx() - , region_iters() + , id(1) + , next_seq_no(1) + , window() + , window_sz(1) + , iter() + , mid() + , sid() + , rid() + , m_ref(0) +{ +} + +migration_manager :: migration_out_state :: migration_out_state(migration_id _mid, + space_id _sid, uint64_t _id, region_id _rid, std::auto_ptr _iter) + : mtx() + , id(_id) + , next_seq_no(1) + , window() + , window_sz(1) + , iter(_iter) + , mid(_mid) + , sid(_sid) + , rid(_rid) , m_ref(0) { } diff --git a/daemon/migration_out_state.h b/daemon/migration_out_state.h index ca8c9ef09..6ed4c3d51 100644 --- a/daemon/migration_out_state.h +++ b/daemon/migration_out_state.h @@ -49,11 +49,23 @@ class migration_manager::migration_out_state { public: migration_out_state(); + migration_out_state(migration_id mid, + space_id sid, + uint64_t out_state_id, + region_id rid, + std::auto_ptr iter); ~migration_out_state() throw (); public: po6::threads::mutex mtx; - std::vector* > region_iters; + uint64_t id; + uint64_t next_seq_no; + migration_id mid; + space_id sid; + region_id rid; + std::list > window; + size_t window_sz; + std::auto_ptr iter; private: friend class e::intrusive_ptr; diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index 6fbffb421..160c998e1 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -226,20 +226,56 @@ replication_manager :: debug_dump() unpause(); } +// OK, so basically, you create a new class, something called "response", which +// contains some state that specifies 1) whether the receiver is a client or a server, +// 2) extra state if the receiver is a server, i.e. state that identify the corresponding +// migration state for the object in question. When receiving a req_atomic or a +// migration_atomic, you generate such an object, then you call client_atomic with +// this response object. Then, client_atomic saves it into the key state. Then, +// when chain_ack is received, the point leader will look into the key state and +// call some method on this response class, that would generate an appropriate response +// that the point leader can send. + void replication_manager :: client_atomic(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - bool erase, - bool fail_if_not_found, - bool fail_if_found, - const e::slice& key, - const std::vector& checks, - const std::vector& funcs) + const virtual_server_id& to, + uint64_t nonce, + bool erase, + bool fail_if_not_found, + bool fail_if_found, + const e::slice& key, + const std::vector& checks, + const std::vector& funcs) { + request_atomic(from, to, nonce, erase, fail_if_not_found, fail_if_found, + key, checks, funcs, false, 0, 0); +} + +void +replication_manager :: request_atomic(const server_id& from, + const virtual_server_id& to, + uint64_t nonce, + bool erase, + bool fail_if_not_found, + bool fail_if_found, + const e::slice& key, + const std::vector& checks, + const std::vector& funcs, + bool is_migration_object, + uint64_t mos_id, + uint64_t seq_no) +{ + #define respond(ret) \ + if (is_migration_object) { respond_for_migration(to, from, mos_id, seq_no, ret); } \ + else { respond_to_client(to, from, nonce, ret); } + + if (is_migration_object) { + LOG(INFO) << "preparing to send a migration object"; + }; + if (m_daemon->m_config.read_only()) { - respond_to_client(to, from, nonce, NET_READONLY); + respond(NET_READONLY) return; } @@ -253,7 +289,7 @@ replication_manager :: client_atomic(const server_id& from, { LOG(ERROR) << "dropping nonce=" << nonce << " from client=" << from << " because the key, checks, or funcs don't validate"; - respond_to_client(to, from, nonce, NET_BADDIMSPEC); + respond(NET_BADDIMSPEC); return; } @@ -261,7 +297,7 @@ replication_manager :: client_atomic(const server_id& from, { LOG(ERROR) << "dropping nonce=" << nonce << " from client=" << from << " because it doesn't map to " << ri; - respond_to_client(to, from, nonce, NET_NOTUS); + respond(NET_NOTUS); return; } @@ -271,7 +307,7 @@ replication_manager :: client_atomic(const server_id& from, if (!ks->check_against_latest_version(sc, erase, fail_if_not_found, fail_if_found, checks, &nrc)) { - respond_to_client(to, from, nonce, nrc); + respond(nrc); return; } @@ -285,9 +321,10 @@ replication_manager :: client_atomic(const server_id& from, } else { - if (!ks->put_from_funcs(sc, ri, seq_id, funcs, from, nonce)) + if (!ks->put_from_funcs(sc, ri, seq_id, funcs, from, nonce, + is_migration_object, mos_id, seq_id)) { - respond_to_client(to, from, nonce, NET_OVERFLOW); + respond(NET_OVERFLOW); return; } } @@ -530,16 +567,26 @@ replication_manager :: chain_ack(const virtual_server_id& from, if (op->client != server_id()) { - respond_to_client(to, op->client, op->nonce, NET_SUCCESS); + if (op->is_migration_object) { + respond_for_migration(to, op->client, op->mos_id, op->seq_no, NET_SUCCESS); + } else { + respond_to_client(to, op->client, op->nonce, NET_SUCCESS); + } + } + else + { + LOG(INFO) << "Oh well I'm not replying RESP_ATOMIC"; } if (is_head && m_daemon->m_config.version() == op->recv_config_version) { + LOG(INFO) << "Sending ack to head"; send_ack(to, op->recv, false, reg_id, seq_id, version, key); } if (op->reg_id == ri) { + LOG(INFO) << "In the same region"; bool x; x = m_idcol.collect(ri, op->seq_id); assert(x); @@ -840,13 +887,45 @@ replication_manager :: respond_to_client(const virtual_server_id& us, uint64_t nonce, network_returncode ret) { - size_t sz = HYPERDEX_HEADER_SIZE_VC - + sizeof(uint64_t) - + sizeof(uint16_t); - std::auto_ptr msg(e::buffer::create(sz)); - uint16_t result = static_cast(ret); - msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; - m_daemon->m_comm.send_client(us, client, RESP_ATOMIC, msg); + if (m_daemon->m_config.exists(client)) { + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint64_t) + + sizeof(uint16_t); + std::auto_ptr msg(e::buffer::create(sz)); + uint16_t result = static_cast(ret); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << nonce << result; + m_daemon->m_comm.send(us, client, RESP_ATOMIC, msg); + } else { + size_t sz = HYPERDEX_HEADER_SIZE_VC + + sizeof(uint64_t) + + sizeof(uint16_t); + std::auto_ptr msg(e::buffer::create(sz)); + uint16_t result = static_cast(ret); + msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; + m_daemon->m_comm.send_client(us, client, RESP_ATOMIC, msg); + } +} + +void +replication_manager :: respond_for_migration(const virtual_server_id& us, + const server_id& client, + uint64_t mos_id, + uint64_t seq_no, + network_returncode ret) +{ + LOG(INFO) << "sending response for a migration object"; + if (m_daemon->m_config.exists(client)) { + size_t sz = HYPERDEX_HEADER_SIZE_VV + + sizeof(uint64_t) + + sizeof(uint64_t) + + sizeof(uint16_t); + std::auto_ptr msg(e::buffer::create(sz)); + uint16_t result = static_cast(ret); + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << mos_id << seq_no << result; + m_daemon->m_comm.send(us, client, RESP_MIGRATION, msg); + } else { + LOG(ERROR) << "migration has to originate from a server"; + } } bool diff --git a/daemon/replication_manager.h b/daemon/replication_manager.h index 8823dd8a5..2b2a1f14c 100755 --- a/daemon/replication_manager.h +++ b/daemon/replication_manager.h @@ -91,6 +91,18 @@ class replication_manager const e::slice& key, const std::vector& checks, const std::vector& funcs); + void request_atomic(const server_id& from, + const virtual_server_id& to, + uint64_t nonce, + bool erase, + bool fail_if_not_found, + bool fail_if_found, + const e::slice& key, + const std::vector& checks, + const std::vector& funcs, + bool is_migration_object, + uint64_t mos_id, + uint64_t seq_no); // These are called in response to messages from other hosts. void chain_op(const virtual_server_id& from, const virtual_server_id& to, @@ -165,6 +177,11 @@ class replication_manager const server_id& client, uint64_t nonce, network_returncode ret); + void respond_for_migration(const virtual_server_id& us, + const server_id& client, + uint64_t mos_id, + uint64_t seq_no, + network_returncode ret); // check stability bool is_check_needed(); void check_is_needed(); diff --git a/daemon/replication_manager_key_state.cc b/daemon/replication_manager_key_state.cc index daf0f3f3b..9d96ce63d 100644 --- a/daemon/replication_manager_key_state.cc +++ b/daemon/replication_manager_key_state.cc @@ -279,7 +279,10 @@ bool replication_manager :: key_state :: put_from_funcs(const schema& sc, const region_id& reg_id, uint64_t seq_id, const std::vector& funcs, - const server_id& client, uint64_t nonce) + const server_id& client, uint64_t nonce, + bool is_migration_object, + uint64_t mos_id, + uint64_t seq_no) { bool has_old_value = false; uint64_t old_version = 0; @@ -303,6 +306,10 @@ replication_manager :: key_state :: put_from_funcs(const schema& sc, client, nonce, 0, virtual_server_id()); + op->is_migration_object = is_migration_object; + op->mos_id = mos_id; + op->seq_no = seq_no; + if (funcs_passed == funcs.size()) { insert_deferred(old_version + 1, op); diff --git a/daemon/replication_manager_key_state.h b/daemon/replication_manager_key_state.h index a112c6c3a..429c3d2cb 100644 --- a/daemon/replication_manager_key_state.h +++ b/daemon/replication_manager_key_state.h @@ -73,7 +73,9 @@ class hyperdex::replication_manager::key_state bool put_from_funcs(const schema& sc, const region_id& reg_id, uint64_t seq_id, const std::vector& funcs, - const server_id& client, uint64_t nonce); + const server_id& client, uint64_t nonce, + bool is_migration_object, + uint64_t mos_id, uint64_t seq_no); void insert_deferred(uint64_t version, e::intrusive_ptr op); bool persist_to_datalayer(replication_manager* rm, const region_id& ri, const region_id& reg_id, uint64_t seq_id, diff --git a/daemon/replication_manager_pending.cc b/daemon/replication_manager_pending.cc index b2bb2a9bd..de7e8f364 100644 --- a/daemon/replication_manager_pending.cc +++ b/daemon/replication_manager_pending.cc @@ -61,6 +61,9 @@ replication_manager :: pending :: pending(std::auto_ptr _backing, , this_new_region() , prev_region() , next_region() + , is_migration_object() + , mos_id(0) + , seq_no(0) , m_ref(0) { } @@ -82,4 +85,7 @@ replication_manager :: pending :: debug_dump() LOG(INFO) << " this_old: " << this_old_region; LOG(INFO) << " this_new: " << this_new_region; LOG(INFO) << " next: " << next_region; + LOG(INFO) << " is_migration_object: " << is_migration_object; + LOG(INFO) << " mos_id: " << mos_id; + LOG(INFO) << " seq_no: " << seq_no; } diff --git a/daemon/replication_manager_pending.h b/daemon/replication_manager_pending.h index 9d551bf27..b09ab82ac 100644 --- a/daemon/replication_manager_pending.h +++ b/daemon/replication_manager_pending.h @@ -72,6 +72,11 @@ class hyperdex::replication_manager::pending region_id prev_region; region_id next_region; + // Migration-related stuff + bool is_migration_object; + uint64_t mos_id; + uint64_t seq_no; + private: friend class e::intrusive_ptr; void inc() { ++m_ref; } From 6cc16c7f06b5ad99435120c6fa265e74f084185c Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 20 Mar 2014 02:40:14 -0400 Subject: [PATCH 08/17] Add a mechanism to inform the coordinator about the completion of migrations --- common/migration.cc | 12 ++++--- common/migration.h | 3 ++ coordinator/coordinator.cc | 46 ++++++++++++++++++++----- coordinator/coordinator.h | 21 ++++++----- coordinator/symtable.c | 1 + coordinator/transitions.cc | 16 +++++++++ coordinator/transitions.h | 2 ++ daemon/coordinator_link_wrapper.cc | 17 ++++++++- daemon/coordinator_link_wrapper.h | 2 ++ daemon/daemon.cc | 12 +++---- daemon/migration_manager.cc | 36 +++++++++---------- daemon/migration_manager.h | 5 ++- daemon/migration_out_state.cc | 4 +-- daemon/migration_out_state.h | 2 -- daemon/replication_manager.cc | 14 ++++---- daemon/replication_manager.h | 4 +-- daemon/replication_manager_key_state.cc | 4 +-- daemon/replication_manager_key_state.h | 2 +- daemon/replication_manager_pending.cc | 4 +-- daemon/replication_manager_pending.h | 2 +- 20 files changed, 139 insertions(+), 70 deletions(-) diff --git a/common/migration.cc b/common/migration.cc index b52ddb161..f1fb12df3 100644 --- a/common/migration.cc +++ b/common/migration.cc @@ -34,6 +34,7 @@ migration :: migration() : id() , space_from() , space_to() + , outstanding_regions() { } @@ -47,6 +48,7 @@ migration :: operator = (const migration& rhs) id = rhs.id; space_from = rhs.space_from; space_to = rhs.space_to; + outstanding_regions = rhs.outstanding_regions; } bool migration :: operator < (const migration& rhs) const @@ -83,7 +85,7 @@ hyperdex :: operator << (std::ostream& lhs, const migration& rhs) e::buffer::packer hyperdex :: operator << (e::buffer::packer pa, const migration& m) { - pa = pa << m.space_from << m.space_to; + pa = pa << m.space_from << m.space_to << m.outstanding_regions; return pa; } @@ -91,14 +93,16 @@ e::unpacker hyperdex :: operator >> (e::unpacker up, migration& m) { space_id s_space_from, s_space_to; - up >> s_space_from >> s_space_to; + std::vector outstanding_regions; + up >> s_space_from >> s_space_to >> outstanding_regions; m.space_from = s_space_from; m.space_to = s_space_to; + m.outstanding_regions = outstanding_regions; return up; } size_t -hyperdex :: pack_size(const migration&) +hyperdex :: pack_size(const migration& m) { - return 2 * sizeof(uint64_t); + return 2 * sizeof(uint64_t) + m.outstanding_regions.size() * sizeof(uint64_t); } diff --git a/common/migration.h b/common/migration.h index bb7007b30..b0c877b08 100644 --- a/common/migration.h +++ b/common/migration.h @@ -51,6 +51,9 @@ class migration migration_id id; space_id space_from; space_id space_to; + // This is only used at the coordinator to keep track + // of which regions have not been migrated. + std::vector outstanding_regions; }; std::ostream& diff --git a/coordinator/coordinator.cc b/coordinator/coordinator.cc index d7ec774bc..a4a571e2e 100644 --- a/coordinator/coordinator.cc +++ b/coordinator/coordinator.cc @@ -760,6 +760,33 @@ coordinator :: transfer_complete(replicant_state_machine_context* ctx, return generate_response(ctx, COORD_SUCCESS); } +void +coordinator :: migration_complete(replicant_state_machine_context* ctx, + uint64_t version, + const migration_id& mid, + const region_id& rid) +{ + for (size_t m = 0; m < m_migrations.size(); m++) + { + if (m_migrations[m].id == mid) + { + for (size_t r; r < m_migrations[m].outstanding_regions.size(); r++) + { + if (m_migrations[m].outstanding_regions[r] == rid) + { + m_migrations[m].outstanding_regions.erase(m_migrations[m].outstanding_regions.begin() + r); + if (m_migrations[m].outstanding_regions.size() == 0) { + del_migration(m_migrations[m].id); + } + // TODO: do I need to call converge_intent? + generate_next_configuration(ctx); // TODO: is this an expensive operation? + return generate_response(ctx, COORD_SUCCESS); + } + } + } + } +} + void coordinator :: config_get(replicant_state_machine_context* ctx) { @@ -1665,18 +1692,22 @@ coordinator :: new_migration(replicant_state_machine_context* ctx, space_id space_to_id = it->second->id; - m_migrations.push_back(migration(migration_id(m_counter++), - space_from_id, space_to_id)); + migration mgt(migration_id(m_counter++), space_from_id, space_to_id); + m_migrations.push_back(mgt); + + space_ptr s = m_spaces[std::string(space_from)]; + regions_in_space(s, &mgt.outstanding_regions); + generate_next_configuration(ctx); } migration* -coordinator :: get_migration(space_id space_from, - space_id space_to) +coordinator :: get_migration(migration_id mid) { for (size_t i = 0; i < m_migrations.size(); ++i) { - if (m_migrations[i].space_from == space_from && m_migrations[i].space_to == space_to) + + if (m_migrations[i].id == mid) { return &m_migrations[i]; } @@ -1686,12 +1717,11 @@ coordinator :: get_migration(space_id space_from, } void -coordinator :: del_migration(space_id space_from, - space_id space_to) +coordinator :: del_migration(migration_id mid) { for (size_t i = 0; i < m_migrations.size(); ++i) { - if (m_migrations[i].space_from == space_from && m_migrations[i].space_to == space_to) + if (m_migrations[i].id == mid) { for (size_t j = i + 1; j < m_migrations.size(); ++j) { diff --git a/coordinator/coordinator.h b/coordinator/coordinator.h index 66e9fc525..6b636e3bf 100644 --- a/coordinator/coordinator.h +++ b/coordinator/coordinator.h @@ -68,14 +68,6 @@ class coordinator void read_only(replicant_state_machine_context* ctx, bool ro); void fault_tolerance(replicant_state_machine_context* ctx, const char* space, uint64_t consistency); - // migrations - void new_migration(replicant_state_machine_context* ctx, - const char* space_from, - const char* space_to); - migration* get_migration(space_id space_from, - space_id space_to); - void del_migration(space_id space_from, - space_id space_to); // server management public: @@ -112,6 +104,16 @@ class coordinator uint64_t version, const transfer_id& xid); + // migrations management + public: + void migration_complete(replicant_state_machine_context* ctx, + uint64_t version, + const migration_id& mid, + const region_id& rid); + void new_migration(replicant_state_machine_context* ctx, + const char* space_from, + const char* space_to); + // config management public: void config_get(replicant_state_machine_context* ctx); @@ -182,6 +184,9 @@ class coordinator transfer* get_transfer(const region_id& rid); transfer* get_transfer(const transfer_id& xid); void del_transfer(const transfer_id& xid); + // migrations + migration* get_migration(migration_id mid); + void del_migration(migration_id mid); // configuration void check_ack_condition(replicant_state_machine_context* ctx); void check_stable_condition(replicant_state_machine_context* ctx); diff --git a/coordinator/symtable.c b/coordinator/symtable.c index 2af782bb7..3e2101934 100644 --- a/coordinator/symtable.c +++ b/coordinator/symtable.c @@ -56,6 +56,7 @@ struct replicant_state_machine HYPERDEX_API rsm = { {"space_rm", hyperdex_coordinator_space_rm}, {"transfer_go_live", hyperdex_coordinator_transfer_go_live}, {"transfer_complete", hyperdex_coordinator_transfer_complete}, + {"migration_complete", hyperdex_coordinator_migration_complete}, {"checkpoint_stable", hyperdex_coordinator_checkpoint_stable}, {"alarm", hyperdex_coordinator_alarm}, {"read_only", hyperdex_coordinator_read_only}, diff --git a/coordinator/transitions.cc b/coordinator/transitions.cc index 251c4bde8..2c967ab5e 100644 --- a/coordinator/transitions.cc +++ b/coordinator/transitions.cc @@ -447,6 +447,22 @@ hyperdex_coordinator_transfer_complete(struct replicant_state_machine_context* c c->transfer_complete(ctx, version, xid); } +void +hyperdex_coordinator_migration_complete(struct replicant_state_machine_context* ctx, + void* obj, const char* data, size_t data_sz) +{ + PROTECT_UNINITIALIZED; + FILE* log = replicant_state_machine_log_stream(ctx); + coordinator* c = static_cast(obj); + migration_id mid; + region_id rid; + uint64_t version; + e::unpacker up(data, data_sz); + up = up >> mid >> rid >> version; + CHECK_UNPACK(migration_complete); + c->migration_complete(ctx, version, mid, rid); +} + void hyperdex_coordinator_checkpoint_stable(struct replicant_state_machine_context* ctx, void* obj, const char* data, size_t data_sz) diff --git a/coordinator/transitions.h b/coordinator/transitions.h index 7aae39633..a722a97da 100644 --- a/coordinator/transitions.h +++ b/coordinator/transitions.h @@ -80,6 +80,8 @@ TRANSITION(space_rm); TRANSITION(transfer_go_live); TRANSITION(transfer_complete); +TRANSITION(migration_complete); + TRANSITION(checkpoint_stable); TRANSITION(alarm); diff --git a/daemon/coordinator_link_wrapper.cc b/daemon/coordinator_link_wrapper.cc index 618ea47d1..7d0ed1e9b 100644 --- a/daemon/coordinator_link_wrapper.cc +++ b/daemon/coordinator_link_wrapper.cc @@ -369,11 +369,26 @@ coordinator_link_wrapper :: transfer_complete(const transfer_id& id) e::pack64be(id.get(), buf); e::pack64be(version, buf + sizeof(uint64_t)); e::intrusive_ptr rpc = new coord_rpc(); - rpc->msg << "transver complete id=" << id; + rpc->msg << "transfer complete id=" << id; make_rpc("transfer_complete", buf, 2 * sizeof(uint64_t), rpc); LOG(INFO) << "requesting that " << id << " complete"; } +void +coordinator_link_wrapper :: migration_complete(const migration_id& mid, + const region_id& rid) +{ + uint64_t version = m_daemon->m_config.version(); + char buf[3 * sizeof(uint64_t)]; + e::pack64be(mid.get(), buf); + e::pack64be(rid.get(), buf + sizeof(uint64_t)); + e::pack64be(version, buf + 2 * sizeof(uint64_t)); + e::intrusive_ptr rpc = new coord_rpc(); + rpc->msg << "migration complete id=" << mid << " " << rid; + make_rpc("migration_complete", buf, 3 * sizeof(uint64_t), rpc); + LOG(INFO) << "requesting that " << mid << " " << rid << " complete"; +} + void coordinator_link_wrapper :: report_tcp_disconnect(const server_id& id) { diff --git a/daemon/coordinator_link_wrapper.h b/daemon/coordinator_link_wrapper.h index 2fdb1c94a..b2fe24371 100644 --- a/daemon/coordinator_link_wrapper.h +++ b/daemon/coordinator_link_wrapper.h @@ -69,6 +69,8 @@ class coordinator_link_wrapper public: void transfer_go_live(const transfer_id& id); void transfer_complete(const transfer_id& id); + void migration_complete(const migration_id& mid, + const region_id& rid); void report_tcp_disconnect(const server_id& id); void config_ack(uint64_t version); void config_stable(uint64_t version); diff --git a/daemon/daemon.cc b/daemon/daemon.cc index f95da9b95..37712c743 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -776,9 +776,9 @@ void daemon :: process_req_migration(server_id from, e::slice key; std::vector checks; std::vector funcs; - uint64_t mos_id; + region_id rid; uint64_t seq_no; - up = up >> key >> flags >> checks >> funcs >> mos_id >> seq_no; + up = up >> key >> flags >> checks >> funcs >> rid >> seq_no; if (up.error()) { @@ -789,7 +789,7 @@ void daemon :: process_req_migration(server_id from, bool erase = !(flags & 128); bool fail_if_not_found = flags & 1; bool fail_if_found = flags & 2; - m_repl.request_atomic(from, vto, 0, erase, fail_if_not_found, fail_if_found, key, checks, funcs, true, mos_id, seq_no); + m_repl.request_atomic(from, vto, 0, erase, fail_if_not_found, fail_if_found, key, checks, funcs, true, rid, seq_no); } void daemon :: process_resp_migration(server_id from, @@ -798,11 +798,11 @@ void daemon :: process_resp_migration(server_id from, std::auto_ptr msg, e::unpacker up) { - uint64_t mos_id; + region_id rid; uint64_t seq_no; uint16_t result; - up = up >> mos_id >> seq_no >> result; - m_mm.migration_ack(from, vto, mos_id, seq_no, result); + up = up >> rid >> seq_no >> result; + m_mm.migration_ack(from, vto, rid, seq_no, result); } void diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index dd89ea8dc..590119c85 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -59,7 +59,6 @@ migration_manager :: migration_manager(daemon* d) , m_shutdown(true) , m_need_pause(false) , m_paused(false) - , m_next_out_state_id(1) { } @@ -121,6 +120,7 @@ migration_manager :: reconfigure(const configuration&, std::vector migrations_out; new_config.migrations_out(sid, &migrations_out); std::sort(migrations_out.begin(), migrations_out.end()); + LOG(INFO) << "We are getting " << migrations_out.size() << " migration objects."; setup_migration_state(migrations_out, &m_migrations_out); // std::vector regions; @@ -182,7 +182,6 @@ migration_manager :: setup_migration_state(const std::vector ptr( new migration_out_state(migrations[m_idx].id, migrations[m_idx].space_to, - m_next_out_state_id++, rid, iter)); tmp.push_back(ptr); @@ -215,7 +214,6 @@ migration_manager :: setup_migration_state(const std::vector ptr( new migration_out_state(migrations[m_idx].id, migrations[m_idx].space_to, - m_next_out_state_id++, rid, iter)); tmp.push_back(ptr); @@ -226,7 +224,7 @@ migration_manager :: setup_migration_state(const std::vectorsize()) { - LOG(INFO) << "ending migration out state" << (*migration_states)[ms_idx]->mid; + // LOG(INFO) << "ending migration out state" << (*migration_states)[ms_idx]->mid; ++ms_idx; } @@ -257,9 +255,9 @@ migration_manager :: migrate_more_state(migration_out_state* mos) mos->iter->next(); } - // TODO: Take a look at the corresponding method in state_transfer_manager. - // You might need to inform the coordinator about the completion of the - // migration. + if (mos->window.empty()) { + m_daemon->m_coord.migration_complete(mos->mid, mos->rid); + } } void @@ -282,16 +280,14 @@ migration_manager :: send_object(migration_out_state* mos, pending* op) std::vector checks; funcs.reserve(op->value.size()); - for (size_t j = 0; j < op->value.size(); ++j) + for (size_t j = 1; j <= op->value.size(); ++j) { - uint16_t attrnum = j; - - hyperdatatype datatype = sc->attrs[attrnum + 1].type; + hyperdatatype datatype = sc->attrs[j].type; funcall o; - o.attr = attrnum + 1; + o.attr = j; o.name = FUNC_SET; - o.arg1 = op->value[j]; + o.arg1 = op->value[j - 1]; o.arg1_datatype = datatype; funcs.push_back(o); } @@ -301,12 +297,12 @@ migration_manager :: send_object(migration_out_state* mos, pending* op) + sizeof(uint8_t) + pack_size(checks) + pack_size(funcs) - + sizeof(uint64_t) // mos_id + + sizeof(region_id) + sizeof(uint64_t); // seq_no std::auto_ptr msg(e::buffer::create(sz)); uint8_t flags = (0 | 0 | 128); msg->pack_at(HYPERDEX_HEADER_SIZE_SV) - << op->key << flags << checks << funcs << mos->id << op->seq_no; + << op->key << flags << checks << funcs << mos->rid << op->seq_no; m_daemon->m_comm.send(to, REQ_MIGRATION, msg); // TODO: do we need this here? m_daemon->m_comm.wake_one(); } @@ -314,15 +310,15 @@ migration_manager :: send_object(migration_out_state* mos, pending* op) void migration_manager :: migration_ack(const server_id& from, const virtual_server_id& to, - uint64_t mos_id, + region_id rid, uint64_t seq_no, uint16_t result) { - migration_out_state* mos = get_mos(mos_id); + migration_out_state* mos = get_mos(rid); if (!mos) { - LOG(INFO) << "dropping RESP_MIGRATION for " << mos_id << " which we don't know about"; + LOG(INFO) << "dropping RESP_MIGRATION for " << rid << " which we don't know about"; return; } @@ -360,11 +356,11 @@ migration_manager :: migration_ack(const server_id& from, } migration_manager::migration_out_state* -migration_manager :: get_mos(uint64_t out_state_id) +migration_manager :: get_mos(region_id rid) { for (size_t i = 0; i < m_migrations_out.size(); ++i) { - if (m_migrations_out[i]->id == out_state_id) + if (m_migrations_out[i]->rid == rid) { return m_migrations_out[i].get(); } diff --git a/daemon/migration_manager.h b/daemon/migration_manager.h index 1d4f790d0..c4b936bae 100644 --- a/daemon/migration_manager.h +++ b/daemon/migration_manager.h @@ -64,7 +64,7 @@ class migration_manager void migration_ack(const server_id& from, const virtual_server_id& to, - uint64_t mos_id, + region_id rid, uint64_t seq_no, uint16_t result); @@ -108,7 +108,7 @@ class migration_manager void kickstarter(); void shutdown(); - migration_out_state* get_mos(uint64_t out_state_id); + migration_out_state* get_mos(region_id rid); private: migration_manager(const migration_manager&); @@ -125,7 +125,6 @@ class migration_manager bool m_shutdown; bool m_need_pause; bool m_paused; - uint64_t m_next_out_state_id; }; END_HYPERDEX_NAMESPACE diff --git a/daemon/migration_out_state.cc b/daemon/migration_out_state.cc index ac6600a7f..f823ad63a 100644 --- a/daemon/migration_out_state.cc +++ b/daemon/migration_out_state.cc @@ -34,7 +34,6 @@ using hyperdex::migration_manager; migration_manager :: migration_out_state :: migration_out_state() : mtx() - , id(1) , next_seq_no(1) , window() , window_sz(1) @@ -47,9 +46,8 @@ migration_manager :: migration_out_state :: migration_out_state() } migration_manager :: migration_out_state :: migration_out_state(migration_id _mid, - space_id _sid, uint64_t _id, region_id _rid, std::auto_ptr _iter) + space_id _sid, region_id _rid, std::auto_ptr _iter) : mtx() - , id(_id) , next_seq_no(1) , window() , window_sz(1) diff --git a/daemon/migration_out_state.h b/daemon/migration_out_state.h index 6ed4c3d51..4e2a1b63b 100644 --- a/daemon/migration_out_state.h +++ b/daemon/migration_out_state.h @@ -51,14 +51,12 @@ class migration_manager::migration_out_state migration_out_state(); migration_out_state(migration_id mid, space_id sid, - uint64_t out_state_id, region_id rid, std::auto_ptr iter); ~migration_out_state() throw (); public: po6::threads::mutex mtx; - uint64_t id; uint64_t next_seq_no; migration_id mid; space_id sid; diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index 160c998e1..252bd3047 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -248,7 +248,7 @@ replication_manager :: client_atomic(const server_id& from, const std::vector& funcs) { request_atomic(from, to, nonce, erase, fail_if_not_found, fail_if_found, - key, checks, funcs, false, 0, 0); + key, checks, funcs, false, region_id(), 0); } void @@ -262,11 +262,11 @@ replication_manager :: request_atomic(const server_id& from, const std::vector& checks, const std::vector& funcs, bool is_migration_object, - uint64_t mos_id, + region_id rid, uint64_t seq_no) { #define respond(ret) \ - if (is_migration_object) { respond_for_migration(to, from, mos_id, seq_no, ret); } \ + if (is_migration_object) { respond_for_migration(to, from, rid, seq_no, ret); } \ else { respond_to_client(to, from, nonce, ret); } if (is_migration_object) { @@ -322,7 +322,7 @@ replication_manager :: request_atomic(const server_id& from, else { if (!ks->put_from_funcs(sc, ri, seq_id, funcs, from, nonce, - is_migration_object, mos_id, seq_id)) + is_migration_object, rid, seq_id)) { respond(NET_OVERFLOW); return; @@ -568,7 +568,7 @@ replication_manager :: chain_ack(const virtual_server_id& from, if (op->client != server_id()) { if (op->is_migration_object) { - respond_for_migration(to, op->client, op->mos_id, op->seq_no, NET_SUCCESS); + respond_for_migration(to, op->client, op->rid, op->seq_no, NET_SUCCESS); } else { respond_to_client(to, op->client, op->nonce, NET_SUCCESS); } @@ -909,7 +909,7 @@ replication_manager :: respond_to_client(const virtual_server_id& us, void replication_manager :: respond_for_migration(const virtual_server_id& us, const server_id& client, - uint64_t mos_id, + region_id rid, uint64_t seq_no, network_returncode ret) { @@ -921,7 +921,7 @@ replication_manager :: respond_for_migration(const virtual_server_id& us, + sizeof(uint16_t); std::auto_ptr msg(e::buffer::create(sz)); uint16_t result = static_cast(ret); - msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << mos_id << seq_no << result; + msg->pack_at(HYPERDEX_HEADER_SIZE_VV) << rid << seq_no << result; m_daemon->m_comm.send(us, client, RESP_MIGRATION, msg); } else { LOG(ERROR) << "migration has to originate from a server"; diff --git a/daemon/replication_manager.h b/daemon/replication_manager.h index 2b2a1f14c..922c5d05d 100755 --- a/daemon/replication_manager.h +++ b/daemon/replication_manager.h @@ -101,7 +101,7 @@ class replication_manager const std::vector& checks, const std::vector& funcs, bool is_migration_object, - uint64_t mos_id, + region_id rid, uint64_t seq_no); // These are called in response to messages from other hosts. void chain_op(const virtual_server_id& from, @@ -179,7 +179,7 @@ class replication_manager network_returncode ret); void respond_for_migration(const virtual_server_id& us, const server_id& client, - uint64_t mos_id, + region_id rid, uint64_t seq_no, network_returncode ret); // check stability diff --git a/daemon/replication_manager_key_state.cc b/daemon/replication_manager_key_state.cc index 9d96ce63d..eab82b8c5 100644 --- a/daemon/replication_manager_key_state.cc +++ b/daemon/replication_manager_key_state.cc @@ -281,7 +281,7 @@ replication_manager :: key_state :: put_from_funcs(const schema& sc, const std::vector& funcs, const server_id& client, uint64_t nonce, bool is_migration_object, - uint64_t mos_id, + region_id rid, uint64_t seq_no) { bool has_old_value = false; @@ -307,7 +307,7 @@ replication_manager :: key_state :: put_from_funcs(const schema& sc, 0, virtual_server_id()); op->is_migration_object = is_migration_object; - op->mos_id = mos_id; + op->rid = rid; op->seq_no = seq_no; if (funcs_passed == funcs.size()) diff --git a/daemon/replication_manager_key_state.h b/daemon/replication_manager_key_state.h index 429c3d2cb..b9d2f0427 100644 --- a/daemon/replication_manager_key_state.h +++ b/daemon/replication_manager_key_state.h @@ -75,7 +75,7 @@ class hyperdex::replication_manager::key_state const std::vector& funcs, const server_id& client, uint64_t nonce, bool is_migration_object, - uint64_t mos_id, uint64_t seq_no); + region_id rid, uint64_t seq_no); void insert_deferred(uint64_t version, e::intrusive_ptr op); bool persist_to_datalayer(replication_manager* rm, const region_id& ri, const region_id& reg_id, uint64_t seq_id, diff --git a/daemon/replication_manager_pending.cc b/daemon/replication_manager_pending.cc index de7e8f364..680861e55 100644 --- a/daemon/replication_manager_pending.cc +++ b/daemon/replication_manager_pending.cc @@ -62,7 +62,7 @@ replication_manager :: pending :: pending(std::auto_ptr _backing, , prev_region() , next_region() , is_migration_object() - , mos_id(0) + , rid(region_id()) , seq_no(0) , m_ref(0) { @@ -86,6 +86,6 @@ replication_manager :: pending :: debug_dump() LOG(INFO) << " this_new: " << this_new_region; LOG(INFO) << " next: " << next_region; LOG(INFO) << " is_migration_object: " << is_migration_object; - LOG(INFO) << " mos_id: " << mos_id; + LOG(INFO) << " rid: " << rid; LOG(INFO) << " seq_no: " << seq_no; } diff --git a/daemon/replication_manager_pending.h b/daemon/replication_manager_pending.h index b09ab82ac..5350b0eb5 100644 --- a/daemon/replication_manager_pending.h +++ b/daemon/replication_manager_pending.h @@ -74,7 +74,7 @@ class hyperdex::replication_manager::pending // Migration-related stuff bool is_migration_object; - uint64_t mos_id; + region_id rid; uint64_t seq_no; private: From 3c45d219b9d57db57b364e8959eea4cf9f27e1f8 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 20 Mar 2014 23:12:30 -0400 Subject: [PATCH 09/17] Fix bugs related to migration --- common/migration.cc | 37 +++++++++++++++++++++++++++++-------- coordinator/coordinator.cc | 5 +++-- daemon/migration_manager.cc | 15 +++++++++------ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/common/migration.cc b/common/migration.cc index f1fb12df3..8e3ae7056 100644 --- a/common/migration.cc +++ b/common/migration.cc @@ -85,24 +85,45 @@ hyperdex :: operator << (std::ostream& lhs, const migration& rhs) e::buffer::packer hyperdex :: operator << (e::buffer::packer pa, const migration& m) { - pa = pa << m.space_from << m.space_to << m.outstanding_regions; + size_t num_outstanding_regions = m.outstanding_regions.size(); + pa = pa << m.id.get() << m.space_from.get() << m.space_to.get() << num_outstanding_regions; + for (size_t i = 0; i < num_outstanding_regions; ++i) + { + pa = pa << m.outstanding_regions[i]; + } + return pa; } e::unpacker hyperdex :: operator >> (e::unpacker up, migration& m) { - space_id s_space_from, s_space_to; - std::vector outstanding_regions; - up >> s_space_from >> s_space_to >> outstanding_regions; - m.space_from = s_space_from; - m.space_to = s_space_to; - m.outstanding_regions = outstanding_regions; + uint64_t mid, space_from_id, space_to_id; + size_t num_outstanding_regions; + up >> mid >> space_from_id >> space_to_id >> num_outstanding_regions; + m.id = migration_id(mid); + m.space_from = space_id(space_from_id); + m.space_to = space_id(space_to_id); + m.outstanding_regions.resize(num_outstanding_regions); + for (size_t i = 0; !up.error() && i < num_outstanding_regions; ++i) + { + up = up >> m.outstanding_regions[i]; + } return up; } size_t hyperdex :: pack_size(const migration& m) { - return 2 * sizeof(uint64_t) + m.outstanding_regions.size() * sizeof(uint64_t); + size_t sz = sizeof(uint64_t) // migration id + + sizeof(uint64_t) // space_from + + sizeof(uint64_t) // space_to + + sizeof(size_t); // num_outstanding_regions + + for (size_t i = 0; i < m.outstanding_regions.size(); ++i) + { + sz += pack_size(m.outstanding_regions[i]); + } + + return sz; } diff --git a/coordinator/coordinator.cc b/coordinator/coordinator.cc index a4a571e2e..5eaf11965 100644 --- a/coordinator/coordinator.cc +++ b/coordinator/coordinator.cc @@ -770,7 +770,7 @@ coordinator :: migration_complete(replicant_state_machine_context* ctx, { if (m_migrations[m].id == mid) { - for (size_t r; r < m_migrations[m].outstanding_regions.size(); r++) + for (size_t r = 0; r < m_migrations[m].outstanding_regions.size(); r++) { if (m_migrations[m].outstanding_regions[r] == rid) { @@ -1693,11 +1693,12 @@ coordinator :: new_migration(replicant_state_machine_context* ctx, space_id space_to_id = it->second->id; migration mgt(migration_id(m_counter++), space_from_id, space_to_id); - m_migrations.push_back(mgt); space_ptr s = m_spaces[std::string(space_from)]; regions_in_space(s, &mgt.outstanding_regions); + m_migrations.push_back(mgt); + generate_next_configuration(ctx); } diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index 590119c85..243bd4c54 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -117,11 +117,12 @@ migration_manager :: reconfigure(const configuration&, } } - std::vector migrations_out; - new_config.migrations_out(sid, &migrations_out); - std::sort(migrations_out.begin(), migrations_out.end()); - LOG(INFO) << "We are getting " << migrations_out.size() << " migration objects."; - setup_migration_state(migrations_out, &m_migrations_out); + std::vector migrations; + new_config.migrations_out(sid, &migrations); + std::sort(migrations.begin(), migrations.end()); + LOG(INFO) << "We are getting " << migrations.size() << " migration objects."; + setup_migration_state(migrations, &m_migrations_out); + LOG(INFO) << "and " << m_migrations_out.size() << " migration_out objects."; // std::vector regions; // new_config.mapped_regions(sid, ®ions); @@ -161,7 +162,9 @@ migration_manager :: setup_migration_state(const std::vectormid) { tmp.push_back((*migration_states)[ms_idx]); - ++m_idx; + // TODO: commenting out the following line seems to fix the + // bug, but check the correctness of this method again. + // ++m_idx; ++ms_idx; } else if (migrations[m_idx].id < (*migration_states)[ms_idx]->mid) From e10fd271de3cc753518b510cca6bd408bd30aff6 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Fri, 21 Mar 2014 03:53:56 -0400 Subject: [PATCH 10/17] Get rid of useless debug statements --- common/configuration.cc | 35 ----------------------------------- daemon/communication.cc | 16 ---------------- daemon/replication_manager.cc | 4 ---- 3 files changed, 55 deletions(-) diff --git a/common/configuration.cc b/common/configuration.cc index f22b1d45d..d92e321b5 100644 --- a/common/configuration.cc +++ b/common/configuration.cc @@ -475,10 +475,8 @@ configuration :: point_leader(const char* sname, const e::slice& key) const virtual_server_id configuration :: point_leader(const space_id& sid, const e::slice& key) const { - std::cout << "m_spaces.size() = " << m_spaces.size() << std::endl; for (size_t s = 0; s < m_spaces.size(); ++s) { - std::cout << "sid = " << sid << " m_spaces[s].id " << m_spaces[s].id << std::endl; if (sid != m_spaces[s].id) { continue; @@ -487,7 +485,6 @@ configuration :: point_leader(const space_id& sid, const e::slice& key) const uint64_t h; hash(m_spaces[s].sc, key, &h); - std::cout << "m_spaces[s].subspaces[0].regions.size() = " << m_spaces[s].subspaces[0].regions.size() << std::endl; for (size_t pl = 0; pl < m_spaces[s].subspaces[0].regions.size(); ++pl) { if (m_spaces[s].subspaces[0].regions[pl].lower_coord[0] <= h && @@ -495,7 +492,6 @@ configuration :: point_leader(const space_id& sid, const e::slice& key) const { if (m_spaces[s].subspaces[0].regions[pl].replicas.empty()) { - std::cout << "BAD BP1" << std::endl; return virtual_server_id(); } @@ -503,11 +499,9 @@ configuration :: point_leader(const space_id& sid, const e::slice& key) const } } - std::cout << "BAD BP2" << std::endl; abort(); } - std::cout << "BAD BP3" << std::endl; return virtual_server_id(); } @@ -673,35 +667,6 @@ configuration :: transfers_out_regions(const server_id& si, std::vector* migrations) const { - // int counter = 0; - // for (size_t m = 0; m < m_migrations.size(); ++m) - // { - // const migration& mi(m_migrations[m]); - // for (size_t w = 0; w < m_spaces.size(); ++w) - // { - // const space& s(m_spaces[w]); - // if (s.id == mi.space_from) { - // for (size_t x = 0; x < s.subspaces.size(); ++x) - // { - // const subspace& ss(s.subspaces[x]); - // for (size_t y = 0; y < ss.regions.size(); ++y) - // { - // const region& r(ss.regions[y]); - // for (size_t z = 0; z < r.replicas.size(); ++z) - // { - // const replica& rr(r.replicas[z]); - // if (rr.si == sid) - // { - // counter++; - // migrations->push_back(mi); - // } - // } - // } - // } - // } - // } - // } - // std::cout << "added migrations for: " << counter << " times" << std::endl; for (size_t m = 0; m < m_migrations.size(); ++m) { migrations->push_back(m_migrations[m]); } diff --git a/daemon/communication.cc b/daemon/communication.cc index 452278002..3e7fc7679 100644 --- a/daemon/communication.cc +++ b/daemon/communication.cc @@ -301,7 +301,6 @@ communication :: send(const virtual_server_id& vto, network_msgtype msg_type, std::auto_ptr msg) { - LOG(INFO) << "SEND2 ->" << vto << " " << msg_type << " " << msg->hex(); assert(msg->size() >= HYPERDEX_HEADER_SIZE_SV); uint8_t mt = static_cast(msg_type); @@ -313,7 +312,6 @@ communication :: send(const virtual_server_id& vto, { return false; } - LOG(INFO) << "sending:" << mt << " " << flags << " " << m_daemon->m_config.version() << " " << vto.get(); #ifdef HD_LOG_ALL_MESSAGES LOG(INFO) << "SEND ->" << vto << " " << msg_type << " " << msg->hex(); @@ -456,25 +454,18 @@ communication :: recv(server_id* from, *from = server_id(id); *vto = virtual_server_id(vidt); - LOG(INFO) << "receiving " << *msg_type; - - LOG(INFO) << "RECV ->" << vidt << " " << *msg_type << " " << (*msg)->hex(); - if ((flags & 0x1)) { - LOG(INFO) << "BP6"; *up = *up >> vidf; *vfrom = virtual_server_id(vidf); } else { - LOG(INFO) << "BP5"; *vfrom = virtual_server_id(); } if (up->error()) { - LOG(INFO) << "BP4"; LOG(WARNING) << "dropping message that has a malformed header; here's some hex: " << (*msg)->hex(); continue; } @@ -486,16 +477,12 @@ communication :: recv(server_id* from, // If this is a virtual-virtual message if ((flags & 0x1)) { - LOG(INFO) << "BP3"; from_valid = *from == m_daemon->m_config.get_server_id(virtual_server_id(vidf)); } // No matter what, wait for the config the sender saw if (version > m_daemon->m_config.version()) { - LOG(INFO) << mt << " " << flags << " " << version << " " << vidt; - LOG(INFO) << version << " " << m_daemon->m_config.version(); - LOG(INFO) << "BP2"; early_message em(version, id, *msg); m_early_messages.push(em); continue; @@ -503,7 +490,6 @@ communication :: recv(server_id* from, if ((flags & 0x2) && version < m_daemon->m_config.version()) { - LOG(INFO) << "BP1"; continue; } @@ -515,8 +501,6 @@ communication :: recv(server_id* from, return true; } - LOG(INFO) << "we are done!"; - // Shove the message back at the client so it fails with a reconfigure. if (!(flags & 0x1)) { diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index 252bd3047..e09b193fa 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -269,10 +269,6 @@ replication_manager :: request_atomic(const server_id& from, if (is_migration_object) { respond_for_migration(to, from, rid, seq_no, ret); } \ else { respond_to_client(to, from, nonce, ret); } - if (is_migration_object) { - LOG(INFO) << "preparing to send a migration object"; - }; - if (m_daemon->m_config.read_only()) { respond(NET_READONLY) From bcd70a6d347b515b7ac066d8630f658fcdba9d65 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Fri, 21 Mar 2014 17:26:42 -0400 Subject: [PATCH 11/17] Fix bug in deserializing integers --- common/datatype_int64.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/datatype_int64.cc b/common/datatype_int64.cc index f87e23069..974817eb2 100644 --- a/common/datatype_int64.cc +++ b/common/datatype_int64.cc @@ -92,8 +92,10 @@ datatype_int64 :: apply(const e::slice& old_value, for (size_t i = 0; i < funcs_sz; ++i) { const funcall* func = funcs + i; - int64_t arg; - e::unpack64le(func->arg1.data(), &arg); + int64_t arg = 0; + if (func->arg1.size() == sizeof(int64_t)) { + e::unpack64le(func->arg1.data(), &arg); + } switch (func->name) { From f4e8f198ad2af938e8253fa3c3c79d6e7ab6d0c7 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Tue, 25 Mar 2014 00:43:25 -0400 Subject: [PATCH 12/17] Add a test case for migration --- test/migration-test.cc | 305 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 test/migration-test.cc diff --git a/test/migration-test.cc b/test/migration-test.cc new file mode 100644 index 000000000..f9b039d6b --- /dev/null +++ b/test/migration-test.cc @@ -0,0 +1,305 @@ +// Copyright (c) 2014, Cornell University +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of HyperDex nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include + +// STL +#include + +// e +#include + +// po6 +#include + +// armnod +#include "ygor.h" + +// HyperDex +#include +#include +#include + +const char *_space_from_name = "profiles"; +const char *_space_from_description = "space profiles \ +key username \ +attributes \ + string name, \ + float height, \ + int profile_views"; +const char *_space_to_name = "profiles2"; +const char *_space_to_description = "space profiles2 \ +key username \ +attributes \ + string name, \ + float height, \ + int profile_views"; + +static bool _quiet = false; +static int _testno = 0; +static hyperdex::Client *_cl = NULL; +static hyperdex::Admin *_ad = NULL; + +static void test0(); +static void add_space(); +static void remove_space(); + +int +main(int argc, const char *argv[]) +{ + try { + // TODO: make the host and port customizable + hyperdex::Client cl("127.0.0.1", 1982); + _cl = &cl; + hyperdex::Admin ad("127.0.0.1", 1982); + _ad = &ad; + + test0(); + + return EXIT_SUCCESS; + } catch (po6::error &e) { + std::cerr << "system error: " << e.what() << std::endl; + return EXIT_FAILURE; + } +} + +static void +success() +{ + if (!_quiet) std::cout << "Test " << _testno << ": [\x1b[32mOK\x1b[0m]\n"; +} + +#define FAIL(REASON) \ + do { \ + if (!_quiet) std::cout << "Test " << _testno << ": [\x1b[31mFAIL\x1b[0m]\n" \ + << "location: " << __FILE__ << ":" << __LINE__ << "\n" \ + << "reason: " << REASON << "\n"; \ + abort(); \ + } while (0) + +static void +setup_space() +{ + hyperdex_admin_returncode status; + if (_ad->add_space(_space_from_description, &status) < 0) { + FAIL("admin operation failed: " << status); + } + if (_ad->add_space(_space_to_description, &status) < 0) { + FAIL("admin operation failed: " << status); + } +} + +static void +remove_space() +{ + hyperdex_admin_returncode status; + if (_ad->rm_space(_space_from_name, &status) < 0) { + FAIL("admin operation failed: " << status); + } + + if (_ad->rm_space(_space_to_name, &status) < 0) { + FAIL("admin operation failed: " << status); + } +} + +static armnod_generator * +get_random_generator(const char *method, + const char *charset) +{ + armnod_config *config = armnod_config_create(); + if (armnod_config_method(config, method) < 0) goto wrong_config; + if (armnod_config_charset(config, charset) < 0) goto wrong_config; + if (armnod_config_set_size(config, 1024) < 0) goto wrong_config; + + { + armnod_generator *gen(armnod_generator_create(config)); + armnod_generator_seed(gen, 0); + return gen; + } + +wrong_config: + FAIL("armnod_config received a wrong parameter."); +} + +static void +add_data(const char *space_name, uint64_t num_objects) +{ + armnod_generator *alpha_gen = get_random_generator("normal", "alpha"); + armnod_generator *digit_gen = get_random_generator("normal", "digit"); + + const char *key_format = "object_%lu"; + for (size_t i = 0; i < num_objects; i++) { + char key[20] = {0}; + snprintf(key, 19, key_format, i); + size_t key_sz = strlen(key); + + hyperdex_client_attribute attrs[3]; + + size_t attrs_sz = 0; + + attrs[0].attr = "name"; + attrs[0].value = armnod_generate(alpha_gen); + attrs[0].value_sz = strlen(attrs[0].value); + attrs[0].datatype = HYPERDATATYPE_STRING; + + attrs[1].attr = "height"; + double valf = atof(armnod_generate(digit_gen)); + char buff[8] = {0}; + hyperdex_ds_pack_float(valf, buff); + attrs[1].value = buff; + attrs[1].value_sz = 8; + attrs[1].datatype = HYPERDATATYPE_FLOAT; + + attrs[2].attr = "profile_views"; + int64_t vali = atoi(armnod_generate(digit_gen)); + char bufi[8] = {0}; + hyperdex_ds_pack_int(vali, bufi); + attrs[2].value = bufi; + attrs[2].value_sz = 8; + attrs[2].datatype = HYPERDATATYPE_INT64; + + hyperdex_client_returncode op_status; + if (_cl->put(space_name, key, key_sz, attrs, 3, &op_status) < 0) { + FAIL("client operation failed: " << op_status); + } + + hyperdex_client_returncode loop_status; + if (_cl->loop(-1, &loop_status) < 0) { + FAIL("client operation failed: " << loop_status); + } + } +} + +inline static void +check_attr(const hyperdex_client_attribute *attr, + const char *name, + const char *value, + hyperdatatype datatype) +{ + if (strcmp(attr->attr, name) != 0) + FAIL("presence check: attribute is \"" << attr->attr << "\" instead of \"name\""); + + if (attr->datatype != datatype) + FAIL("presence check: attribute is not of datatype \"string\""); + + switch (datatype) { + case HYPERDATATYPE_STRING: { + std::string str(attr->value, attr->value_sz); + if (str.compare(value) != 0) + FAIL("presence check: attribute has the value \"" + << str << "\" instead of \"" << value << "\""); + break; + } + case HYPERDATATYPE_INT64: { + int64_t num; + hyperdex_ds_unpack_int(attr->value, attr->value_sz, &num); + int64_t val_int = atoi(value); + if (num != val_int) + FAIL("presence check: attribute has the value \"" + << num << "\" instead of \"" << val_int << "\""); + break; + } + case HYPERDATATYPE_FLOAT: { + double num; + hyperdex_ds_unpack_float(attr->value, attr->value_sz, &num); + double val_float = atof(value); + if (num != val_float) + FAIL("presence check: attribute has the value \"" + << num << "\" instead of \"" << val_float << "\""); + break; + } + default: + FAIL("Unknown datatype " << datatype); + } +} + +static void +read_and_verify_data(const char *space_name, uint64_t num_objects) +{ + armnod_generator *alpha_gen = get_random_generator("normal", "alpha"); + armnod_generator *digit_gen = get_random_generator("normal", "digit"); + + const char *key_format = "object_%lu"; + for (size_t i = 0; i < num_objects; i++) { + char key[20] = {0}; + snprintf(key, 19, key_format, i); + size_t key_sz = strlen(key); + + const hyperdex_client_attribute *attrs; + size_t attrs_sz; + + hyperdex_client_returncode get_status; + int64_t gid = _cl->get(space_name, key, key_sz, &get_status, &attrs, &attrs_sz); + if (gid < 0) { + FAIL("get encountered error: " << get_status); + } + + hyperdex_client_returncode loop_status; + int64_t lid = _cl->loop(10000, &loop_status); + if (lid < 0) { + FAIL("loop encountered error: " << loop_status); + } + + if (gid != lid) + FAIL("loop id (" << lid << ") does not match get id (" << gid << ")"); + + if (get_status != HYPERDEX_CLIENT_SUCCESS) + FAIL("operation " << gid << " (a presence check) returned " << get_status); + + check_attr(&attrs[0], "name", armnod_generate(alpha_gen), HYPERDATATYPE_STRING); + check_attr(&attrs[1], "height", armnod_generate(digit_gen), HYPERDATATYPE_FLOAT); + check_attr(&attrs[2], "profile_views", armnod_generate(digit_gen), HYPERDATATYPE_INT64); + } + + // armnod_config_destroy(alpha_gen->config); + armnod_generator_destroy(alpha_gen); + // armnod_config_destroy(digit_gen->config); + armnod_generator_destroy(digit_gen); +} + +static uint64_t num_objects = 1000; + +static void +test0() +{ + setup_space(); + + add_data(_space_from_name, num_objects); + + hyperdex_admin_returncode status; + if (_ad->migrate_data(_space_from_name, _space_to_name, &status) < 0) { + FAIL("migration failure: " << status); + } + + std::cout << "Sleeping for 5 seconds for the migration to complete...\n"; + usleep(5 * 1000 * 1000); + + read_and_verify_data(_space_to_name, num_objects); + + remove_space(); + success(); +} From a3c63ed2ea9096ba8892ed51aa1e9a3ac3bc490a Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Wed, 26 Mar 2014 00:36:53 -0400 Subject: [PATCH 13/17] Clean up --- daemon/coordinator_link_wrapper.cc | 2 +- daemon/migration_manager.cc | 6 ++++-- daemon/replication_manager.cc | 7 ------- test/migration-test.cc | 6 +++--- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/daemon/coordinator_link_wrapper.cc b/daemon/coordinator_link_wrapper.cc index 7d0ed1e9b..ef5f10ad0 100644 --- a/daemon/coordinator_link_wrapper.cc +++ b/daemon/coordinator_link_wrapper.cc @@ -386,7 +386,7 @@ coordinator_link_wrapper :: migration_complete(const migration_id& mid, e::intrusive_ptr rpc = new coord_rpc(); rpc->msg << "migration complete id=" << mid << " " << rid; make_rpc("migration_complete", buf, 3 * sizeof(uint64_t), rpc); - LOG(INFO) << "requesting that " << mid << " " << rid << " complete"; + // LOG(INFO) << "requesting that " << mid << " " << rid << " complete"; } void diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index 243bd4c54..bb7b03b48 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -227,7 +227,6 @@ migration_manager :: setup_migration_state(const std::vectorsize()) { - // LOG(INFO) << "ending migration out state" << (*migration_states)[ms_idx]->mid; ++ms_idx; } @@ -321,7 +320,10 @@ migration_manager :: migration_ack(const server_id& from, if (!mos) { - LOG(INFO) << "dropping RESP_MIGRATION for " << rid << " which we don't know about"; + // TODO: it seems that sometimes we receive ACK for regions + // that have already been completely migrated. Why is that? + // Does that indicate a bug? + // LOG(INFO) << "dropping RESP_MIGRATION for " << rid << " which we don't know about."; return; } diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index e09b193fa..95dd50abd 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -569,20 +569,14 @@ replication_manager :: chain_ack(const virtual_server_id& from, respond_to_client(to, op->client, op->nonce, NET_SUCCESS); } } - else - { - LOG(INFO) << "Oh well I'm not replying RESP_ATOMIC"; - } if (is_head && m_daemon->m_config.version() == op->recv_config_version) { - LOG(INFO) << "Sending ack to head"; send_ack(to, op->recv, false, reg_id, seq_id, version, key); } if (op->reg_id == ri) { - LOG(INFO) << "In the same region"; bool x; x = m_idcol.collect(ri, op->seq_id); assert(x); @@ -909,7 +903,6 @@ replication_manager :: respond_for_migration(const virtual_server_id& us, uint64_t seq_no, network_returncode ret) { - LOG(INFO) << "sending response for a migration object"; if (m_daemon->m_config.exists(client)) { size_t sz = HYPERDEX_HEADER_SIZE_VV + sizeof(uint64_t) diff --git a/test/migration-test.cc b/test/migration-test.cc index f9b039d6b..d0b2db831 100644 --- a/test/migration-test.cc +++ b/test/migration-test.cc @@ -281,7 +281,7 @@ read_and_verify_data(const char *space_name, uint64_t num_objects) armnod_generator_destroy(digit_gen); } -static uint64_t num_objects = 1000; +static uint64_t num_objects = 100000; static void test0() @@ -295,8 +295,8 @@ test0() FAIL("migration failure: " << status); } - std::cout << "Sleeping for 5 seconds for the migration to complete...\n"; - usleep(5 * 1000 * 1000); + std::cout << "Sleeping for 10 seconds for the migration to complete...\n"; + usleep(10 * 1000 * 1000); read_and_verify_data(_space_to_name, num_objects); From f32041ef2800ed06481735d62cc6a5c178760edf Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Wed, 26 Mar 2014 01:18:13 -0400 Subject: [PATCH 14/17] Bug fix --- daemon/migration_manager.cc | 6 ++++++ test/migration-test.cc | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index bb7b03b48..5171883a7 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -278,6 +278,12 @@ migration_manager :: send_object(migration_out_state* mos, pending* op) virtual_server_id to = m_daemon->m_config.point_leader(mos->sid, op->key); const schema* sc = m_daemon->m_config.get_schema(op->rid); + if (sc == NULL) { + // TODO: this happens occationally. Not sure why. Possibly because the + // related space has been destroyed? + LOG(INFO) << "trying to send an object whose region no longer exists."; + return; + } std::vector funcs; std::vector checks; funcs.reserve(op->value.size()); diff --git a/test/migration-test.cc b/test/migration-test.cc index d0b2db831..ffe109ccb 100644 --- a/test/migration-test.cc +++ b/test/migration-test.cc @@ -295,8 +295,8 @@ test0() FAIL("migration failure: " << status); } - std::cout << "Sleeping for 10 seconds for the migration to complete...\n"; - usleep(10 * 1000 * 1000); + std::cout << "Sleeping for 20 seconds for the migration to complete...\n"; + usleep(20 * 1000 * 1000); read_and_verify_data(_space_to_name, num_objects); From 57aa34d4d38d3e876325e71329f69920a8396f78 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Wed, 26 Mar 2014 01:56:10 -0400 Subject: [PATCH 15/17] Delete a file that was accidentally introduced --- bindings/python/_hyperdex_admin.pyx | 343 ---------------------------- 1 file changed, 343 deletions(-) delete mode 100644 bindings/python/_hyperdex_admin.pyx diff --git a/bindings/python/_hyperdex_admin.pyx b/bindings/python/_hyperdex_admin.pyx deleted file mode 100644 index e132d19b0..000000000 --- a/bindings/python/_hyperdex_admin.pyx +++ /dev/null @@ -1,343 +0,0 @@ -# Copyright (c) 2013, Cornell University -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of HyperDex nor the names of its contributors may be -# used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -from cpython cimport bool - -cdef extern from "stdint.h": - - ctypedef short int int16_t - ctypedef unsigned short int uint16_t - ctypedef int int32_t - ctypedef unsigned int uint32_t - ctypedef long int int64_t - ctypedef unsigned long int uint64_t - ctypedef long unsigned int size_t - -cdef extern from "stdlib.h": - - void* malloc(size_t size) - void free(void* ptr) - -cdef extern from "sys/socket.h": - - ctypedef uint16_t in_port_t - cdef struct sockaddr - -cdef extern from "../../include/hyperdex/admin.h": - - cdef struct hyperdex_admin - - cdef struct hyperdex_admin_perf_counter: - uint64_t id - uint64_t time - char* property - uint64_t measurement - - cdef enum hyperdex_admin_returncode: - HYPERDEX_ADMIN_SUCCESS = 8704 - HYPERDEX_ADMIN_NOMEM = 8768 - HYPERDEX_ADMIN_NONEPENDING = 8769 - HYPERDEX_ADMIN_POLLFAILED = 8770 - HYPERDEX_ADMIN_TIMEOUT = 8771 - HYPERDEX_ADMIN_INTERRUPTED = 8772 - HYPERDEX_ADMIN_COORDFAIL = 8774 - HYPERDEX_ADMIN_SERVERERROR = 8773 - HYPERDEX_ADMIN_INTERNAL = 8829 - HYPERDEX_ADMIN_EXCEPTION = 8830 - HYPERDEX_ADMIN_GARBAGE = 8831 - - hyperdex_admin* hyperdex_admin_create(char* coordinator, uint16_t port) - void hyperdex_admin_destroy(hyperdex_admin* admin) - int64_t hyperdex_admin_add_space(hyperdex_admin* admin, char* description, hyperdex_admin_returncode* status) - int64_t hyperdex_admin_rm_space(hyperdex_admin* admin, char* space, hyperdex_admin_returncode* status) - int64_t hyperdex_admin_dump_config(hyperdex_admin* admin, hyperdex_admin_returncode* status, char** config) - int64_t hyperdex_admin_enable_perf_counters(hyperdex_admin* admin, hyperdex_admin_returncode* status, hyperdex_admin_perf_counter* pc) - void hyperdex_admin_disable_perf_counters(hyperdex_admin* admin) - int64_t hyperdex_admin_loop(hyperdex_admin* admin, int timeout, hyperdex_admin_returncode* status) nogil - -import collections -import struct - -class HyperDexAdminException(Exception): - def __init__(self, status, attr=None): - self._status = status - self._s = {HYPERDEX_ADMIN_SUCCESS: 'Success' - ,HYPERDEX_ADMIN_NOMEM: 'Memory allocation failed' - ,HYPERDEX_ADMIN_NONEPENDING: 'None pending' - ,HYPERDEX_ADMIN_POLLFAILED: 'Polling Failed' - ,HYPERDEX_ADMIN_TIMEOUT: 'Timeout' - ,HYPERDEX_ADMIN_INTERRUPTED: 'Interrupted by a signal' - ,HYPERDEX_ADMIN_COORDFAIL: 'Coordinator Failure' - ,HYPERDEX_ADMIN_SERVERERROR: 'Server Error' - ,HYPERDEX_ADMIN_INTERNAL: 'Internal Error (file a bug)' - ,HYPERDEX_ADMIN_EXCEPTION: 'Internal Exception (file a bug)' - ,HYPERDEX_ADMIN_GARBAGE: 'Internal Corruption (file a bug)' - }.get(status, 'Unknown Error (file a bug)') - self.e = {HYPERDEX_ADMIN_SUCCESS: 'HYPERDEX_ADMIN_SUCCESS' - ,HYPERDEX_ADMIN_NOMEM: 'HYPERDEX_ADMIN_NOMEM' - ,HYPERDEX_ADMIN_NONEPENDING: 'HYPERDEX_ADMIN_NONEPENDING' - ,HYPERDEX_ADMIN_POLLFAILED: 'HYPERDEX_ADMIN_POLLFAILED' - ,HYPERDEX_ADMIN_TIMEOUT: 'HYPERDEX_ADMIN_TIMEOUT' - ,HYPERDEX_ADMIN_INTERRUPTED: 'HYPERDEX_ADMIN_INTERRUPTED' - ,HYPERDEX_ADMIN_COORDFAIL: 'HYPERDEX_ADMIN_COORDFAIL' - ,HYPERDEX_ADMIN_SERVERERROR: 'HYPERDEX_ADMIN_SERVERERROR' - ,HYPERDEX_ADMIN_INTERNAL: 'HYPERDEX_ADMIN_INTERNAL' - ,HYPERDEX_ADMIN_EXCEPTION: 'HYPERDEX_ADMIN_EXCEPTION' - ,HYPERDEX_ADMIN_GARBAGE: 'HYPERDEX_ADMIN_GARBAGE' - }.get(status, 'BUG') - - def status(self): - return self._status - - def symbol(self): - return self._e - - def __str__(self): - return 'HyperDexAdminException(%s, %s)' % (self._e, self._s) - - def __repr__(self): - return str(self) - - def __eq__(self, other): - if self.__class__ != other.__class__: - return False - return self._status == other._status - - def __ne__(self, other): - return not (self == other) - -cdef class DeferredAddSpace: - - cdef Admin _admin - cdef int64_t _reqid - cdef hyperdex_admin_returncode _status - cdef bint _finished - - def __cinit__(self, Admin admin, bytes space): - self._admin = admin - self._reqid = 0 - self._status = HYPERDEX_ADMIN_GARBAGE - self._finished = False - self._reqid = hyperdex_admin_add_space(self._admin._admin, - space, &self._status) - if self._reqid < 0: - raise HyperDexAdminException(self._status) - self._admin._ops[self._reqid] = self - - def _callback(self): - self._finished = True - del self._admin._ops[self._reqid] - - def wait(self): - while not self._finished and self._reqid > 0: - self._admin.loop() - self._finished = True - if self._status == HYPERDEX_ADMIN_SUCCESS: - return True - else: - raise HyperDexAdminException(self._status) - -cdef class DeferredRmSpace: - - cdef Admin _admin - cdef int64_t _reqid - cdef hyperdex_admin_returncode _status - cdef bint _finished - - def __cinit__(self, Admin admin, bytes space): - self._admin = admin - self._reqid = 0 - self._status = HYPERDEX_ADMIN_GARBAGE - self._finished = False - self._reqid = hyperdex_admin_rm_space(self._admin._admin, - space, &self._status) - if self._reqid < 0: - raise HyperDexAdminException(self._status) - self._admin._ops[self._reqid] = self - - def _callback(self): - self._finished = True - del self._admin._ops[self._reqid] - - def wait(self): - while not self._finished and self._reqid > 0: - self._admin.loop() - self._finished = True - if self._status == HYPERDEX_ADMIN_SUCCESS: - return True - else: - raise HyperDexAdminException(self._status) - -cdef class DeferredString: - - cdef Admin _admin - cdef int64_t _reqid - cdef hyperdex_admin_returncode _status - cdef char* _cstr - cdef str _pstr - cdef bint _finished - - def __cinit__(self, Admin admin, *args): - self._admin = admin - self._reqid = 0 - self._status = HYPERDEX_ADMIN_GARBAGE - self._cstr = NULL - self._pstr = "" - self._finished = False - self._reqid = hyperdex_admin_dump_config(self._admin._admin, - &self._status, - &self._cstr) - if self._reqid < 0: - raise HyperDexAdminException(self._status) - self._admin._ops[self._reqid] = self - - def _callback(self): - if self._cstr: - self._pstr = self._cstr - self._finished = True - del self._admin._ops[self._reqid] - - def wait(self): - while not self._finished and self._reqid > 0: - self._admin.loop() - self._finished = True - if self._status == HYPERDEX_ADMIN_SUCCESS: - ret = {'cluster': 0, 'version': 0, 'servers': []} - for line in self._pstr.split('\n'): - if line.startswith('cluster'): - ret['cluster'] = int(line.split(' ')[1]) - if line.startswith('version'): - ret['version'] = int(line.split(' ')[1]) - if line.startswith('server'): - sid, loc, state = line.split(' ')[1:] - server = {'id': sid, 'location': loc, 'state': state} - ret['servers'].append(server) - return ret - else: - raise HyperDexAdminException(self._status) - -cdef class DeferredPerfCounter: - - cdef Admin _admin - cdef int64_t _reqid - cdef hyperdex_admin_returncode _status - cdef hyperdex_admin_perf_counter _pc - cdef bint _finished - cdef list _backlogged - - def __cinit__(self, Admin admin, *args): - self._admin = admin - self._reqid = 0 - self._status = HYPERDEX_ADMIN_GARBAGE - self._finished = False - self._backlogged = [] - - def __iter__(self): - return self - - def __next__(self): - while not self._finished and not self._backlogged: - self._admin.loop() - if self._backlogged: - return self._backlogged.pop() - raise StopIteration() - - def _callback(self): - if self._status == HYPERDEX_ADMIN_SUCCESS: - self._backlogged.append({'server': self._pc.id - ,'time': self._pc.time - ,'property': self._pc.property - ,'measurement': self._pc.measurement}) - else: - self._backlogged.append(HyperDexAdminException(self._status)) - -cdef class Admin: - cdef hyperdex_admin* _admin - cdef dict _ops - cdef DeferredPerfCounter _pc - - def __cinit__(self, address, port): - self._admin = hyperdex_admin_create(address, port) - self._ops = {} - self._pc = None - - def __dealloc__(self): - if self._admin: - hyperdex_admin_destroy(self._admin) - - def async_dump_config(self): - return DeferredString(self) - - def dump_config(self): - return self.async_dump_config().wait() - - def async_add_space(self, space): - return DeferredAddSpace(self, space) - - def add_space(self, space): - return self.async_add_space(space).wait() - - def async_rm_space(self, space): - return DeferredRmSpace(self, space) - - def rm_space(self, space): - return self.async_rm_space(space).wait() - - def enable_perf_counters(self): - cdef hyperdex_admin_returncode rc - if self._pc: - return self._pc - self._pc = DeferredPerfCounter(self) - self._pc._reqid = hyperdex_admin_enable_perf_counters(self._admin, - &self._pc._status, - &self._pc._pc) - if self._pc._reqid < 0: - rc = self._pc._status - self._pc = None - raise HyperDexAdminException(rc) - self._ops[self._pc._reqid] = self._pc - return self._pc - - def disable_perf_counters(self): - hyperdex_admin_disable_perf_counters(self._admin) - self._pc._finished = True - del self._ops[self._pc._reqid] - self._pc = None - - def loop(self): - cdef hyperdex_admin_returncode rc - with nogil: - ret = hyperdex_admin_loop(self._admin, -1, &rc) - if ret < 0: - raise HyperDexAdminException(rc) - else: - assert ret in self._ops - op = self._ops[ret] - # We cannot refer to self._ops[ret] after this call as - # _callback() may remove ret from self._ops. - op._callback() - return op From ccc95578d45da6bb59c1a23bcf733a15dbb61e95 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Wed, 26 Mar 2014 02:32:08 -0400 Subject: [PATCH 16/17] Cleanup --- daemon/daemon.cc | 36 +---------------------------------- daemon/daemon.h | 2 -- daemon/migration_manager.cc | 17 ----------------- daemon/migration_manager.h | 27 -------------------------- daemon/replication_manager.cc | 16 ++++++++-------- 5 files changed, 9 insertions(+), 89 deletions(-) diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 37712c743..190205525 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -130,7 +130,6 @@ daemon :: daemon() , m_perf_xfer_ack() , m_perf_backup() , m_perf_perf_counters() - , m_perf_resp_atomic() , m_perf_resp_migration() , m_block_stat_path() , m_stat_collector(std::tr1::bind(&daemon::collect_stats, this)) @@ -517,7 +516,6 @@ daemon :: loop(size_t thread) THREAD_AFFINITY_POLICY_COUNT); #endif - LOG(INFO) << "My server id is: " << m_us; LOG(INFO) << "network thread " << thread << " started on core " << core; if (sigfillset(&ss) < 0) @@ -556,10 +554,6 @@ daemon :: loop(size_t thread) process_req_atomic(from, vfrom, vto, msg, up); m_perf_req_atomic.tap(); break; - case RESP_ATOMIC: - process_resp_atomic(from, vfrom, vto, msg, up); - m_perf_resp_atomic.tap(); - break; case REQ_MIGRATION: process_req_migration(from, vfrom, vto, msg, up); m_perf_req_migration.tap(); @@ -645,6 +639,7 @@ daemon :: loop(size_t thread) m_perf_perf_counters.tap(); break; case RESP_GET: + case RESP_ATOMIC: case RESP_SEARCH_ITEM: case RESP_SEARCH_DONE: case RESP_SORTED_SEARCH: @@ -737,35 +732,6 @@ daemon :: process_req_atomic(server_id from, m_repl.client_atomic(from, vto, nonce, erase, fail_if_not_found, fail_if_found, key, checks, funcs); } -void -daemon :: process_resp_atomic(server_id from, - virtual_server_id vfrom, - virtual_server_id vto, - std::auto_ptr msg, - e::unpacker up) -{ - // TODO: get rid of this function - - // // size_t sz = HYPERDEX_HEADER_SIZE_VC - // // + sizeof(uint64_t) - // // + sizeof(uint16_t); - // // std::auto_ptr msg(e::buffer::create(sz)); - // // uint16_t result = static_cast(ret); - // // msg->pack_at(HYPERDEX_HEADER_SIZE_VC) << nonce << result; - // // m_daemon->m_comm.send_client(us, client, RESP_ATOMIC, msg); - // uint64_t nonce; - // uint16_t result; - // up = up >> nonce >> result; - - // LOG(WARNING) << "nonce: " << nonce << " result: " << result << std::endl; - - // if (up.error()) - // { - // LOG(WARNING) << "unpack of REQ_ATOMIC failed; here's some hex: " << msg->hex(); - // return; - // } -} - void daemon :: process_req_migration(server_id from, virtual_server_id vfrom, virtual_server_id vto, diff --git a/daemon/daemon.h b/daemon/daemon.h index 74ec64caa..0e63c6fd1 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -75,7 +75,6 @@ class daemon void loop(size_t thread); void process_req_get(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); - void process_resp_atomic(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_migration(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_resp_migration(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); void process_req_search_start(server_id from, virtual_server_id vfrom, virtual_server_id vto, std::auto_ptr msg, e::unpacker up); @@ -150,7 +149,6 @@ class daemon performance_counter m_perf_xfer_ack; performance_counter m_perf_backup; performance_counter m_perf_perf_counters; - performance_counter m_perf_resp_atomic; performance_counter m_perf_resp_migration; // iostat-like stats std::string m_block_stat_path; diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index 5171883a7..4a9b649bc 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -120,24 +120,7 @@ migration_manager :: reconfigure(const configuration&, std::vector migrations; new_config.migrations_out(sid, &migrations); std::sort(migrations.begin(), migrations.end()); - LOG(INFO) << "We are getting " << migrations.size() << " migration objects."; setup_migration_state(migrations, &m_migrations_out); - LOG(INFO) << "and " << m_migrations_out.size() << " migration_out objects."; - - // std::vector regions; - // new_config.mapped_regions(sid, ®ions); - - // std::vector::iterator m_iter; - // for (m_iter = migrations_out.begin(); m_iter != migrations_out.end(); m_iter++) { - // std::vector::iterator r_iter; - // for (r_iter = regions.begin(); r_iter != regions.end(); r_iter++) { - // region_id rid = (*r_iter); - // if (new_config.space_of(rid) == (*m_iter).space_from) { - // e::intrusive_ptr ptr(new migration_out_state((*m_iter).space_to, rid)); - // m_migrations_out.push_back(ptr); - // } - // } - // } } void diff --git a/daemon/migration_manager.h b/daemon/migration_manager.h index c4b936bae..f5790b91a 100644 --- a/daemon/migration_manager.h +++ b/daemon/migration_manager.h @@ -68,33 +68,6 @@ class migration_manager uint64_t seq_no, uint16_t result); - // public: - // void handshake_syn(const virtual_server_id& from, - // const migration_id& xid); - // void handshake_synack(const server_id& from, - // const virtual_server_id& to, - // const migration_id& xid, - // uint64_t timestamp); - // void handshake_ack(const virtual_server_id& from, - // const migration_id& xid, - // bool wipe); - // void handshake_wiped(const server_id& from, - // const virtual_server_id& to, - // const migration_id& xid); - // void report_wiped(const migration_id& xid); - // void xfer_op(const virtual_server_id& from, - // const migration_id& xid, - // uint64_t seq_no, - // bool has_value, - // uint64_t version, - // std::auto_ptr msg, - // const e::slice& key, - // const std::vector& value); - // void xfer_ack(const server_id& from, - // const virtual_server_id& to, - // const migration_id& xid, - // uint64_t seq_no); - private: class pending; class migration_out_state; diff --git a/daemon/replication_manager.cc b/daemon/replication_manager.cc index 95dd50abd..951abceb0 100644 --- a/daemon/replication_manager.cc +++ b/daemon/replication_manager.cc @@ -238,14 +238,14 @@ replication_manager :: debug_dump() void replication_manager :: client_atomic(const server_id& from, - const virtual_server_id& to, - uint64_t nonce, - bool erase, - bool fail_if_not_found, - bool fail_if_found, - const e::slice& key, - const std::vector& checks, - const std::vector& funcs) + const virtual_server_id& to, + uint64_t nonce, + bool erase, + bool fail_if_not_found, + bool fail_if_found, + const e::slice& key, + const std::vector& checks, + const std::vector& funcs) { request_atomic(from, to, nonce, erase, fail_if_not_found, fail_if_found, key, checks, funcs, false, region_id(), 0); From 005950ac333584407d78d1789f0699a2d167d884 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 27 Mar 2014 15:37:58 -0400 Subject: [PATCH 17/17] Bug fix --- daemon/datalayer.cc | 8 ++++++-- daemon/datalayer.h | 3 ++- daemon/migration_manager.cc | 8 ++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/daemon/datalayer.cc b/daemon/datalayer.cc index ea36c5ad4..2b0e4906c 100644 --- a/daemon/datalayer.cc +++ b/daemon/datalayer.cc @@ -978,12 +978,16 @@ datalayer :: get_from_iterator(const region_id& ri, uint64_t* version, reference* ref) { - const schema& sc(*m_daemon->m_config.get_schema(ri)); + const schema *sc = m_daemon->m_config.get_schema(ri); + if (sc == NULL) { + return INVALID_REGION; + } + std::vector scratch; // create the encoded key leveldb::Slice lkey; - encode_key(ri, sc.attrs[0].type, iter->key(), &scratch, &lkey); + encode_key(ri, sc->attrs[0].type, iter->key(), &scratch, &lkey); // perform the read leveldb::ReadOptions opts; diff --git a/daemon/datalayer.h b/daemon/datalayer.h index 22c82f399..3c98b0e05 100644 --- a/daemon/datalayer.h +++ b/daemon/datalayer.h @@ -71,7 +71,8 @@ class datalayer BAD_ENCODING, CORRUPTION, IO_ERROR, - LEVELDB_ERROR + LEVELDB_ERROR, + INVALID_REGION }; class reference; class iterator; diff --git a/daemon/migration_manager.cc b/daemon/migration_manager.cc index 4a9b649bc..5aee79afa 100644 --- a/daemon/migration_manager.cc +++ b/daemon/migration_manager.cc @@ -229,9 +229,13 @@ migration_manager :: migrate_more_state(migration_out_state* mos) ++mos->next_seq_no; // TODO: can an object has no value? - if (m_daemon->m_data.get_from_iterator(mos->rid, mos->iter.get(), &op->key, &op->value, &op->version, &op->vref) != datalayer::SUCCESS) + datalayer::returncode rc = m_daemon->m_data.get_from_iterator(mos->rid, mos->iter.get(), &op->key, &op->value, &op->version, &op->vref); + if (rc != datalayer::SUCCESS) { - LOG(ERROR) << "error unpacking value during migration"; + if (rc == datalayer::INVALID_REGION) + LOG(INFO) << "trying to send an object whose region no longer exists."; + else + LOG(ERROR) << "error unpacking value during migration"; break; }