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:
Adam Ierymenko 2015-11-03 15:52:10 -08:00
parent 4b655ab22c
commit 7903f24a8f
3 changed files with 62 additions and 1 deletions

View file

@ -71,6 +71,9 @@
// than this (ms).
#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000
// Delay between backups in milliseconds
#define ZT_NETCONF_BACKUP_PERIOD 60000
namespace ZeroTier {
namespace {
@ -122,6 +125,7 @@ struct NetworkRecord {
SqliteNetworkController::SqliteNetworkController(Node *node,const char *dbPath,const char *circuitTestPath) :
_node(node),
_backupThreadRun(true),
_dbPath(dbPath),
_circuitTestPath(circuitTestPath),
_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)");
_instanceId = iid;
}
_backupThread = Thread::start(this);
}
SqliteNetworkController::~SqliteNetworkController()
{
_backupThreadRun = false;
Thread::join(_backupThread);
Mutex::Lock _l(_lock);
if (_db) {
sqlite3_finalize(_sGetNetworkById);
@ -991,6 +1000,52 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpDELETE(
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(
const std::vector<std::string> &path,
const std::map<std::string,std::string> &urlArgs,