mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Create periodic backup copies of controller.db in network controller from the main process itself to facilitate easier and safer backups of controller.db.
This commit is contained in:
parent
4b655ab22c
commit
7903f24a8f
3 changed files with 62 additions and 1 deletions
|
@ -71,6 +71,9 @@
|
||||||
// than this (ms).
|
// than this (ms).
|
||||||
#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000
|
#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000
|
||||||
|
|
||||||
|
// Delay between backups in milliseconds
|
||||||
|
#define ZT_NETCONF_BACKUP_PERIOD 60000
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -122,6 +125,7 @@ struct NetworkRecord {
|
||||||
|
|
||||||
SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,const char *circuitTestPath) :
|
SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,const char *circuitTestPath) :
|
||||||
_node(node),
|
_node(node),
|
||||||
|
_backupThreadRun(true),
|
||||||
_dbPath(dbPath),
|
_dbPath(dbPath),
|
||||||
_circuitTestPath(circuitTestPath),
|
_circuitTestPath(circuitTestPath),
|
||||||
_db((sqlite3 *)0)
|
_db((sqlite3 *)0)
|
||||||
|
@ -247,10 +251,15 @@ SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,c
|
||||||
throw std::runtime_error("SqliteNetworkController unable to read instanceId (it's NULL)");
|
throw std::runtime_error("SqliteNetworkController unable to read instanceId (it's NULL)");
|
||||||
_instanceId = iid;
|
_instanceId = iid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_backupThread = Thread::start(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SqliteNetworkController::~SqliteNetworkController()
|
SqliteNetworkController::~SqliteNetworkController()
|
||||||
{
|
{
|
||||||
|
_backupThreadRun = false;
|
||||||
|
Thread::join(_backupThread);
|
||||||
|
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
if (_db) {
|
if (_db) {
|
||||||
sqlite3_finalize(_sGetNetworkById);
|
sqlite3_finalize(_sGetNetworkById);
|
||||||
|
@ -991,6 +1000,52 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
|
||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SqliteNetworkController::threadMain()
|
||||||
|
throw()
|
||||||
|
{
|
||||||
|
uint64_t lastBackupTime = 0;
|
||||||
|
while (_backupThreadRun) {
|
||||||
|
if ((OSUtils::now() - lastBackupTime) >= ZT_NETCONF_BACKUP_PERIOD) {
|
||||||
|
lastBackupTime = OSUtils::now();
|
||||||
|
|
||||||
|
char backupPath[4096],backupPath2[4096];
|
||||||
|
Utils::snprintf(backupPath,sizeof(backupPath),"%s.backupInProgress",_dbPath.c_str());
|
||||||
|
Utils::snprintf(backupPath2,sizeof(backupPath),"%s.backup",_dbPath.c_str());
|
||||||
|
OSUtils::rm(backupPath); // delete any unfinished backups
|
||||||
|
|
||||||
|
sqlite3 *bakdb = (sqlite3 *)0;
|
||||||
|
sqlite3_backup *bak = (sqlite3_backup *)0;
|
||||||
|
if (sqlite3_open_v2(backupPath,&bakdb,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,(const char *)0) != SQLITE_OK) {
|
||||||
|
fprintf(stderr,"SqliteNetworkController: CRITICAL: backup failed on sqlite3_open_v2()"ZT_EOL_S);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bak = sqlite3_backup_init(bakdb,"main",_db,"main");
|
||||||
|
if (!bak) {
|
||||||
|
sqlite3_close(bakdb);
|
||||||
|
OSUtils::rm(backupPath); // delete any unfinished backups
|
||||||
|
fprintf(stderr,"SqliteNetworkController: CRITICAL: backup failed on sqlite3_backup_init()"ZT_EOL_S);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
for(;;) {
|
||||||
|
rc = sqlite3_backup_step(bak,1);
|
||||||
|
if ((rc == SQLITE_OK)||(rc == SQLITE_LOCKED)||(rc == SQLITE_BUSY))
|
||||||
|
Thread::sleep(100);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_backup_finish(bak);
|
||||||
|
sqlite3_close(bakdb);
|
||||||
|
|
||||||
|
OSUtils::rm(backupPath2);
|
||||||
|
::rename(backupPath,backupPath2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread::sleep(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int SqliteNetworkController::_doCPGet(
|
unsigned int SqliteNetworkController::_doCPGet(
|
||||||
const std::vector<std::string> &path,
|
const std::vector<std::string> &path,
|
||||||
const std::map<std::string,std::string> &urlArgs,
|
const std::map<std::string,std::string> &urlArgs,
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "../node/Constants.hpp"
|
#include "../node/Constants.hpp"
|
||||||
#include "../node/NetworkController.hpp"
|
#include "../node/NetworkController.hpp"
|
||||||
#include "../node/Mutex.hpp"
|
#include "../node/Mutex.hpp"
|
||||||
|
#include "../osdep/Thread.hpp"
|
||||||
|
|
||||||
// Number of in-memory last log entries to maintain per user
|
// Number of in-memory last log entries to maintain per user
|
||||||
#define ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE 32
|
#define ZT_SQLITENETWORKCONTROLLER_IN_MEMORY_LOG_SIZE 32
|
||||||
|
@ -86,6 +87,10 @@ public:
|
||||||
std::string &responseBody,
|
std::string &responseBody,
|
||||||
std::string &responseContentType);
|
std::string &responseContentType);
|
||||||
|
|
||||||
|
// threadMain() for backup thread -- do not call directly
|
||||||
|
void threadMain()
|
||||||
|
throw();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum IpAssignmentType {
|
enum IpAssignmentType {
|
||||||
// IP assignment is a static IP address
|
// IP assignment is a static IP address
|
||||||
|
@ -112,6 +117,8 @@ private:
|
||||||
static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report);
|
static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report);
|
||||||
|
|
||||||
Node *_node;
|
Node *_node;
|
||||||
|
Thread _backupThread;
|
||||||
|
volatile bool _backupThreadRun;
|
||||||
std::string _dbPath;
|
std::string _dbPath;
|
||||||
std::string _circuitTestPath;
|
std::string _circuitTestPath;
|
||||||
std::string _instanceId;
|
std::string _instanceId;
|
||||||
|
|
|
@ -95,7 +95,6 @@ public:
|
||||||
static inline bool rm(const std::string &path) throw() { return rm(path.c_str()); }
|
static inline bool rm(const std::string &path) throw() { return rm(path.c_str()); }
|
||||||
|
|
||||||
static inline bool mkdir(const char *path)
|
static inline bool mkdir(const char *path)
|
||||||
throw()
|
|
||||||
{
|
{
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
if (::PathIsDirectoryA(path))
|
if (::PathIsDirectoryA(path))
|
||||||
|
|
Loading…
Add table
Reference in a new issue