You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-08-01 06:46:55 +03:00
MCOL-5152 This patch enables PP to put ByteStreams into DEC input queue directly for a local PP-EM connection
This commit is contained in:
@ -1243,7 +1243,7 @@ void BatchPrimitiveProcessorJL::createBPP(ByteStream& bs) const
|
|||||||
* (projection count)x run msgs for projection Commands
|
* (projection count)x run msgs for projection Commands
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void BatchPrimitiveProcessorJL::runBPP(ByteStream& bs, uint32_t pmNum)
|
void BatchPrimitiveProcessorJL::runBPP(ByteStream& bs, uint32_t pmNum, bool isExeMgrDEC)
|
||||||
{
|
{
|
||||||
ISMPacketHeader ism;
|
ISMPacketHeader ism;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@ -1276,6 +1276,8 @@ void BatchPrimitiveProcessorJL::runBPP(ByteStream& bs, uint32_t pmNum)
|
|||||||
|
|
||||||
bs << dbRoot;
|
bs << dbRoot;
|
||||||
bs << count;
|
bs << count;
|
||||||
|
uint8_t sentByEM = (isExeMgrDEC) ? 1 : 0;
|
||||||
|
bs << sentByEM;
|
||||||
|
|
||||||
if (_hasScan)
|
if (_hasScan)
|
||||||
idbassert(ridCount == 0);
|
idbassert(ridCount == 0);
|
||||||
|
@ -137,7 +137,7 @@ class BatchPrimitiveProcessorJL
|
|||||||
void addElementType(const StringElementType&, uint32_t dbroot);
|
void addElementType(const StringElementType&, uint32_t dbroot);
|
||||||
// void setRowGroupData(const rowgroup::RowGroup &);
|
// void setRowGroupData(const rowgroup::RowGroup &);
|
||||||
|
|
||||||
void runBPP(messageqcpp::ByteStream&, uint32_t pmNum);
|
void runBPP(messageqcpp::ByteStream&, uint32_t pmNum, bool isExeMgrDEC);
|
||||||
void abortProcessing(messageqcpp::ByteStream*);
|
void abortProcessing(messageqcpp::ByteStream*);
|
||||||
|
|
||||||
/* After serializing a BPP object, reset it and it's ready for more input */
|
/* After serializing a BPP object, reset it and it's ready for more input */
|
||||||
|
@ -921,7 +921,7 @@ void DistributedEngineComm::StartClientListener(boost::shared_ptr<MessageQueueCl
|
|||||||
fPmReader.push_back(thrd);
|
fPmReader.push_back(thrd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DistributedEngineComm::addDataToOutput(SBS sbs, uint32_t connIndex, Stats* stats)
|
void DistributedEngineComm::addDataToOutput(SBS sbs)
|
||||||
{
|
{
|
||||||
ISMPacketHeader* hdr = (ISMPacketHeader*)(sbs->buf());
|
ISMPacketHeader* hdr = (ISMPacketHeader*)(sbs->buf());
|
||||||
PrimitiveHeader* p = (PrimitiveHeader*)(hdr + 1);
|
PrimitiveHeader* p = (PrimitiveHeader*)(hdr + 1);
|
||||||
@ -931,6 +931,39 @@ void DistributedEngineComm::addDataToOutput(SBS sbs, uint32_t connIndex, Stats*
|
|||||||
boost::mutex::scoped_lock lk(fMlock);
|
boost::mutex::scoped_lock lk(fMlock);
|
||||||
MessageQueueMap::iterator map_tok = fSessionMessages.find(uniqueId);
|
MessageQueueMap::iterator map_tok = fSessionMessages.find(uniqueId);
|
||||||
|
|
||||||
|
// The message for a session that doesn't exist.
|
||||||
|
if (map_tok == fSessionMessages.end())
|
||||||
|
{
|
||||||
|
// Here gets the dead session ByteStream that is already removed
|
||||||
|
// from DEC queue.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mqe = map_tok->second;
|
||||||
|
lk.unlock();
|
||||||
|
|
||||||
|
if (pmCount > 0)
|
||||||
|
{
|
||||||
|
// I hardcoded the unacked Worker id here. ACK isn't important
|
||||||
|
// for the local exchange b/c there is no need to
|
||||||
|
// enable flowcontrol localy on PM.
|
||||||
|
(void)atomicops::atomicInc(&mqe->unackedWork[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] TSQSize_t queueSize = mqe->queue.push(sbs);
|
||||||
|
// There will be no statistics about data transfered
|
||||||
|
// over the memory.
|
||||||
|
}
|
||||||
|
|
||||||
|
void DistributedEngineComm::addDataToOutput(SBS sbs, uint32_t connIndex, Stats* stats)
|
||||||
|
{
|
||||||
|
ISMPacketHeader* hdr = (ISMPacketHeader*)(sbs->buf());
|
||||||
|
PrimitiveHeader* p = (PrimitiveHeader*)(hdr + 1);
|
||||||
|
uint32_t uniqueId = p->UniqueID;
|
||||||
|
boost::shared_ptr<MQE> mqe;
|
||||||
|
boost::mutex::scoped_lock lk(fMlock);
|
||||||
|
MessageQueueMap::iterator map_tok = fSessionMessages.find(uniqueId);
|
||||||
|
|
||||||
if (map_tok == fSessionMessages.end())
|
if (map_tok == fSessionMessages.end())
|
||||||
{
|
{
|
||||||
// For debugging...
|
// For debugging...
|
||||||
@ -1036,9 +1069,9 @@ int DistributedEngineComm::writeToClient(size_t aPMIndex, const ByteStream& bs,
|
|||||||
// reconfig the connection array
|
// reconfig the connection array
|
||||||
ClientList tempConns;
|
ClientList tempConns;
|
||||||
{
|
{
|
||||||
//cout << "WARNING: DEC WRITE BROKEN PIPE " << fPmConnections[index]->otherEnd()<<
|
//cout << "WARNING: DEC WRITE BROKEN PIPE " <<
|
||||||
endl; boost::mutex::scoped_lock onErrLock(fOnErrMutex); string moduleName =
|
fPmConnections[index]->otherEnd()<< endl; boost::mutex::scoped_lock onErrLock(fOnErrMutex); string
|
||||||
fPmConnections[index]->moduleName();
|
moduleName = fPmConnections[index]->moduleName();
|
||||||
//cout << "module name = " << moduleName << endl;
|
//cout << "module name = " << moduleName << endl;
|
||||||
if (index >= fPmConnections.size()) return 0;
|
if (index >= fPmConnections.size()) return 0;
|
||||||
|
|
||||||
|
@ -201,7 +201,13 @@ class DistributedEngineComm
|
|||||||
return fRm->getPsCount() * cpp;
|
return fRm->getPsCount() * cpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isExeMgrDEC() const
|
||||||
|
{
|
||||||
|
return fIsExeMgr;
|
||||||
|
}
|
||||||
|
|
||||||
messageqcpp::Stats getNetworkStats(uint32_t uniqueID);
|
messageqcpp::Stats getNetworkStats(uint32_t uniqueID);
|
||||||
|
void addDataToOutput(messageqcpp::SBS sbs);
|
||||||
|
|
||||||
friend class ::TestDistributedEngineComm;
|
friend class ::TestDistributedEngineComm;
|
||||||
|
|
||||||
@ -251,7 +257,6 @@ class DistributedEngineComm
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void addDataToOutput(messageqcpp::SBS, uint32_t connIndex, messageqcpp::Stats* statsToAdd);
|
void addDataToOutput(messageqcpp::SBS, uint32_t connIndex, messageqcpp::Stats* statsToAdd);
|
||||||
|
|
||||||
/** @brief Writes data to the client at the index
|
/** @brief Writes data to the client at the index
|
||||||
*
|
*
|
||||||
* Continues trying to write data to the client at the next index until all clients have been tried.
|
* Continues trying to write data to the client at the next index until all clients have been tried.
|
||||||
|
@ -1047,12 +1047,13 @@ void TupleBPS::storeCasualPartitionInfo(const bool estimateRowCounts)
|
|||||||
const EMEntry& extent = colCmd->getExtents()[idx];
|
const EMEntry& extent = colCmd->getExtents()[idx];
|
||||||
|
|
||||||
/* If any column filter eliminates an extent, it doesn't get scanned */
|
/* If any column filter eliminates an extent, it doesn't get scanned */
|
||||||
scanFlags[idx] = scanFlags[idx] && (extent.colWid <= utils::MAXCOLUMNWIDTH) && // XXX: change to named constant.
|
scanFlags[idx] =
|
||||||
|
scanFlags[idx] && (extent.colWid <= utils::MAXCOLUMNWIDTH) && // XXX: change to named constant.
|
||||||
(ignoreCP || extent.partition.cprange.isValid != BRM::CP_VALID ||
|
(ignoreCP || extent.partition.cprange.isValid != BRM::CP_VALID ||
|
||||||
colCmd->getColType().colWidth != extent.colWid ||
|
colCmd->getColType().colWidth != extent.colWid ||
|
||||||
lbidListVec[i]->CasualPartitionPredicate(
|
lbidListVec[i]->CasualPartitionPredicate(extent.partition.cprange, &(colCmd->getFilterString()),
|
||||||
extent.partition.cprange, &(colCmd->getFilterString()), colCmd->getFilterCount(),
|
colCmd->getFilterCount(), colCmd->getColType(),
|
||||||
colCmd->getColType(), colCmd->getBOP(), colCmd->getIsDict()));
|
colCmd->getBOP(), colCmd->getIsDict()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2032,7 +2033,7 @@ void TupleBPS::makeJobs(vector<Job>* jobs)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
startingLBID = scannedExtents[i].range.start;
|
startingLBID = scannedExtents[i].range.start;
|
||||||
|
bool isExeMgrDEC = fDec->isExeMgrDEC();
|
||||||
while (blocksToScan > 0)
|
while (blocksToScan > 0)
|
||||||
{
|
{
|
||||||
uint32_t blocksThisJob = min(blocksToScan, blocksPerJob);
|
uint32_t blocksThisJob = min(blocksToScan, blocksPerJob);
|
||||||
@ -2040,7 +2041,7 @@ void TupleBPS::makeJobs(vector<Job>* jobs)
|
|||||||
fBPP->setLBID(startingLBID, scannedExtents[i]);
|
fBPP->setLBID(startingLBID, scannedExtents[i]);
|
||||||
fBPP->setCount(blocksThisJob);
|
fBPP->setCount(blocksThisJob);
|
||||||
bs.reset(new ByteStream());
|
bs.reset(new ByteStream());
|
||||||
fBPP->runBPP(*bs, (*dbRootConnectionMap)[scannedExtents[i].dbRoot]);
|
fBPP->runBPP(*bs, (*dbRootConnectionMap)[scannedExtents[i].dbRoot], isExeMgrDEC);
|
||||||
jobs->push_back(
|
jobs->push_back(
|
||||||
Job(scannedExtents[i].dbRoot, (*dbRootConnectionMap)[scannedExtents[i].dbRoot], blocksThisJob, bs));
|
Job(scannedExtents[i].dbRoot, (*dbRootConnectionMap)[scannedExtents[i].dbRoot], blocksThisJob, bs));
|
||||||
blocksToScan -= blocksThisJob;
|
blocksToScan -= blocksThisJob;
|
||||||
@ -2373,8 +2374,10 @@ void TupleBPS::receiveMultiPrimitiveMessages()
|
|||||||
for (uint32_t z = 0; z < size; z++)
|
for (uint32_t z = 0; z < size; z++)
|
||||||
{
|
{
|
||||||
if (bsv[z]->length() > 0 && fBPP->countThisMsg(*(bsv[z])))
|
if (bsv[z]->length() > 0 && fBPP->countThisMsg(*(bsv[z])))
|
||||||
|
{
|
||||||
++msgsRecvd;
|
++msgsRecvd;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//@Bug 1424,1298
|
//@Bug 1424,1298
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include "serviceexemgr.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -140,6 +141,7 @@ BatchPrimitiveProcessor::BatchPrimitiveProcessor()
|
|||||||
, ptMask(0)
|
, ptMask(0)
|
||||||
, firstInstance(false)
|
, firstInstance(false)
|
||||||
, valuesLBID(0)
|
, valuesLBID(0)
|
||||||
|
, initiatedByEM_(false)
|
||||||
{
|
{
|
||||||
pp.setLogicalBlockMode(true);
|
pp.setLogicalBlockMode(true);
|
||||||
pp.setBlockPtr((int*)blockData);
|
pp.setBlockPtr((int*)blockData);
|
||||||
@ -193,6 +195,7 @@ BatchPrimitiveProcessor::BatchPrimitiveProcessor(ByteStream& b, double prefetch,
|
|||||||
// ptMask(processorThreads - 1),
|
// ptMask(processorThreads - 1),
|
||||||
, firstInstance(true)
|
, firstInstance(true)
|
||||||
, valuesLBID(0)
|
, valuesLBID(0)
|
||||||
|
, initiatedByEM_(false)
|
||||||
{
|
{
|
||||||
// promote processorThreads to next power of 2. also need to change the name to bucketCount or similar
|
// promote processorThreads to next power of 2. also need to change the name to bucketCount or similar
|
||||||
processorThreads = nextPowOf2(processorThreads);
|
processorThreads = nextPowOf2(processorThreads);
|
||||||
@ -544,6 +547,10 @@ void BatchPrimitiveProcessor::resetBPP(ByteStream& bs, const SP_UM_MUTEX& w, con
|
|||||||
bs.advance(sizeof(ISMPacketHeader) + 16);
|
bs.advance(sizeof(ISMPacketHeader) + 16);
|
||||||
bs >> dbRoot;
|
bs >> dbRoot;
|
||||||
bs >> count;
|
bs >> count;
|
||||||
|
uint8_t u8 = 0;
|
||||||
|
bs >> u8;
|
||||||
|
initiatedByEM_ = u8;
|
||||||
|
|
||||||
bs >> ridCount;
|
bs >> ridCount;
|
||||||
|
|
||||||
if (gotAbsRids)
|
if (gotAbsRids)
|
||||||
@ -1647,8 +1654,9 @@ void BatchPrimitiveProcessor::execute()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// else
|
// else
|
||||||
// cout << " no target found for OID " << projectSteps[j]->getOID() <<
|
// cout << " no target found for OID " <<
|
||||||
//endl;
|
// projectSteps[j]->getOID()
|
||||||
|
//<< endl;
|
||||||
}
|
}
|
||||||
if (fe2)
|
if (fe2)
|
||||||
{
|
{
|
||||||
@ -2134,6 +2142,17 @@ void BatchPrimitiveProcessor::serializeStrings()
|
|||||||
|
|
||||||
void BatchPrimitiveProcessor::sendResponse()
|
void BatchPrimitiveProcessor::sendResponse()
|
||||||
{
|
{
|
||||||
|
bool isLocalNodeConnection = exemgr::globServiceExeMgr->isLocalNodeSock(sock);
|
||||||
|
// Here is the fast path for local EM to PM interacction. PM puts into the
|
||||||
|
// input EM DEC queue directly.
|
||||||
|
if (initiatedByEM_ && isLocalNodeConnection)
|
||||||
|
{
|
||||||
|
joblist::DistributedEngineComm* exeMgrDecPtr = exemgr::globServiceExeMgr->getDec();
|
||||||
|
exeMgrDecPtr->addDataToOutput(serialized);
|
||||||
|
serialized.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sendThread->flowControlEnabled())
|
if (sendThread->flowControlEnabled())
|
||||||
{
|
{
|
||||||
// newConnection should be set only for the first result of a batch job
|
// newConnection should be set only for the first result of a batch job
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
#include "bppsendthread.h"
|
#include "bppsendthread.h"
|
||||||
#include "columnwidth.h"
|
#include "columnwidth.h"
|
||||||
|
|
||||||
//#define PRIMPROC_STOPWATCH
|
|
||||||
#ifdef PRIMPROC_STOPWATCH
|
#ifdef PRIMPROC_STOPWATCH
|
||||||
#include "stopwatch.h"
|
#include "stopwatch.h"
|
||||||
#endif
|
#endif
|
||||||
@ -433,6 +432,7 @@ class BatchPrimitiveProcessor
|
|||||||
uint ptMask;
|
uint ptMask;
|
||||||
bool firstInstance;
|
bool firstInstance;
|
||||||
uint64_t valuesLBID;
|
uint64_t valuesLBID;
|
||||||
|
bool initiatedByEM_;
|
||||||
|
|
||||||
static const uint64_t maxResultCount = 1048576; // 2^20
|
static const uint64_t maxResultCount = 1048576; // 2^20
|
||||||
|
|
||||||
|
@ -20,7 +20,9 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <ifaddrs.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#undef root_name
|
#undef root_name
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@ -60,6 +62,7 @@
|
|||||||
|
|
||||||
namespace exemgr
|
namespace exemgr
|
||||||
{
|
{
|
||||||
|
using SharedPtrEMSock = boost::shared_ptr<messageqcpp::IOSocket>;
|
||||||
class Opt
|
class Opt
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -168,7 +171,6 @@ namespace exemgr
|
|||||||
}
|
}
|
||||||
void initMaxMemPct(uint32_t sessionId)
|
void initMaxMemPct(uint32_t sessionId)
|
||||||
{
|
{
|
||||||
// WIP
|
|
||||||
if (sessionId < 0x80000000)
|
if (sessionId < 0x80000000)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(sessionMemMapMutex_);
|
std::lock_guard<std::mutex> lk(sessionMemMapMutex_);
|
||||||
@ -187,7 +189,6 @@ namespace exemgr
|
|||||||
uint64_t getMaxMemPct(const uint32_t sessionId)
|
uint64_t getMaxMemPct(const uint32_t sessionId)
|
||||||
{
|
{
|
||||||
uint64_t maxMemoryPct = 0;
|
uint64_t maxMemoryPct = 0;
|
||||||
// WIP
|
|
||||||
if (sessionId < 0x80000000)
|
if (sessionId < 0x80000000)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(sessionMemMapMutex_);
|
std::lock_guard<std::mutex> lk(sessionMemMapMutex_);
|
||||||
@ -290,6 +291,17 @@ namespace exemgr
|
|||||||
{
|
{
|
||||||
return *rm_;
|
return *rm_;
|
||||||
}
|
}
|
||||||
|
bool isLocalNodeSock(SharedPtrEMSock& sock) const
|
||||||
|
{
|
||||||
|
for (auto& sin : localNetIfaceSins_)
|
||||||
|
{
|
||||||
|
if (sock->isSameAddr(sin))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
void setupSignalHandlers();
|
void setupSignalHandlers();
|
||||||
int8_t setupCwd()
|
int8_t setupCwd()
|
||||||
@ -326,7 +338,27 @@ namespace exemgr
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
void getLocalNetIfacesSins()
|
||||||
|
{
|
||||||
|
string ipAddress = "Unable to get IP Address";
|
||||||
|
struct ifaddrs* netIfacesList = nullptr;
|
||||||
|
struct ifaddrs* ifaceListMembPtr = nullptr;
|
||||||
|
int success = 0;
|
||||||
|
// retrieve the current interfaces - returns 0 on success
|
||||||
|
success = getifaddrs(&netIfacesList);
|
||||||
|
if (success == 0)
|
||||||
|
{
|
||||||
|
ifaceListMembPtr = netIfacesList;
|
||||||
|
for (; ifaceListMembPtr; ifaceListMembPtr = ifaceListMembPtr->ifa_next)
|
||||||
|
{
|
||||||
|
if (ifaceListMembPtr->ifa_addr->sa_family == AF_INET)
|
||||||
|
{
|
||||||
|
localNetIfaceSins_.push_back(((struct sockaddr_in*)ifaceListMembPtr->ifa_addr)->sin_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freeifaddrs(netIfacesList);
|
||||||
|
}
|
||||||
logging::Logger msgLog_;
|
logging::Logger msgLog_;
|
||||||
SessionMemMap_t sessionMemMap_; // track memory% usage during a query
|
SessionMemMap_t sessionMemMap_; // track memory% usage during a query
|
||||||
std::mutex sessionMemMapMutex_;
|
std::mutex sessionMemMapMutex_;
|
||||||
@ -343,6 +375,7 @@ namespace exemgr
|
|||||||
joblist::ResourceManager* rm_;
|
joblist::ResourceManager* rm_;
|
||||||
// Its attributes are set in Child()
|
// Its attributes are set in Child()
|
||||||
querytele::QueryTeleServerParms teleServerParms_;
|
querytele::QueryTeleServerParms teleServerParms_;
|
||||||
|
std::vector<struct in_addr> localNetIfaceSins_;
|
||||||
};
|
};
|
||||||
extern ServiceExeMgr* globServiceExeMgr;
|
extern ServiceExeMgr* globServiceExeMgr;
|
||||||
}
|
}
|
@ -1075,6 +1075,10 @@ bool InetStreamSocket::isSameAddr(const Socket* rhs) const
|
|||||||
|
|
||||||
return (fSa.sin_addr.s_addr == issp->fSa.sin_addr.s_addr);
|
return (fSa.sin_addr.s_addr == issp->fSa.sin_addr.s_addr);
|
||||||
}
|
}
|
||||||
|
bool InetStreamSocket::isSameAddr(const struct in_addr& ipv4Addr) const
|
||||||
|
{
|
||||||
|
return (fSa.sin_addr.s_addr == ipv4Addr.s_addr);
|
||||||
|
}
|
||||||
|
|
||||||
/*static*/
|
/*static*/
|
||||||
int InetStreamSocket::ping(const std::string& ipaddr, const struct timespec* timeout)
|
int InetStreamSocket::ping(const std::string& ipaddr, const struct timespec* timeout)
|
||||||
|
@ -201,6 +201,7 @@ class InetStreamSocket : public Socket
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
virtual bool isSameAddr(const Socket* rhs) const;
|
virtual bool isSameAddr(const Socket* rhs) const;
|
||||||
|
virtual bool isSameAddr(const struct in_addr& ipv4Addr) const;
|
||||||
|
|
||||||
/** ping an ip address
|
/** ping an ip address
|
||||||
*
|
*
|
||||||
|
@ -179,6 +179,11 @@ class IOSocket
|
|||||||
{
|
{
|
||||||
return fSocket->isSameAddr(rhs->fSocket);
|
return fSocket->isSameAddr(rhs->fSocket);
|
||||||
}
|
}
|
||||||
|
virtual bool isSameAddr(const struct in_addr& ipv4Addr) const
|
||||||
|
{
|
||||||
|
return fSocket->isSameAddr(ipv4Addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** connect() forwarder for inherited classes
|
/** connect() forwarder for inherited classes
|
||||||
*
|
*
|
||||||
|
@ -174,6 +174,7 @@ class Socket
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
virtual bool isSameAddr(const Socket* rhs) const = 0;
|
virtual bool isSameAddr(const Socket* rhs) const = 0;
|
||||||
|
virtual bool isSameAddr(const struct in_addr& ipv4Addr) const = 0;
|
||||||
|
|
||||||
virtual bool isConnected() const = 0;
|
virtual bool isConnected() const = 0;
|
||||||
virtual bool hasData() const = 0;
|
virtual bool hasData() const = 0;
|
||||||
|
Reference in New Issue
Block a user