3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 06:44:16 +00:00

Additional level of locking to work around Android issue

Resolves issue 153.
This commit is contained in:
Miron Cuperman 2012-03-23 13:43:23 -07:00
parent 4f0c10bd2d
commit 91a5949930
3 changed files with 92 additions and 14 deletions

View File

@ -17,6 +17,8 @@
package com.google.bitcoin.store;
import com.google.bitcoin.core.*;
import com.google.bitcoin.utils.NamedSemaphores;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -52,6 +54,7 @@ import java.util.Map;
public class BoundedOverheadBlockStore implements BlockStore {
private static final Logger log = LoggerFactory.getLogger(BoundedOverheadBlockStore.class);
private static final byte FILE_FORMAT_VERSION = 1;
private static NamedSemaphores semaphores = new NamedSemaphores();
private RandomAccessFile file;
// We keep some recently found blocks in the blockCache. It can help to optimize some cases where we are
@ -80,6 +83,7 @@ public class BoundedOverheadBlockStore implements BlockStore {
private final NetworkParameters params;
private FileChannel channel;
private FileLock lock;
private String fileName;
private static class Record {
// A BigInteger representing the total amount of work done so far on this chain. As of May 2011 it takes 8
@ -148,6 +152,12 @@ public class BoundedOverheadBlockStore implements BlockStore {
public BoundedOverheadBlockStore(NetworkParameters params, File file) throws BlockStoreException {
this.params = params;
try {
this.fileName = file.getCanonicalPath();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (file.exists()) {
try {
load(file);
@ -203,6 +213,7 @@ public class BoundedOverheadBlockStore implements BlockStore {
int version = this.file.read();
if (version == -1) {
// No such file or the file was empty.
close();
throw new FileNotFoundException(file.getName() + " does not exist or is empty");
}
if (version != FILE_FORMAT_VERSION) {
@ -216,7 +227,8 @@ public class BoundedOverheadBlockStore implements BlockStore {
log.info("Read chain head from disk: {}", this.chainHead);
channel.position(channel.size() - Record.SIZE);
} catch (IOException e) {
this.file.close();
if (this.file != null)
this.file.close();
throw e;
} catch (BlockStoreException e) {
this.file.close();
@ -225,9 +237,13 @@ public class BoundedOverheadBlockStore implements BlockStore {
}
private void lock() throws IOException, BlockStoreException {
if (!semaphores.tryAcquire(fileName)) {
throw new BlockStoreException("File in use");
}
try {
lock = channel.tryLock();
} catch (OverlappingFileLockException e) {
semaphores.release(fileName);
lock = null;
}
if (lock == null) {
@ -354,6 +370,7 @@ public class BoundedOverheadBlockStore implements BlockStore {
} catch (IOException e) {
throw new BlockStoreException(e);
} finally {
semaphores.release(this.fileName);
file = null;
}
}

View File

@ -17,6 +17,8 @@
package com.google.bitcoin.store;
import com.google.bitcoin.core.*;
import com.google.bitcoin.utils.NamedSemaphores;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -42,26 +44,23 @@ public class DiskBlockStore implements BlockStore {
private Sha256Hash chainHead;
private NetworkParameters params;
private FileLock lock;
private String fileName;
private static NamedSemaphores semaphores = new NamedSemaphores();
public DiskBlockStore(NetworkParameters params, File theFile) throws BlockStoreException {
this.params = params;
try {
this.fileName = theFile.getCanonicalPath();
} catch (IOException e) {
throw new RuntimeException(e);
}
blockMap = new HashMap<Sha256Hash, StoredBlock>();
try {
file = new RandomAccessFile(theFile, "rwd");
// Lock the file from other processes.
try {
lock = file.getChannel().tryLock();
} catch (OverlappingFileLockException e) {
lock = null;
}
if (lock == null) {
try {
this.file.close();
} finally {
this.file = null;
}
throw new BlockStoreException("Could not lock file");
}
lock();
// The file position is at BOF
load(theFile);
// The file position is at EOF
@ -79,6 +78,7 @@ public class DiskBlockStore implements BlockStore {
} catch (IOException e) {
throw new BlockStoreException(e);
} finally {
semaphores.release(this.fileName);
file = null;
}
}
@ -213,4 +213,24 @@ public class DiskBlockStore implements BlockStore {
throw new BlockStoreException(e);
}
}
private void lock() throws IOException, BlockStoreException {
if (!semaphores.tryAcquire(fileName)) {
throw new BlockStoreException("File in use");
}
try {
lock = file.getChannel().tryLock();
} catch (OverlappingFileLockException e) {
semaphores.release(fileName);
lock = null;
}
if (lock == null) {
try {
this.file.close();
} finally {
this.file = null;
}
throw new BlockStoreException("Could not lock file");
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright 2012 Google Inc. All Rights Reserved.
package com.google.bitcoin.utils;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
/**
* @author miron@google.com (Miron Cuperman)
*
*/
public class NamedSemaphores {
private Map<String, Semaphore> lockMap = new HashMap<String, Semaphore>();
public void acquire(String name) throws InterruptedException {
Semaphore s = getSemaphore(name);
s.acquire();
}
public boolean tryAcquire(String name) {
Semaphore s = getSemaphore(name);
return s.tryAcquire();
}
public void release(String name) {
Semaphore s = getSemaphore(name);
s.release();
}
private Semaphore getSemaphore(String name) {
synchronized (lockMap) {
Semaphore s = lockMap.get(name);
if (s == null) {
s = new Semaphore(1);
lockMap.put(name, s);
}
return s;
}
}
}