class RpcHeartbeatTrigger implements HeartbeatTrigger {
    private static final Logger logger                 = BoltLoggerFactory.getLogger("RpcRemoting");

    /** max trigger times */
    public static final Integer maxCount               = ConfigManager.tcp_idle_maxtimes();

    private static final long   heartbeatTimeoutMillis = 1000;

    private CommandFactory      commandFactory;

    public RpcHeartbeatTrigger(CommandFactory commandFactory) {
        this.commandFactory = commandFactory;
    }

    /**
     * @see com.alipay.remoting.HeartbeatTrigger#heartbeatTriggered(io.netty.channel.ChannelHandlerContext)
     */
    @Override
    public void heartbeatTriggered(final ChannelHandlerContext ctx) throws Exception {<FILL_FUNCTION_BODY>}
}

        Integer heartbeatTimes = ctx.channel().attr(Connection.HEARTBEAT_COUNT).get();
        final Connection conn = ctx.channel().attr(Connection.CONNECTION).get();
        if (heartbeatTimes >= maxCount) {
            try {
                conn.close();
                logger.error(
                    "Heartbeat failed for {} times, close the connection from client side: {} ",
                    heartbeatTimes, RemotingUtil.parseRemoteAddress(ctx.channel()));
            } catch (Exception e) {
                logger.warn("Exception caught when closing connection in SharableHandler.", e);
            }
        } else {
            boolean heartbeatSwitch = ctx.channel().attr(Connection.HEARTBEAT_SWITCH).get();
            if (!heartbeatSwitch) {
                return;
            }
            final HeartbeatCommand heartbeat = new HeartbeatCommand();

            final InvokeFuture future = new DefaultInvokeFuture(heartbeat.getId(),
                new InvokeCallbackListener() {
                    @Override
                    public void onResponse(InvokeFuture future) {
                        ResponseCommand response;
                        try {
                            response = (ResponseCommand) future.waitResponse(0);
                        } catch (InterruptedException e) {
                            logger.error("Heartbeat ack process error! Id={}, from remoteAddr={}",
                                heartbeat.getId(), RemotingUtil.parseRemoteAddress(ctx.channel()),
                                e);
                            return;
                        }
                        if (response != null
                            && response.getResponseStatus() == ResponseStatus.SUCCESS) {
                            if (logger.isDebugEnabled()) {
                                logger.debug("Heartbeat ack received! Id={}, from remoteAddr={}",
                                    response.getId(),
                                    RemotingUtil.parseRemoteAddress(ctx.channel()));
                            }
                            ctx.channel().attr(Connection.HEARTBEAT_COUNT).set(0);
                        } else {
                            if (response != null
                                && response.getResponseStatus() == ResponseStatus.TIMEOUT) {
                                logger.error("Heartbeat timeout! The address is {}",
                                    RemotingUtil.parseRemoteAddress(ctx.channel()));
                            } else {
                                logger.error(
                                    "Heartbeat exception caught! Error code={}, The address is {}",
                                    response == null ? null : response.getResponseStatus(),
                                    RemotingUtil.parseRemoteAddress(ctx.channel()));
                            }
                            Integer times = ctx.channel().attr(Connection.HEARTBEAT_COUNT).get();
                            ctx.channel().attr(Connection.HEARTBEAT_COUNT).set(times + 1);
                        }
                    }

                    @Override
                    public String getRemoteAddress() {
                        return ctx.channel().remoteAddress().toString();
                    }
                }, null, heartbeat.getProtocolCode().getFirstByte(), this.commandFactory);
            final int heartbeatId = heartbeat.getId();
            conn.addInvokeFuture(future);
            if (logger.isDebugEnabled()) {
                logger.debug("Send heartbeat, successive count={}, Id={}, to remoteAddr={}",
                    heartbeatTimes, heartbeatId, RemotingUtil.parseRemoteAddress(ctx.channel()));
            }
            ctx.writeAndFlush(heartbeat).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (future.isSuccess()) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Send heartbeat done! Id={}, to remoteAddr={}",
                                heartbeatId, RemotingUtil.parseRemoteAddress(ctx.channel()));
                        }
                    } else {
                        logger.error("Send heartbeat failed! Id={}, to remoteAddr={}", heartbeatId,
                            RemotingUtil.parseRemoteAddress(ctx.channel()));
                    }
                }
            });
            TimerHolder.getTimer().newTimeout(new TimerTask() {
                @Override
                public void run(Timeout timeout) throws Exception {
                    InvokeFuture future = conn.removeInvokeFuture(heartbeatId);
                    if (future != null) {
                        future.putResponse(commandFactory.createTimeoutResponse(conn
                            .getRemoteAddress()));
                        future.tryAsyncExecuteInvokeCallbackAbnormally();
                    }
                }
            }, heartbeatTimeoutMillis, TimeUnit.MILLISECONDS);
        }

    
<no_super_class>