3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 23:02:15 +00:00

Make Peer.downloadData() atomic rather than locked under the Peer lock.

Resolves issue 310.
This commit is contained in:
Mike Hearn 2013-02-15 15:48:53 +01:00
parent 38ec23299c
commit 4bcb550796

View File

@ -33,6 +33,7 @@ import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -61,7 +62,7 @@ public class Peer {
// Whether to try and download blocks and transactions from this peer. Set to false by PeerGroup if not the // Whether to try and download blocks and transactions from this peer. Set to false by PeerGroup if not the
// primary peer. This is to avoid redundant work and concurrency problems with downloading the same chain // primary peer. This is to avoid redundant work and concurrency problems with downloading the same chain
// in parallel. // in parallel.
private boolean downloadData = false; private final AtomicBoolean downloadData = new AtomicBoolean();
// The version data to announce to the other side of the connections we make: useful for setting our "user agent" // The version data to announce to the other side of the connections we make: useful for setting our "user agent"
// equivalent and other things. // equivalent and other things.
private final VersionMessage versionMessage; private final VersionMessage versionMessage;
@ -124,7 +125,7 @@ public class Peer {
this.params = Preconditions.checkNotNull(params); this.params = Preconditions.checkNotNull(params);
this.versionMessage = Preconditions.checkNotNull(ver); this.versionMessage = Preconditions.checkNotNull(ver);
this.blockChain = chain; // Allowed to be null. this.blockChain = chain; // Allowed to be null.
this.downloadData = chain != null; this.downloadData.set(chain != null);
this.getDataFutures = new CopyOnWriteArrayList<GetDataRequest>(); this.getDataFutures = new CopyOnWriteArrayList<GetDataRequest>();
this.eventListeners = new CopyOnWriteArrayList<PeerEventListener>(); this.eventListeners = new CopyOnWriteArrayList<PeerEventListener>();
this.lifecycleListeners = new CopyOnWriteArrayList<PeerLifecycleListener>(); this.lifecycleListeners = new CopyOnWriteArrayList<PeerLifecycleListener>();
@ -632,7 +633,7 @@ public class Peer {
// Was this block requested by getBlock()? // Was this block requested by getBlock()?
if (maybeHandleRequestedData(m)) return; if (maybeHandleRequestedData(m)) return;
if (!downloadData) { if (!downloadData.get()) {
// This can happen if we lose download peer status after requesting block data. // This can happen if we lose download peer status after requesting block data.
log.debug("{}: Received block we did not ask for: {}", address.get(), m.getHashAsString()); log.debug("{}: Received block we did not ask for: {}", address.get(), m.getHashAsString());
return; return;
@ -674,7 +675,7 @@ public class Peer {
private synchronized void processFilteredBlock(FilteredBlock m) throws IOException { private synchronized void processFilteredBlock(FilteredBlock m) throws IOException {
log.debug("{}: Received broadcast filtered block {}", address.get(), m.getHash().toString()); log.debug("{}: Received broadcast filtered block {}", address.get(), m.getHash().toString());
try { try {
if (!downloadData) { if (!downloadData.get()) {
log.debug("{}: Received block we did not ask for: {}", address.get(), m.getHash().toString()); log.debug("{}: Received block we did not ask for: {}", address.get(), m.getHash().toString());
return; return;
} }
@ -761,6 +762,8 @@ public class Peer {
} }
} }
final boolean downloadData = this.downloadData.get();
if (transactions.size() == 0 && blocks.size() == 1) { if (transactions.size() == 0 && blocks.size() == 1) {
// Single block announcement. If we're downloading the chain this is just a tickle to make us continue // Single block announcement. If we're downloading the chain this is just a tickle to make us continue
// (the block chain download protocol is very implicit and not well thought out). If we're not downloading // (the block chain download protocol is very implicit and not well thought out). If we're not downloading
@ -1182,16 +1185,16 @@ public class Peer {
* Returns true if this peer will try and download things it is sent in "inv" messages. Normally you only need * Returns true if this peer will try and download things it is sent in "inv" messages. Normally you only need
* one peer to be downloading data. Defaults to true. * one peer to be downloading data. Defaults to true.
*/ */
public synchronized boolean getDownloadData() { public boolean getDownloadData() {
return downloadData; return downloadData.get();
} }
/** /**
* If set to false, the peer won't try and fetch blocks and transactions it hears about. Normally, only one * If set to false, the peer won't try and fetch blocks and transactions it hears about. Normally, only one
* peer should download missing blocks. Defaults to true. * peer should download missing blocks. Defaults to true.
*/ */
public synchronized void setDownloadData(boolean downloadData) { public void setDownloadData(boolean downloadData) {
this.downloadData = downloadData; this.downloadData.set(downloadData);
} }
/** /**