1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
Roman Nozdrin 4fe9cd64a3
Revert "No boost condition (#2822)" (#2828)
This reverts commit f916e64927cd81569327014f20c4cc0b8aca40ff.
2023-04-22 15:49:50 +03:00

357 lines
8.0 KiB
C++

/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: cacheutils.cpp 4051 2013-08-09 22:38:47Z wweeks $
#include <unistd.h>
#include "cacheutils.h"
#include <string>
#include <stdint.h>
#include <sstream>
#include <limits>
//#define NDEBUG
#include <cassert>
using namespace std;
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/thread.hpp>
using namespace boost;
#include "configcpp.h"
using namespace config;
#include "bytestream.h"
#include "messagequeue.h"
using namespace messageqcpp;
#include "primitivemsg.h"
#include "brmtypes.h"
using namespace BRM;
#include "atomicops.h"
namespace
{
// Only one of the cacheutils fcns can run at a time
boost::mutex CacheOpsMutex;
// This global is updated only w/ atomic ops
volatile uint32_t MultiReturnCode;
int32_t extractRespCode(const ByteStream& bs)
{
if (bs.length() < (sizeof(ISMPacketHeader) + sizeof(int32_t)))
return 1;
const uint8_t* bytePtr = bs.buf();
const ISMPacketHeader* hdrp = reinterpret_cast<const ISMPacketHeader*>(bytePtr);
if (hdrp->Command != CACHE_OP_RESULTS)
return 1;
const int32_t* resp = reinterpret_cast<const int32_t*>(bytePtr + sizeof(ISMPacketHeader));
return *resp;
}
class CacheOpThread
{
public:
CacheOpThread(const string& svr, const ByteStream& outBs) : fServerName(svr), fOutBs(outBs)
{
}
~CacheOpThread()
{
}
void operator()()
{
struct timespec ts = {10, 0};
int32_t rc = 0;
scoped_ptr<MessageQueueClient> cl(new MessageQueueClient(fServerName));
try
{
cl->write(fOutBs);
rc = extractRespCode(cl->read(&ts));
}
catch (...)
{
rc = 1;
}
if (rc != 0)
atomicops::atomicCAS<uint32_t>(&MultiReturnCode, 0, 1);
}
private:
// CacheOpThread(const CacheOpThread& rhs);
// CacheOpThread& operator=(const CacheOpThread& rhs);
string fServerName;
ByteStream fOutBs;
};
int sendToAll(const ByteStream& outBs)
{
// Not thread-safe: external synchronization is needed!
// added code here to flush any running primprocs that may be active
// TODO: we really only need to flush each unique PrimProc, but we can't tell from the
// config file which those are, so use the same logic as joblist::DistributedEngineComm
Config* cf = Config::makeConfig();
const string section = "PrimitiveServers";
int cnt = static_cast<int>(Config::fromText(cf->getConfig(section, "Count")));
if (cnt <= 0)
cnt = 1;
thread_group tg;
int rc = 0;
MultiReturnCode = 0;
for (int i = 0; i < cnt; i++)
{
ostringstream oss;
oss << "PMS" << (i + 1);
tg.create_thread(CacheOpThread(oss.str(), outBs));
}
tg.join_all();
if (MultiReturnCode != 0)
rc = -1;
return rc;
}
} // namespace
namespace cacheutils
{
/**
*
*/
int flushPrimProcCache()
{
boost::mutex::scoped_lock lk(CacheOpsMutex);
try
{
const int msgsize = sizeof(ISMPacketHeader);
uint8_t msgbuf[msgsize];
memset(msgbuf, 0, sizeof(ISMPacketHeader));
ISMPacketHeader* hdrp = reinterpret_cast<ISMPacketHeader*>(&msgbuf[0]);
hdrp->Command = CACHE_FLUSH;
ByteStream bs(msgbuf, msgsize);
int rc = sendToAll(bs);
return rc;
}
catch (...)
{
}
return -1;
}
/**
*
*/
int flushPrimProcBlocks(const BRM::BlockList_t& list)
{
if (list.empty())
return 0;
boost::mutex::scoped_lock lk(CacheOpsMutex);
#if defined(__LP64__) || defined(_WIN64)
if (list.size() > numeric_limits<uint32_t>::max())
return -1;
#endif
try
{
const size_t msgsize = sizeof(ISMPacketHeader) + sizeof(uint32_t) + sizeof(LbidAtVer) * list.size();
scoped_array<uint8_t> msgbuf(new uint8_t[msgsize]);
memset(msgbuf.get(), 0, sizeof(ISMPacketHeader));
ISMPacketHeader* hdrp = reinterpret_cast<ISMPacketHeader*>(msgbuf.get());
hdrp->Command = CACHE_CLEAN_VSS;
uint32_t* cntp = reinterpret_cast<uint32_t*>(msgbuf.get() + sizeof(ISMPacketHeader));
*cntp = static_cast<uint32_t>(list.size());
LbidAtVer* itemp =
reinterpret_cast<LbidAtVer*>(msgbuf.get() + sizeof(ISMPacketHeader) + sizeof(uint32_t));
BlockList_t::const_iterator iter = list.begin();
BlockList_t::const_iterator end = list.end();
while (iter != end)
{
itemp->LBID = static_cast<uint64_t>(iter->first);
itemp->Ver = static_cast<uint32_t>(iter->second);
++itemp;
++iter;
}
ByteStream bs(msgbuf.get(), msgsize);
int rc = sendToAll(bs);
return rc;
}
catch (...)
{
}
return -1;
}
int flushPrimProcAllverBlocks(const vector<LBID_t>& list)
{
if (list.empty())
return 0;
ByteStream bs(sizeof(ISMPacketHeader) + sizeof(uint32_t) + (sizeof(LBID_t) * list.size()));
ISMPacketHeader* hdr;
int rc;
hdr = (ISMPacketHeader*)bs.getInputPtr();
hdr->Command = FLUSH_ALL_VERSION;
bs.advanceInputPtr(sizeof(ISMPacketHeader));
bs << (uint32_t)list.size();
bs.append((uint8_t*)&list[0], sizeof(LBID_t) * list.size());
try
{
boost::mutex::scoped_lock lk(CacheOpsMutex);
rc = sendToAll(bs);
return rc;
}
catch (...)
{
}
return -1;
}
int flushOIDsFromCache(const vector<BRM::OID_t>& oids)
{
/* Message format:
* ISMPacketHeader
* uint32_t - OID count
* uint32_t * - OID array
*/
boost::mutex::scoped_lock lk(CacheOpsMutex, boost::defer_lock_t());
ByteStream bs;
ISMPacketHeader ism;
uint32_t i;
void* ismp = static_cast<void*>(&ism);
memset(ismp, 0, sizeof(ISMPacketHeader));
ism.Command = CACHE_FLUSH_BY_OID;
bs.load((uint8_t*)&ism, sizeof(ISMPacketHeader));
bs << (uint32_t)oids.size();
for (i = 0; i < oids.size(); i++)
bs << (uint32_t)oids[i];
lk.lock();
return sendToAll(bs);
}
int flushPartition(const std::vector<BRM::OID_t>& oids, set<BRM::LogicalPartition>& partitionNums)
{
/* Message format:
* ISMPacketHeader
* uint32_t - partition count
* LogicalPartition * - partitionNum
* uint32_t - OID count
* uint32_t * - OID array
*/
boost::mutex::scoped_lock lk(CacheOpsMutex, boost::defer_lock_t());
ByteStream bs;
ISMPacketHeader ism;
void* ismp = static_cast<void*>(&ism);
memset(ismp, 0, sizeof(ISMPacketHeader));
ism.Command = CACHE_FLUSH_PARTITION;
bs.load((uint8_t*)&ism, sizeof(ISMPacketHeader));
serializeSet<BRM::LogicalPartition>(bs, partitionNums);
serializeInlineVector<BRM::OID_t>(bs, oids);
lk.lock();
return sendToAll(bs);
}
int dropPrimProcFdCache()
{
const int msgsize = sizeof(ISMPacketHeader);
uint8_t msgbuf[msgsize];
memset(msgbuf, 0, sizeof(ISMPacketHeader));
ISMPacketHeader* hdrp = reinterpret_cast<ISMPacketHeader*>(&msgbuf[0]);
hdrp->Command = CACHE_DROP_FDS;
ByteStream bs(msgbuf, msgsize);
try
{
boost::mutex::scoped_lock lk(CacheOpsMutex);
int rc = sendToAll(bs);
return rc;
}
catch (...)
{
}
return -1;
}
int purgePrimProcFdCache(const std::vector<BRM::FileInfo> files, const int pmId)
{
const int msgsize = sizeof(ISMPacketHeader);
uint8_t msgbuf[msgsize];
memset(msgbuf, 0, sizeof(ISMPacketHeader));
ISMPacketHeader* hdrp = reinterpret_cast<ISMPacketHeader*>(&msgbuf[0]);
hdrp->Command = CACHE_PURGE_FDS;
ByteStream bs(msgbuf, msgsize);
serializeInlineVector<FileInfo>(bs, files);
int32_t rc = 0;
try
{
struct timespec ts = {10, 0};
ostringstream oss;
oss << "PMS" << pmId;
scoped_ptr<MessageQueueClient> cl(new MessageQueueClient(oss.str()));
cl->write(bs);
rc = extractRespCode(cl->read(&ts));
}
catch (...)
{
rc = -1;
}
return rc;
}
} // namespace cacheutils