You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
Checkpointing, not ready to build yet.
This commit is contained in:
@ -0,0 +1,7 @@
|
|||||||
|
// copy licensing stuff here
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "SMComm.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ namespace idbdatafile {
|
|||||||
class SMComm : public boost::noncopyable
|
class SMComm : public boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SMComm *get();
|
// This is a singleton. Get it with get()
|
||||||
|
static SMComm *get();
|
||||||
|
|
||||||
/* Open currently returns a stat struct so SMDataFile can set its initial position, otherwise
|
/* Open currently returns a stat struct so SMDataFile can set its initial position, otherwise
|
||||||
behaves how you'd think. */
|
behaves how you'd think. */
|
||||||
@ -42,13 +43,8 @@ class SMComm : public boost::noncopyable
|
|||||||
SMComm();
|
SMComm();
|
||||||
|
|
||||||
SocketPool sockets;
|
SocketPool sockets;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
185
utils/cloudio/SocketPool.cpp
Normal file
185
utils/cloudio/SocketPool.cpp
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
// copy licensing stuff here
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "SocketPool.h"
|
||||||
|
#include "configcpp.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "storage-manager/include/messageFormat.h"
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
void log(logging::LOG_TYPE whichLogFile, const string& msg)
|
||||||
|
{
|
||||||
|
logging::Logger logger(12); //12 = configcpp
|
||||||
|
logger.logMessage(whichLogFile, msg, logging::LoggingID(12));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace idbdatafile
|
||||||
|
{
|
||||||
|
|
||||||
|
SocketPool::SocketPool()
|
||||||
|
{
|
||||||
|
config::Config *config = config::Config::makeConfig(); // the most 'config' ever put into a single line of code?
|
||||||
|
string stmp;
|
||||||
|
int64_t itmp = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stmp = config->getConfig("StorageManager", "MaxSockets");
|
||||||
|
itmp = strtol(stmp.c_str(), NULL, 10);
|
||||||
|
if (itmp > 500 || itmp < 1) {
|
||||||
|
string errmsg = "SocketPool(): Got a bad value '" + stmp + "' for StorageManager/MaxSockets.";
|
||||||
|
log(logging::CRITICAL, errmsg);
|
||||||
|
throw runtime_error(errmsg);
|
||||||
|
maxSockets = itmp;
|
||||||
|
}
|
||||||
|
catch (exception &e)
|
||||||
|
{
|
||||||
|
ostringstream os;
|
||||||
|
os << "SocketPool(): Using default of " << defaultSockets << ".";
|
||||||
|
log(logging::CRITICAL, os.str());
|
||||||
|
maxSockets = defaultSockets;
|
||||||
|
}
|
||||||
|
clientSocket = ::socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (clientSocket < 0) {
|
||||||
|
char buf[80], *ptr;
|
||||||
|
ptr = strerror_r(errno, buf, 80);
|
||||||
|
throw runtime_error("SocketPool(): Failed to get clientSocket, got " + string(ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketPool::~SocketPool()
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock(mutex);
|
||||||
|
|
||||||
|
for (int i = 0; i < allSockets.size(); i++)
|
||||||
|
::close(allSockets[i]);
|
||||||
|
::close(clientSocket)
|
||||||
|
}
|
||||||
|
|
||||||
|
int SocketPool::send_recv(const messageqcpp::ByteStream &in, messageqcpp::ByteStream *out)
|
||||||
|
{
|
||||||
|
uint count = 0;
|
||||||
|
uint length = in.length();
|
||||||
|
int sock = getSocket();
|
||||||
|
uint8_t inbuf* = in.buf();
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
::write(sock, &storagemanager::SM_MSG_START, sizeof(storagemanager::SM_MSG_START));
|
||||||
|
::write(sock, &length, sizeof(length));
|
||||||
|
while (count < length)
|
||||||
|
{
|
||||||
|
err = ::write(sock, &inbuf[count], length-count);
|
||||||
|
if (err < 0)
|
||||||
|
{
|
||||||
|
returnSocket(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
count += err;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->restart();
|
||||||
|
uint8_t *outbuf;
|
||||||
|
uint8_t window[8192];
|
||||||
|
bool foundheader = false;
|
||||||
|
length = 0;
|
||||||
|
uint remainingBytes = 0;
|
||||||
|
int i;
|
||||||
|
while (!foundheader)
|
||||||
|
{
|
||||||
|
// here remainingBytes means the # of bytes from the previous message
|
||||||
|
err = ::read(sock, &window[remainingBytes], 8192 - remainingBytes);
|
||||||
|
if (err < 0)
|
||||||
|
{
|
||||||
|
returnSocket(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint endOfData = remainingBytes + err; // for clarity
|
||||||
|
|
||||||
|
// scan for the 8-byte header. If it is fragmented, move the fragment to the front of the buffer
|
||||||
|
// for the next iteration to handle.
|
||||||
|
for (i = 0; i <= endOfData - 8 && !foundHeader; i++)
|
||||||
|
{
|
||||||
|
if (*((uint *) &window[i]) == storagemanager::SM_MSG_START)
|
||||||
|
{
|
||||||
|
length = *((uint *) &window[i+4]);
|
||||||
|
foundHeader = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundHeader)
|
||||||
|
{
|
||||||
|
remainingBytes = endOfData - i;
|
||||||
|
if (i != 0)
|
||||||
|
memmove(window, &window[i], remainingBytes);
|
||||||
|
else
|
||||||
|
continue; // if i == 0, then the read was too short to see the whole header, do another read().
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out->needAtLeast(length);
|
||||||
|
outbuf = out->buf();
|
||||||
|
memcpy(outbuf, &window[i+8], endOfData - (i+8));
|
||||||
|
remainingBytes = length - (endOfData - (i+8)); // remainingBytes is now the # of bytes left to read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the rest of the payload
|
||||||
|
while (remainingBytes > 0)
|
||||||
|
{
|
||||||
|
err = ::read(sock, &outbuf[length - remainingBytes], remainingBytes);
|
||||||
|
if (err < 0)
|
||||||
|
{
|
||||||
|
returnSocket(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
remainingBytes -= err;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnSocket(sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SocketPool::getSocket()
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (freeSockets.size() == 0 && allSockets.size() < maxSockets)
|
||||||
|
{
|
||||||
|
// make a new connection
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strcpy(&addr.sun_path[1], "storagemanager"); // abstract socket; this is intentional
|
||||||
|
ret = ::connect(tmp, &addr, sizeof(addr));
|
||||||
|
if (ret >= 0)
|
||||||
|
allSockets.push_back(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for a socket to become free
|
||||||
|
while (freeSockets.size() == 0)
|
||||||
|
socketAvailable.wait(lock);
|
||||||
|
|
||||||
|
ret = freeSockets.front();
|
||||||
|
freeSockets.pop_front();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketPool::returnSocket(int sock)
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
|
freeSockets.push_back(sock);
|
||||||
|
socketAvailable.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
42
utils/cloudio/SocketPool.h
Normal file
42
utils/cloudio/SocketPool.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// copy licensing stuff here
|
||||||
|
|
||||||
|
#ifndef _SOCKETPOOL_H_
|
||||||
|
#define _SOCKETPOOL_H_
|
||||||
|
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
|
#include "bytestream.h"
|
||||||
|
|
||||||
|
namespace idbdatafile
|
||||||
|
{
|
||||||
|
|
||||||
|
class SocketPool : public boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SocketPool();
|
||||||
|
|
||||||
|
// the dtor will immediately close all sockets
|
||||||
|
virtual ~SocketPool();
|
||||||
|
|
||||||
|
// 0 = success, -1 = failure. Should this throw instead?
|
||||||
|
int send_recv(const ByteStream &to_send, ByteStream *to_recv);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int getSocket();
|
||||||
|
void returnSocket();
|
||||||
|
|
||||||
|
std::vector<int> allSockets;
|
||||||
|
std::deque<int> freeSockets;
|
||||||
|
boost::mutex mutex;
|
||||||
|
boost::condition socketAvailable;
|
||||||
|
int clientSocket;
|
||||||
|
int maxSockets;
|
||||||
|
static const int defaultSockets = 20;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -3,15 +3,42 @@
|
|||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
|
namespace idbdatafile
|
||||||
|
{
|
||||||
|
|
||||||
class NotImplementedYet : public std::exception
|
class NotImplementedYet : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NotImplementedYet(const std::string &s);
|
NotImplementedYet(const std::string &s);
|
||||||
};
|
};
|
||||||
|
|
||||||
NotImplementedYes::NotImplementedYet(const std::string &s) :
|
class FailedToSend : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FailedToSend(const std::string &s);
|
||||||
|
};
|
||||||
|
|
||||||
|
class FailedToRecv : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FailedToRecv(const std::string &s);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
NotImplementedYet::NotImplementedYet(const std::string &s) :
|
||||||
std::exception(s + "() isn't implemented yet.")
|
std::exception(s + "() isn't implemented yet.")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FailedToSend::FailedToSend(const std::string &s) :
|
||||||
|
std::runtime_error(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FailedToRecv::FailedToRecv(const std::string &s) :
|
||||||
|
std::runtime_error(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Submodule utils/cloudio/storage-manager updated: 20b0d3b88b...50daf50b82
Reference in New Issue
Block a user