mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 13:49:53 +01:00
Don't block when free disk space is critically low.
If it's not possible to free up any additional space, exit rather than hanging. In future we should warn the user before exiting.
This commit is contained in:
@@ -86,10 +86,8 @@ DatabaseCleaner.Callback {
|
|||||||
private final List<DatabaseListener> listeners =
|
private final List<DatabaseListener> listeners =
|
||||||
new ArrayList<DatabaseListener>(); // Locking: self
|
new ArrayList<DatabaseListener>(); // Locking: self
|
||||||
private final Object spaceLock = new Object();
|
private final Object spaceLock = new Object();
|
||||||
private final Object writeLock = new Object();
|
|
||||||
private long bytesStoredSinceLastCheck = 0L; // Locking: spaceLock
|
private long bytesStoredSinceLastCheck = 0L; // Locking: spaceLock
|
||||||
private long timeOfLastCheck = 0L; // Locking: spaceLock
|
private long timeOfLastCheck = 0L; // Locking: spaceLock
|
||||||
private volatile boolean writesAllowed = true;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner) {
|
DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner) {
|
||||||
@@ -162,7 +160,6 @@ DatabaseCleaner.Callback {
|
|||||||
|
|
||||||
public void addLocalGroupMessage(Message m) throws DbException {
|
public void addLocalGroupMessage(Message m) throws DbException {
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
waitForPermissionToWrite();
|
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
@@ -201,23 +198,6 @@ DatabaseCleaner.Callback {
|
|||||||
if(added) callListeners(Event.MESSAGES_ADDED);
|
if(added) callListeners(Event.MESSAGES_ADDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Blocks until messages are allowed to be stored in the database. The
|
|
||||||
* storage of messages is not allowed while the amount of free storage
|
|
||||||
* space available to the database is less than CRITICAL_FREE_SPACE.
|
|
||||||
*/
|
|
||||||
private void waitForPermissionToWrite() {
|
|
||||||
synchronized(writeLock) {
|
|
||||||
while(!writesAllowed) {
|
|
||||||
if(LOG.isLoggable(Level.FINE))
|
|
||||||
LOG.fine("Waiting for permission to write");
|
|
||||||
try {
|
|
||||||
writeLock.wait();
|
|
||||||
} catch(InterruptedException ignored) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the given message is already in the database, marks it as seen by the
|
* If the given message is already in the database, marks it as seen by the
|
||||||
* sender and returns false. Otherwise stores the message, updates the
|
* sender and returns false. Otherwise stores the message, updates the
|
||||||
@@ -307,7 +287,6 @@ DatabaseCleaner.Callback {
|
|||||||
public void addLocalPrivateMessage(Message m, ContactId c)
|
public void addLocalPrivateMessage(Message m, ContactId c)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
waitForPermissionToWrite();
|
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
@@ -901,7 +880,6 @@ DatabaseCleaner.Callback {
|
|||||||
|
|
||||||
public void receiveBatch(ContactId c, Batch b) throws DbException {
|
public void receiveBatch(ContactId c, Batch b) throws DbException {
|
||||||
boolean anyAdded = false;
|
boolean anyAdded = false;
|
||||||
waitForPermissionToWrite();
|
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
@@ -1356,27 +1334,25 @@ DatabaseCleaner.Callback {
|
|||||||
public void checkFreeSpaceAndClean() throws DbException {
|
public void checkFreeSpaceAndClean() throws DbException {
|
||||||
long freeSpace = db.getFreeSpace();
|
long freeSpace = db.getFreeSpace();
|
||||||
while(freeSpace < MIN_FREE_SPACE) {
|
while(freeSpace < MIN_FREE_SPACE) {
|
||||||
// If disk space is critical, disable the storage of new messages
|
boolean expired = expireMessages(BYTES_PER_SWEEP);
|
||||||
if(freeSpace < CRITICAL_FREE_SPACE) {
|
if(freeSpace < CRITICAL_FREE_SPACE && !expired) {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Critical cleanup");
|
// FIXME: Work out what to do here - the amount of free space
|
||||||
writesAllowed = false;
|
// is critically low and there are no messages left to expire
|
||||||
} else {
|
System.err.println("Disk space is critical - shutting down");
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Normal cleanup");
|
System.exit(1);
|
||||||
}
|
}
|
||||||
expireMessages(BYTES_PER_SWEEP);
|
|
||||||
Thread.yield();
|
Thread.yield();
|
||||||
freeSpace = db.getFreeSpace();
|
freeSpace = db.getFreeSpace();
|
||||||
// If disk space is no longer critical, re-enable writes
|
|
||||||
if(freeSpace >= CRITICAL_FREE_SPACE && !writesAllowed) {
|
|
||||||
writesAllowed = true;
|
|
||||||
synchronized(writeLock) {
|
|
||||||
writeLock.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expireMessages(int size) throws DbException {
|
/**
|
||||||
|
* Removes the oldest messages from the database, with a total size less
|
||||||
|
* than or equal to the given size, and returns true if any messages were
|
||||||
|
* removed.
|
||||||
|
*/
|
||||||
|
private boolean expireMessages(int size) throws DbException {
|
||||||
|
Collection<MessageId> old;
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
@@ -1385,9 +1361,8 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
for(MessageId m : db.getOldMessages(txn, size)) {
|
old = db.getOldMessages(txn, size);
|
||||||
removeMessage(txn, m);
|
for(MessageId m : old) removeMessage(txn, m);
|
||||||
}
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
@@ -1402,6 +1377,7 @@ DatabaseCleaner.Callback {
|
|||||||
} finally {
|
} finally {
|
||||||
contactLock.readLock().unlock();
|
contactLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
|
return old.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user