/**
 * pay attention to the work of different block buffer according to the
 * comments near it
 */
bool ExchangeSenderPipeline::Open(SegmentExecStatus* const exec_status,
                                  const PartitionOffset&) {
  RETURN_IF_CANCELLED(exec_status);
  state_.child_->Open(exec_status, state_.partition_offset_);
  RETURN_IF_CANCELLED(exec_status);

  upper_num_ = state_.upper_id_list_.size();
  partition_function_ =
      PartitionFunctionFactory::createBoostHashFunction(upper_num_);
  socket_fd_upper_list_ = new int[upper_num_];

  /**
   * initialize the block that is used to accumulate the block obtained
   * by calling child iterator's next()
   */
  block_for_asking_ =
      BlockStreamBase::createBlock(state_.schema_, state_.block_size_);

  /**
   * partitioned_data_buffer_ stores the tuples received from child iterator.
   * Note the tuples are partitioned and stored.
   */
  partitioned_data_buffer_ = new PartitionedBlockBuffer(
      upper_num_, block_for_asking_->getSerializedBlockSize());

  /**
   * the temporary block that is used to transfer a block from partitioned data
   * buffer into sending_buffer.
   */
  block_for_sending_buffer_ =
      new BlockContainer(block_for_asking_->getSerializedBlockSize());

  /**
   * Initialize the buffer that is used to hold the blocks being sent. There are
   * upper_num blocks, each corresponding to a merger.
   */
  sending_buffer_ = new PartitionedBlockContainer(
      upper_num_, block_for_asking_->getSerializedBlockSize());

  // Initialized the temporary block to hold the serialized block.

  block_for_serialization_ =
      new Block(block_for_asking_->getSerializedBlockSize());

  /**
   * Initialize the blocks that are used to accumulate the tuples from child so
   * that the insertion to the buffer
   * can be conducted at the granularity of blocks rather than tuples.
   */
  partitioned_block_stream_ = new BlockStreamBase* [upper_num_];
  for (unsigned i = 0; i < upper_num_; ++i) {
    partitioned_block_stream_[i] =
        BlockStreamBase::createBlock(state_.schema_, state_.block_size_);
  }
  RETURN_IF_CANCELLED(exec_status);

  /** connect to all the mergers **/
  for (unsigned upper_offset = 0; upper_offset < state_.upper_id_list_.size();
       ++upper_offset) {
    RETURN_IF_CANCELLED(exec_status);

    LOG(INFO) << "(exchane_id= " << state_.exchange_id_
              << " partition_offset= " << state_.partition_offset_
              << " ) try to connect to upper( " << upper_offset << " , "
              << state_.upper_id_list_[upper_offset] << " ) ";

    if (ConnectToUpper(ExchangeID(state_.exchange_id_, upper_offset),
                       state_.upper_id_list_[upper_offset],
                       socket_fd_upper_list_[upper_offset]) != true) {
      LOG(INFO) << "unsuccessfully !" << std::endl;
      return false;
    }
  }
  LOG(INFO) << "connect to all mereger successfully !" << std::endl;

  RETURN_IF_CANCELLED(exec_status);

  /** create the Sender thread **/
  int error = pthread_create(&sender_thread_id_, NULL, Sender, this);
  if (error != 0) {
    LOG(ERROR) << "(exchane_id= " << state_.exchange_id_
               << " partition_offset= " << state_.partition_offset_
               << " ) Failed to create the sender thread>>>>>>>>>>"
               << std::endl;
    return false;
  }
  return true;
}
bool ExpandableBlockStreamExchangeLowerEfficient::open(const PartitionOffset&) {
  logging_->log("[%lld] Exchange lower is created!", state_.exchange_id_);

  debug_connected_uppers = 0;
  debug_connected_uppers_in = 0;
  state_.child_->open(state_.partition_offset_);

  nuppers_ = state_.upper_id_list_.size();
  partition_function_ = PartitionFunctionFactory::createBoostHashFunction(
      nuppers_);
  socket_fd_upper_list = new int[nuppers_];

  /** initialize the block stream that is used to accumulate the block obtained by calling child iterator's next() **/
  block_stream_for_asking_ = BlockStreamBase::createBlock(state_.schema_,
                                                          state_.block_size_);

  /** buffer stores the tuples received from child iterator. Note the tuples are partitioned and stored. **/
  partitioned_data_buffer_ = new PartitionedBlockBuffer(
      nuppers_, block_stream_for_asking_->getSerializedBlockSize());

  /** the temporary block that is used to transfer a block from partitioned data buffer into sending buffer.**/
  block_for_buffer_ = new BlockContainer(
      block_stream_for_asking_->getSerializedBlockSize());

  /** Initialize the buffer that is used to hold the blocks being sent. There are nuppers block, each corresponding
   * to a merger. **/
  sending_buffer_ = new PartitionedBlockContainer(
      nuppers_, block_stream_for_asking_->getSerializedBlockSize());

  /** Initialized the temporary block to hold the serialized block stream. **/
  block_for_serialization_ = new Block(
      block_stream_for_asking_->getSerializedBlockSize());

  /** Initialize the blocks that are used to accumulate the tuples from child so that the insertion to the buffer
   * can be conducted at the granularity of blocks rather than tuples.
   */
  partitioned_block_stream_ = new BlockStreamBase*[nuppers_];
  for (unsigned i = 0; i < nuppers_; i++) {
    partitioned_block_stream_[i] = BlockStreamBase::createBlock(
        state_.schema_, state_.block_size_);
  }

  /** connect to all the mergers **/
  for (unsigned upper_offset = 0; upper_offset < state_.upper_id_list_.size();
      upper_offset++) {

    logging_->log("[%ld,%d] try to connect to upper (%d) %s\n",
                  state_.exchange_id_, state_.partition_offset_, upper_offset,
                  state_.upper_id_list_[upper_offset]);
    if (ConnectToUpper(ExchangeID(state_.exchange_id_, upper_offset),
                       state_.upper_id_list_[upper_offset],
                       socket_fd_upper_list[upper_offset], logging_) != true) return false;
    printf("[%ld,%d] connected to upper [%d,%d] on Node %d\n",
           state_.exchange_id_, state_.partition_offset_, state_.exchange_id_,
           upper_offset, state_.upper_id_list_[upper_offset]);
  }

  /** create the sender thread **/
//	if (true == g_thread_pool_used) {
//		Environment::getInstance()->getThreadPool()->add_task(sender, this);
//	}
//	else {
  int error;
  error = pthread_create(&sender_tid, NULL, sender, this);
  if (error != 0) {
    logging_->elog(
        "Failed to create the sender thread>>>>>>>>>>>>>>>>>>>>>>>>>>>>@@#@#\n\n.");
    return false;
  }
//	}
//	pthread_create(&debug_tid,NULL,debug,this);
  /*debug*/
  return true;
}