Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit 806068b2 authored by rswindell's avatar rswindell

Use a lock file (sbbslist.json.lock) to protect the database (sbbslist.json)

from corruption during concurrent operations. Although the list file is not
open shareable, I was observing corruption on Vertrauen when multiple sbbslist
tasks (e.g. verification and maintenance) were running concurrently on
different systems. The .lock file method is crude, but is working to protect
the list from concurrent opens of any kind (read or write).
parent 37e55ca3
// $Id$
// @format.tab-size 4
// Synchronet BBS List (SBL) v4 Library
......@@ -402,39 +403,78 @@ function parse(f)
return list;
}
function lock_fname()
{
return list_fname + '.lock';
}
function lock(op, timeout /* in seconds */, max)
{
var start = time();
if(timeout === undefined)
timeout = 60;
if(max === undefined)
max = 24 * 60 * 60;
while(!file_mutex(lock_fname(), op, max)) {
if(time() - start >= timeout) {
log(LOG_ERR, "SBBSLIST: Timeout locking " + list_fname + " for " + op);
return false;
}
sleep(1000);
}
return true;
}
function unlock()
{
return file_remove(lock_fname());
}
function read_list()
{
if(!lock("read"))
return false;
var f = new File(list_fname);
log(LOG_DEBUG, "Opening list file: " + f.name);
if(!f.open("r")) {
log(LOG_ERR, "SBBSLIST: Error " + f.error + " opening " + f.name);
unlock();
return [];
}
var list = parse(f);
f.close();
unlock();
return list;
}
function write_list(list)
{
if(!lock("write"))
return false;
var out = new File(list_fname);
log(LOG_DEBUG, "SBBSLIST: Opening / creating list file: " + list_fname);
if(!out.open("w+")) {
log(LOG_ERR, "SBBSLIST: Error " + out.error + " creating " + out.name);
unlock();
return false;
}
log(LOG_DEBUG, "SBBSLIST: Writing list file: " + out.name + " (" + list.length + " BBS entries)");
out.write(JSON.stringify(list, null, 4));
out.close();
unlock();
return true;
}
function append(bbs)
{
if(!lock("append"))
return false;
var f = new File(list_fname);
log(LOG_DEBUG, "SBBSLIST: Opening / creating list file: " + list_fname);
if(!f.open(f.exists ? 'r+':'w+')) {
log(LOG_ERR, "SBBSLIST: Error " + f.error + " creating " + f.name);
unlock();
return false;
}
var list = parse(f);
......@@ -443,21 +483,26 @@ function append(bbs)
f.truncate();
f.write(JSON.stringify(list, null, 4));
f.close();
unlock();
return true;
}
function remove(bbs)
{
if(!lock("remove"))
return false;
var f = new File(list_fname);
log(LOG_INFO, "SBBSLIST: Opening / creating list file: " + list_fname);
if(!f.open('r+')) {
log(LOG_ERR, "SBBSLIST: Error " + f.error + " opening " + f.name);
unlock();
return false;
}
var list = parse(f);
var index = find_value(list, "name", bbs.name);
if(index < 0 ) {
f.close();
unlock();
return false;
}
list.splice(index, 1);
......@@ -465,21 +510,26 @@ function remove(bbs)
f.truncate();
f.write(JSON.stringify(list, null, 4));
f.close();
unlock();
return true;
}
function replace(bbs)
{
if(!lock("replace"))
return false;
var f = new File(list_fname);
log(LOG_INFO, "SBBSLIST: Opening / creating list file: " + list_fname);
if(!f.open('r+')) {
log(LOG_ERR, "SBBSLIST: Error " + f.error + " opening " + f.name);
unlock();
return false;
}
var list = parse(f);
var index = find_value(list, "name", bbs.name);
if(index < 0 ) {
f.close();
unlock();
return false;
}
list[index] = bbs;
......@@ -487,6 +537,7 @@ function replace(bbs)
f.truncate();
f.write(JSON.stringify(list, null, 4));
f.close();
unlock();
return true;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment