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
MCOL-3577: Add functionality to sync S3 storage for suspendDatabaseWrites.
This commit is contained in:
@ -2712,6 +2712,8 @@ void processMSG(messageqcpp::IOSocket* cfIos)
|
|||||||
ByteStream::byte ackResponse = API_FAILURE;
|
ByteStream::byte ackResponse = API_FAILURE;
|
||||||
log.writeLog(__LINE__, "MSG RECEIVED: suspend database writes");
|
log.writeLog(__LINE__, "MSG RECEIVED: suspend database writes");
|
||||||
|
|
||||||
|
string storageType = Config::makeConfig()->getConfig("Installation", "DBRootStorageType");
|
||||||
|
|
||||||
// GRACEFUL_WAIT means that we are Suspending writes, but waiting for all
|
// GRACEFUL_WAIT means that we are Suspending writes, but waiting for all
|
||||||
// transactions to finish or rollback as commanded. This is only set if there
|
// transactions to finish or rollback as commanded. This is only set if there
|
||||||
// are, in fact, transactions active (or cpimport).
|
// are, in fact, transactions active (or cpimport).
|
||||||
@ -2785,6 +2787,16 @@ void processMSG(messageqcpp::IOSocket* cfIos)
|
|||||||
dbrm.setSystemSuspended(false);
|
dbrm.setSystemSuspended(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (storageType == "storagemanager")
|
||||||
|
{
|
||||||
|
string DBRMroot;
|
||||||
|
oam.getSystemConfig("DBRMRoot", DBRMroot);
|
||||||
|
|
||||||
|
string currentFileName = DBRMroot + "_current";
|
||||||
|
IDBFileSystem &fs = IDBPolicy::getFs(currentFileName.c_str());
|
||||||
|
fs.filesystemSync();
|
||||||
|
}
|
||||||
|
|
||||||
ackMsg.reset();
|
ackMsg.reset();
|
||||||
ackMsg << (ByteStream::byte) oam::ACK;
|
ackMsg << (ByteStream::byte) oam::ACK;
|
||||||
ackMsg << actionType;
|
ackMsg << actionType;
|
||||||
|
@ -34,6 +34,7 @@ set(storagemanager_SRCS
|
|||||||
src/Utilities.cpp
|
src/Utilities.cpp
|
||||||
src/Ownership.cpp
|
src/Ownership.cpp
|
||||||
src/PrefixCache.cpp
|
src/PrefixCache.cpp
|
||||||
|
src/SyncTask.cpp
|
||||||
../utils/common/crashtrace.cpp
|
../utils/common/crashtrace.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,7 +82,8 @@ enum Opcodes {
|
|||||||
TRUNCATE,
|
TRUNCATE,
|
||||||
LIST_DIRECTORY,
|
LIST_DIRECTORY,
|
||||||
PING,
|
PING,
|
||||||
COPY
|
COPY,
|
||||||
|
SYNC
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "TruncateTask.h"
|
#include "TruncateTask.h"
|
||||||
#include "UnlinkTask.h"
|
#include "UnlinkTask.h"
|
||||||
#include "WriteTask.h"
|
#include "WriteTask.h"
|
||||||
|
#include "SyncTask.h"
|
||||||
#include "SessionManager.h"
|
#include "SessionManager.h"
|
||||||
#include "SMLogging.h"
|
#include "SMLogging.h"
|
||||||
|
|
||||||
@ -109,6 +110,9 @@ void ProcessTask::operator()()
|
|||||||
case PING:
|
case PING:
|
||||||
task.reset(new PingTask(sock, length));
|
task.reset(new PingTask(sock, length));
|
||||||
break;
|
break;
|
||||||
|
case SYNC:
|
||||||
|
task.reset(new SyncTask(sock, length));
|
||||||
|
break;
|
||||||
case COPY:
|
case COPY:
|
||||||
task.reset(new CopyTask(sock, length));
|
task.reset(new CopyTask(sock, length));
|
||||||
break;
|
break;
|
||||||
|
62
storage-manager/src/SyncTask.cpp
Normal file
62
storage-manager/src/SyncTask.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* Copyright (C) 2019 MariaDB Corporation
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
|
||||||
|
#include "SyncTask.h"
|
||||||
|
#include "Synchronizer.h"
|
||||||
|
#include "messageFormat.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
namespace storagemanager
|
||||||
|
{
|
||||||
|
|
||||||
|
SyncTask::SyncTask(int sock, uint len) : PosixTask(sock, len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncTask::~SyncTask()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncTask::run()
|
||||||
|
{
|
||||||
|
// force flush synchronizer
|
||||||
|
uint8_t buf;
|
||||||
|
|
||||||
|
if (getLength() > 1)
|
||||||
|
{
|
||||||
|
handleError("SyncTask", E2BIG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// consume the msg
|
||||||
|
bool success = read(&buf, getLength());
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
handleError("SyncTask", errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Synchronizer::get()->syncNow();
|
||||||
|
|
||||||
|
// send generic success response
|
||||||
|
sm_response ret;
|
||||||
|
ret.returnCode = 0;
|
||||||
|
success = write(ret, 0);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
storage-manager/src/SyncTask.h
Normal file
41
storage-manager/src/SyncTask.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* Copyright (C) 2019 MariaDB Corporation
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SYNCTASK_H_
|
||||||
|
#define SYNCTASK_H_
|
||||||
|
|
||||||
|
#include "PosixTask.h"
|
||||||
|
|
||||||
|
namespace storagemanager
|
||||||
|
{
|
||||||
|
|
||||||
|
class SyncTask : public PosixTask
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SyncTask(int sock, uint length);
|
||||||
|
virtual ~SyncTask();
|
||||||
|
|
||||||
|
bool run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SyncTask();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
@ -185,6 +185,10 @@ void Synchronizer::deletedObjects(const bf::path &prefix, const vector<string> &
|
|||||||
void Synchronizer::flushObject(const bf::path &prefix, const string &_key)
|
void Synchronizer::flushObject(const bf::path &prefix, const string &_key)
|
||||||
{
|
{
|
||||||
string key = (prefix/_key).string();
|
string key = (prefix/_key).string();
|
||||||
|
|
||||||
|
while (blockNewJobs)
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||||
|
|
||||||
boost::unique_lock<boost::mutex> s(mutex);
|
boost::unique_lock<boost::mutex> s(mutex);
|
||||||
|
|
||||||
// if there is something to do on key, it should be either in pendingOps or opsInProgress
|
// if there is something to do on key, it should be either in pendingOps or opsInProgress
|
||||||
@ -307,13 +311,45 @@ void Synchronizer::syncNow(const bf::path &prefix)
|
|||||||
if (job.first.find(prefix.string()) == 0)
|
if (job.first.find(prefix.string()) == 0)
|
||||||
makeJob(job.first);
|
makeJob(job.first);
|
||||||
uncommittedJournalSize[prefix] = 0;
|
uncommittedJournalSize[prefix] = 0;
|
||||||
|
lock.unlock();
|
||||||
threadPool.reset(new ThreadPool());
|
threadPool.reset(new ThreadPool());
|
||||||
threadPool->setMaxThreads(maxUploads);
|
threadPool->setMaxThreads(maxUploads);
|
||||||
|
lock.lock();
|
||||||
blockNewJobs = false;
|
blockNewJobs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Synchronizer::syncNow()
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(mutex);
|
||||||
|
|
||||||
|
// this is pretty hacky. when time permits, implement something better.
|
||||||
|
//
|
||||||
|
// Issue all of the pendingOps for the given prefix
|
||||||
|
// recreate the threadpool (dtor returns once all jobs have finished)
|
||||||
|
// resume normal operation
|
||||||
|
|
||||||
|
blockNewJobs = true;
|
||||||
|
while (pendingOps.size() != 0)
|
||||||
|
{
|
||||||
|
for (auto &job : pendingOps)
|
||||||
|
makeJob(job.first);
|
||||||
|
for (auto it = uncommittedJournalSize.begin(); it != uncommittedJournalSize.end(); ++it)
|
||||||
|
it->second = 0;
|
||||||
|
lock.unlock();
|
||||||
|
while (opsInProgress.size() > 0)
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||||
|
if (pendingOps.size() != 0)
|
||||||
|
logger->log(LOG_DEBUG,"Synchronizer syncNow pendingOps not empty.");
|
||||||
|
lock.lock();
|
||||||
|
}
|
||||||
|
blockNewJobs = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Synchronizer::forceFlush()
|
void Synchronizer::forceFlush()
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(mutex);
|
boost::unique_lock<boost::mutex> lock(mutex);
|
||||||
|
|
||||||
syncThread.interrupt();
|
syncThread.interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ class Synchronizer : public boost::noncopyable , public ConfigListener
|
|||||||
void deletedObjects(const boost::filesystem::path &firstDir, const std::vector<std::string> &keys);
|
void deletedObjects(const boost::filesystem::path &firstDir, const std::vector<std::string> &keys);
|
||||||
void flushObject(const boost::filesystem::path &firstDir, const std::string &key);
|
void flushObject(const boost::filesystem::path &firstDir, const std::string &key);
|
||||||
void forceFlush(); // ideally, make a version of this that takes a firstDir parameter
|
void forceFlush(); // ideally, make a version of this that takes a firstDir parameter
|
||||||
|
void syncNow(); // synchronous version of force for SyncTask
|
||||||
|
|
||||||
void newPrefix(const boost::filesystem::path &p);
|
void newPrefix(const boost::filesystem::path &p);
|
||||||
void dropPrefix(const boost::filesystem::path &p);
|
void dropPrefix(const boost::filesystem::path &p);
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ class Synchronizer : public boost::noncopyable , public ConfigListener
|
|||||||
bool blockNewJobs;
|
bool blockNewJobs;
|
||||||
|
|
||||||
void syncNow(const boost::filesystem::path &prefix); // a synchronous version of forceFlush()
|
void syncNow(const boost::filesystem::path &prefix); // a synchronous version of forceFlush()
|
||||||
|
|
||||||
// some KPIs
|
// some KPIs
|
||||||
size_t numBytesRead, numBytesWritten, numBytesUploaded, numBytesDownloaded,
|
size_t numBytesRead, numBytesWritten, numBytesUploaded, numBytesDownloaded,
|
||||||
flushesTriggeredBySize, flushesTriggeredByTimer, journalsMerged, objectsSyncedWithNoJournal,
|
flushesTriggeredBySize, flushesTriggeredByTimer, journalsMerged, objectsSyncedWithNoJournal,
|
||||||
|
@ -247,6 +247,20 @@ int SMComm::ping()
|
|||||||
common_exit(command, response, err);
|
common_exit(command, response, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SMComm::sync()
|
||||||
|
{
|
||||||
|
ByteStream *command = buffers.getByteStream();
|
||||||
|
ByteStream *response = buffers.getByteStream();
|
||||||
|
ssize_t err;
|
||||||
|
|
||||||
|
*command << (uint8_t) storagemanager::SYNC;
|
||||||
|
err = sockets.send_recv(*command, response);
|
||||||
|
if (err)
|
||||||
|
common_exit(command, response, err);
|
||||||
|
check_for_error(command, response, err);
|
||||||
|
common_exit(command, response, err);
|
||||||
|
}
|
||||||
|
|
||||||
int SMComm::copyFile(const string &file1, const string &file2)
|
int SMComm::copyFile(const string &file1, const string &file2)
|
||||||
{
|
{
|
||||||
ByteStream *command = buffers.getByteStream();
|
ByteStream *command = buffers.getByteStream();
|
||||||
|
@ -59,6 +59,8 @@ class SMComm : public boost::noncopyable
|
|||||||
// the specified S3 bucket. Need to define specific error codes.
|
// the specified S3 bucket. Need to define specific error codes.
|
||||||
int ping();
|
int ping();
|
||||||
|
|
||||||
|
int sync();
|
||||||
|
|
||||||
int copyFile(const std::string &file1, const std::string &file2);
|
int copyFile(const std::string &file1, const std::string &file2);
|
||||||
|
|
||||||
virtual ~SMComm();
|
virtual ~SMComm();
|
||||||
|
@ -110,4 +110,9 @@ bool SMFileSystem::filesystemIsUp() const
|
|||||||
return (comm->ping() == 0);
|
return (comm->ping() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SMFileSystem::filesystemSync() const
|
||||||
|
{
|
||||||
|
SMComm *comm = SMComm::get();
|
||||||
|
return (comm->sync() == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ class SMFileSystem : public IDBFileSystem, boost::noncopyable
|
|||||||
bool isDir(const char* pathname) const;
|
bool isDir(const char* pathname) const;
|
||||||
int copyFile(const char* srcPath, const char* destPath) const;
|
int copyFile(const char* srcPath, const char* destPath) const;
|
||||||
bool filesystemIsUp() const;
|
bool filesystemIsUp() const;
|
||||||
|
bool filesystemSync() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,11 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool filesystemSync() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
IDBFileSystem( Types type );
|
IDBFileSystem( Types type );
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user