void MigrationVerifyActor::handleVerifyRequest(const idgs::actor::ActorMessagePtr& msg) {
  pb::MigrationVerifyRequest* request = NULL;
  if (msg->getPayload()) {
    request = dynamic_cast<pb::MigrationVerifyRequest*>(msg->getPayload().get());
  }

  if (request && request->has_schema_name() && request->has_store_name()) {
    auto datastore = idgs::store::idgs_store_module()->getDataStore();
    auto store = datastore->getStore(request->schema_name(), request->store_name());
    if (!store) {
      LOG(ERROR) << "store " << request->schema_name() << "." << request->store_name() << " is not found.";
      auto payload = std::make_shared<pb::MigrationVerifyResponse>();
      payload->set_result_code(static_cast<int32_t>(RC_STORE_NOT_FOUND));
      auto respMsg = msg->createResponse();
      respMsg->setOperationName("VERIFY_RESPONSE");
      respMsg->setPayload(payload);
      idgs::actor::sendMessage(respMsg);
      return;
    }

    if (store->getStoreConfig()->getStoreConfig().partition_type() != idgs::store::pb::PARTITION_TABLE) {
      LOG(ERROR) << "store " << request->schema_name() << "." << request->store_name() << " is not a partition store.";
      auto payload = std::make_shared<pb::MigrationVerifyResponse>();
      payload->set_result_code(static_cast<int32_t>(RC_STORE_NOT_FOUND));
      auto respMsg = msg->createResponse();
      respMsg->setOperationName("VERIFY_RESPONSE");
      respMsg->setPayload(payload);
      idgs::actor::sendMessage(respMsg);
      return;
    }
  }

  clientMsg = msg;
  auto& members = idgs_application()->getMemberManager()->getMemberTable();
  auto it = members.begin();
  for (; it != members.end(); ++ it) {
    if (it->isLocalStore() && (it->getState() == idgs::pb::MS_PREPARED || it->getState() == idgs::pb::MS_ACTIVE)) {
      auto reqMsg = createActorMessage();
      reqMsg->setOperationName("LOCAL_VERIFY_REQUEST");
      reqMsg->setDestMemberId(it->getId());
      reqMsg->setDestActorId(actorId);
      reqMsg->setPayload(msg->getPayload());
      idgs::actor::sendMessage(reqMsg);
      ++ memberSize;
    }
  }
}
void PairStoreDelegateRddPartition::handleActionRequest(const idgs::actor::ActorMessagePtr& msg) {
  ActionRequest* request = dynamic_cast<ActionRequest*>(msg->getPayload().get());
  DVLOG(3) << getPartitionName() << " run " << request->action_op_name() << " action";

  shared_ptr<ActionResponse> response = make_shared<ActionResponse>();
  response->set_action_id(request->action_id());
  response->set_partition(partition);
  ActionMgr& actionMgr = *idgs_rdd_module()->getActionManager();
  const ActionPtr& action = actionMgr.get(request->action_op_name());

  RddResultCode code = RRC_SUCCESS;
  if (action.get()) {
    if (rddLocal->isReplicatedRdd() && partition > 0) {
      code = RRC_SUCCESS;
    } else {
      action::ActionContext ctx;
      if (ctx.initContext(&msg, &rddLocal->getKeyTemplate(), &rddLocal->getValueTemplate())) {
        code = action->action(&ctx, this);
        if (code == RRC_SUCCESS) {
          auto& result = ctx.getPartitionResult();
          for (int32_t i = 0; i < result.size(); ++i) {
            response->add_action_value(result[i].toString());
          }
        }
      } else {
        code = RRC_INVALID_ACTION_PARAM;
      }
    }
  } else {
    LOG(ERROR)<< "action " << request->action_op_name() << " is not registered.";
    code = RRC_ACTION_NOT_FOUND;
  }

  response->set_result_code(code);

  VLOG(2) << getPartitionName() << " process " << request->action_op_name() << " action done.";
  auto respMsg = msg->createResponse();
  respMsg->setOperationName(RDD_ACTION_RESPONSE);
  respMsg->setPayload(response);
  idgs::actor::sendMessage(respMsg);
}
void StoreMigrationSourceActor::handleMigrationRequest(const idgs::actor::ActorMessagePtr& msg) {
  // migration data
  if (it->hasNext()) {
    std::shared_ptr<pb::MigrationData> payload = std::make_shared<pb::MigrationData>();

    size_t cnt = 0;
    auto mode = static_cast<protobuf::SerdesMode>(msg->getSerdesType());
    while (it->hasNext() && cnt < batchSize) {
      auto data = payload->add_data();
      data->set_operation_name(OP_INTERNAL_INSERT);
      protobuf::ProtoSerdesHelper::serialize(mode, it->key().get(), data->mutable_key());
      protobuf::ProtoSerdesHelper::serialize(mode, it->value().get().get(), data->mutable_value());

      ++ cnt;
      it->next();
    }

    auto reqMsg = msg->createResponse();
    reqMsg->setOperationName(MIGRATION_DATA);
    reqMsg->setPayload(payload);
    idgs::actor::postMessage(reqMsg);

    return;
  }

  // migration store cache
  if (!redoLog.empty()) {
    std::shared_ptr<pb::MigrationData> payload = std::make_shared<pb::MigrationData>();

    auto mode = static_cast<protobuf::SerdesMode>(msg->getSerdesType());
    size_t cnt = 0;

    while (!redoLog.empty() && cnt < batchSize) {
      MigrationRedoLog info;
      redoLog.try_pop(info);

      if (!info.key) {
        continue;
      }

      auto data = payload->add_data();
      data->set_operation_name(info.opName);
      protobuf::ProtoSerdesHelper::serialize(mode, info.key.get(), data->mutable_key());
      if (info.value) {
        protobuf::ProtoSerdesHelper::serialize(mode, info.value.get(), data->mutable_value());
      }

      ++ cnt;
    }

    auto reqMsg = msg->createResponse();
    reqMsg->setOperationName(MIGRATION_DATA);
    reqMsg->setPayload(payload);
    idgs::actor::postMessage(reqMsg);

    return;
  }

  auto& wrapper = pstore->getStoreConfig();
  auto& schemaName = wrapper->getSchema();
  auto& storeName = wrapper->getStoreConfig().name();

  auto payload = std::make_shared<pb::StoreMigrationComplete>();
  payload->set_schema_name(schemaName);
  payload->set_store_name(storeName);
  payload->set_data_size(map->size());

  auto respMsg = msg->createResponse();
  respMsg->setOperationName(STORE_MIGRATION_COMPLETE);
  respMsg->setPayload(payload);
  DVLOG(2) << "store " << schemaName << "." << storeName << " of partition " << partId << " migration complete on source member ";
  idgs::actor::sendMessage(respMsg);

  terminate();
}
void MigrationVerifyActor::handleLocalVerifyRequest(const idgs::actor::ActorMessagePtr& msg) {
  pb::MigrationVerifyRequest* request = NULL;
  if (msg->getPayload()) {
    request = dynamic_cast<pb::MigrationVerifyRequest*>(msg->getPayload().get());
  }

  auto datastore = idgs::store::idgs_store_module()->getDataStore();
  std::vector<idgs::store::StorePtr> stores;
  if (request && request->has_schema_name() && request->has_store_name()) {
    auto store = datastore->getStore(request->schema_name(), request->store_name());
    stores.push_back(store);
  } else {
    datastore->getStores(stores);
  }

  auto app = idgs_application();
  auto cluster = app->getClusterFramework();
  auto pcnt = cluster->getPartitionCount();
  auto bkcnt = cluster->getClusterConfig()->max_replica_count() - 1;
  auto local = cluster->getLocalMember()->getId();
  auto partitionMgr = app->getPartitionManager();

  auto payload = std::make_shared<pb::MigrationVerifyResponse>();
  payload->set_result_code(static_cast<int32_t>(RC_SUCCESS));

  auto memberData = payload->add_member_data();
  memberData->set_member_id(local);

  for (int32_t i = 0; i < stores.size(); ++ i) {
    auto& store = stores.at(i);
    auto& storeConfigWrapper = store->getStoreConfig();
    if (storeConfigWrapper->getStoreConfig().partition_type() == idgs::store::pb::PARTITION_TABLE) {
      auto pstore = dynamic_cast<idgs::store::PartitionedStore*>(store.get());

      auto& schemaName = store->getStoreConfig()->getSchema();
      auto& storeName = store->getStoreConfig()->getStoreConfig().name();
      auto storeData = memberData->add_store_data();
      storeData->set_schema_name(schemaName);
      storeData->set_store_name(storeName);

      for (int32_t p = 0; p < pcnt; ++ p) {
        auto partition = partitionMgr->getPartition(p);
        for (int32_t pos = 0; pos < bkcnt + 1; ++ pos) {
          if (partition->getMemberId(pos) == local) {
            auto partitionData = storeData->add_partition_data();
            partitionData->set_partition_id(p);
            partitionData->set_position(pos);
            partitionData->set_member_id(local);
            partitionData->set_size(pstore->dataSize(p));
            VLOG(0) << schemaName << "." << storeName << " partition " << p << "(" << pos << ") data size " << partitionData->size() << " on member " << local;

            std::shared_ptr<idgs::store::StoreMap> map;
            pstore->snapshotStore(p, map);
            auto it = map->iterator();
            while (it->hasNext()) {
              idgs::store::StoreOption ps;
              storeConfigWrapper->calculatePartitionInfo(it->key(), &ps);
              ps.memberId = partitionMgr->getPartition(ps.partitionId)->getMemberId(pos);

              auto keyPartition = partitionData->add_key_partition();
              keyPartition->set_key_partition_id(ps.partitionId);
              keyPartition->set_key_member_id(ps.memberId);

              it->next();
            }
          }
        }
      }
    }
  }

  auto respMsg = msg->createResponse();
  respMsg->setOperationName("VERIFY_RESPONSE");
  respMsg->setPayload(payload);
  idgs::actor::sendMessage(respMsg);
}