private void doLeaveAndReplace(
      ServerPeer serverpeer, TreeNode treeNode, SPLeaveFindReplacementNodeBody body) {
    Message result = null;
    Head thead = new Head();
    Body tbody = null, tbodyLeave = null;

    try {
      AdjacentNodeInfo adjacentInfo;
      Vector<String> transferWorkList;

      int i;

      adjacentInfo =
          new AdjacentNodeInfo(
              treeNode.getParentNode().getPhysicalInfo(),
              treeNode.getParentNode().getLogicalInfo());
      transferWorkList =
          SPGeneralAction.getTransferWorkList(
              treeNode, treeNode.getParentNode().getLogicalInfo().toString());

      /*
       * send update adjacent request to its adjacent node,
       * and leave request to its parent
       */
      treeNode.getContent().setData(SPGeneralAction.loadData());

      if ((treeNode.getLogicalInfo().getNumber() % 2) == 0) {
        tbodyLeave =
            new SPLeaveBody(
                serverpeer.getPhysicalInfo(),
                treeNode.getLogicalInfo(),
                treeNode.getContent(),
                treeNode.getRightAdjacentNode(),
                true,
                transferWorkList,
                treeNode.getParentNode().getLogicalInfo());

        if (treeNode.getRightAdjacentNode() != null) {
          tbody =
              new SPUpdateAdjacentLinkBody(
                  serverpeer.getPhysicalInfo(),
                  treeNode.getLogicalInfo(),
                  adjacentInfo,
                  false,
                  treeNode.getRightAdjacentNode().getLogicalInfo());

          thead.setMsgType(MsgType.SP_UPDATE_ADJACENT_LINK.getValue());
          result = new Message(thead, tbody);
          serverpeer.sendMessage(treeNode.getRightAdjacentNode().getPhysicalInfo(), result);
        }
      } else {
        tbodyLeave =
            new SPLeaveBody(
                serverpeer.getPhysicalInfo(),
                treeNode.getLogicalInfo(),
                treeNode.getContent(),
                treeNode.getLeftAdjacentNode(),
                false,
                transferWorkList,
                treeNode.getParentNode().getLogicalInfo());

        if (treeNode.getLeftAdjacentNode() != null) {
          tbody =
              new SPUpdateAdjacentLinkBody(
                  serverpeer.getPhysicalInfo(),
                  treeNode.getLogicalInfo(),
                  adjacentInfo,
                  true,
                  treeNode.getLeftAdjacentNode().getLogicalInfo());

          thead.setMsgType(MsgType.SP_UPDATE_ADJACENT_LINK.getValue());
          result = new Message(thead, tbody);
          serverpeer.sendMessage(treeNode.getLeftAdjacentNode().getPhysicalInfo(), result);
        }
      }

      thead.setMsgType(MsgType.SP_LEAVE.getValue());
      result = new Message(thead, tbodyLeave);
      serverpeer.sendMessage(treeNode.getParentNode().getPhysicalInfo(), result);

      /*
       * notify its neighbor nodes
       */
      RoutingTableInfo leftRoutingTable = treeNode.getLeftRoutingTable();
      RoutingItemInfo temptInfo;

      for (i = 0; i < leftRoutingTable.getTableSize(); i++) {
        temptInfo = leftRoutingTable.getRoutingTableNode(i);
        if (temptInfo != null) {
          tbody =
              new SPUpdateRoutingTableDirectlyBody(
                  serverpeer.getPhysicalInfo(),
                  treeNode.getLogicalInfo(),
                  null,
                  i,
                  true,
                  temptInfo.getLogicalInfo());

          thead.setMsgType(MsgType.SP_UPDATE_ROUTING_TABLE_DIRECTLY.getValue());
          result = new Message(thead, tbody);
          serverpeer.sendMessage(temptInfo.getPhysicalInfo(), result);
        }
      }

      RoutingTableInfo rightRoutingTable = treeNode.getRightRoutingTable();
      for (i = 0; i < rightRoutingTable.getTableSize(); i++) {
        temptInfo = rightRoutingTable.getRoutingTableNode(i);
        if (temptInfo != null) {
          tbody =
              new SPUpdateRoutingTableDirectlyBody(
                  serverpeer.getPhysicalInfo(),
                  treeNode.getLogicalInfo(),
                  null,
                  i,
                  false,
                  temptInfo.getLogicalInfo());

          thead.setMsgType(MsgType.SP_UPDATE_ROUTING_TABLE_DIRECTLY.getValue());
          result = new Message(thead, tbody);
          serverpeer.sendMessage(temptInfo.getPhysicalInfo(), result);
        }
      }

      /*
       * ready to replace
       */
      tbody =
          new SPLeaveFindReplacementNodeReplyBody(
              serverpeer.getPhysicalInfo(), body.getLogicalRequester());

      thead.setMsgType(MsgType.SP_LEAVE_FIND_REPLACEMENT_NODE_REPLY.getValue());
      result = new Message(thead, tbody);
      serverpeer.sendMessage(body.getPhysicalRequester(), result);

      // 4. delete logical node
      SPGeneralAction.deleteTreeNode(serverpeer, treeNode);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }