15670430创建于 2020年12月28日历史提交
/*
 * Copyright (c) 2020 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * streamTransportComm.cpp
 *	  Support methods for class StreamCOMM.
 *
 * IDENTIFICATION
 *	  src/gausskernel/process/stream/streamTransportComm.cpp
 *
 * -------------------------------------------------------------------------
 */
#include "postgres.h"
#include "knl/knl_variable.h"
#include "libcomm/libcomm.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "distributelayer/streamCore.h"
#include "distributelayer/streamTransportCore.h"
#include "distributelayer/streamTransportComm.h"

StreamCOMM::StreamCOMM(libcommaddrinfo* addr, bool flag) : m_addr(addr)
{
    m_nodeName[0] = '\0';
    m_nodeoid = InvalidOid;
    m_type = STREAM_COMM;
    m_sendSide = flag;
    m_port = NULL;
    m_buffer = NULL;
}

StreamCOMM::~StreamCOMM()
{
    m_addr = NULL;
}

/*
 * @Description: Send a normal message
 *
 * @param[IN] msgtype:  message type
 * @param[IN] msg:  pointer to message body
 * @param[IN] len:  length of the message
 * @return: 0 if OK, EOF if trouble
 */
int StreamCOMM::send(char msgtype, const char* msg, size_t len)
{
    return pq_putmessage(msgtype, msg, len);
}

/*
 * @Description: Flush pending output
 *
 * @return: void
 */
void StreamCOMM::flush()
{
    pq_flush();
}

/*
 * @Description: Close stream
 *
 * @return: void
 */
void StreamCOMM::release()
{
    gs_close_gsocket(&(m_addr->gs_sock));
}

/*
 * @Description: Init stream port
 * @param[IN] dbname: database name inherited from StreamProducer.
 * @param[IN] usrname: user name inherited from StreamProducer.
 * @return: void
 */
void StreamCOMM::init(char* dbname, char* usrname)
{
    m_port->sock = NO_SOCKET;
    m_port->libcomm_addrinfo = m_addr;
    m_port->database_name = dbname;
    m_port->user_name = usrname;
}

/*
 * @Description: Allocate net buffer for stream port
 *
 * @return: void
 */
void StreamCOMM::allocNetBuffer()
{
    m_port = (Port*)palloc0(sizeof(Port));

    if (m_sendSide) {
        m_buffer = (StreamBuffer*)palloc0(sizeof(StreamBuffer));
        m_buffer->PqSendBufferSize = STREAM_BUFFER_SIZE;
        m_buffer->PqSendPointer = 0;
        m_buffer->PqSendStart = 0;
        m_buffer->PqCommBusy = false;
    }
}

/*
 * @Description: Set send buffer active
 *
 * @return: void
 */
bool StreamCOMM::setActive()
{
    /*
     * if we use parallel send mode,
     * and the head of address info list is already close,
     * we must continue to send,
     * and gs_broadcast can send to other node in address info list.
     */
    if (m_addr->parallel_send_mode == true) {
        /*
         * if we use parallel send mode,
         * we only send to head node of address info list,
         * and do not care other node in address info list,
         * gs_broadcast can parallel send to other node.
         */
        if (m_addr->addr_list_size == 0)
            return false;
    } else if (m_addr->gs_sock.type == GSOCK_INVALID) {
        return false;
    }

    u_sess->proc_cxt.MyProcPort = m_port;

    t_thrd.libpq_cxt.PqSendBuffer = &m_buffer->PqSendBuffer[0];
    t_thrd.libpq_cxt.PqSendPointer = m_buffer->PqSendPointer;
    t_thrd.libpq_cxt.PqSendBufferSize = m_buffer->PqSendBufferSize;
    t_thrd.libpq_cxt.PqSendStart = m_buffer->PqSendStart;
    t_thrd.libpq_cxt.PqCommBusy = m_buffer->PqCommBusy;

    return true;
}

/*
 * @Description: Is stream closed?
 *
 * @return: true if already closed
 */
bool StreamCOMM::isClosed()
{
    return (m_addr->gs_sock.type == GSOCK_INVALID);
}

/*
 * @Description: Set send buffer inactive
 *
 * @return: void
 */
void StreamCOMM::setInActive()
{
    m_buffer->PqSendPointer = t_thrd.libpq_cxt.PqSendPointer;
    m_buffer->PqSendStart = t_thrd.libpq_cxt.PqSendStart;
    m_buffer->PqCommBusy = t_thrd.libpq_cxt.PqCommBusy;
}

/*
 * @Description: Update connection info
 *
 * @param[IN] connInfo:  connection info
 * @return: void
 */
void StreamCOMM::updateInfo(StreamConnInfo* connInfo)
{
    int nodeNameLen = strlen(connInfo->nodeName);
    errno_t rc = EOK;

    m_addr->gs_sock = connInfo->port.libcomm_layer.gsock;
    rc = strncpy_s(m_nodeName, NAMEDATALEN, connInfo->nodeName, nodeNameLen + 1);
    securec_check(rc, "\0", "\0");
    m_addr->streamKey.producerSmpId = connInfo->producerSmpId;
}