Separate the locks on the main FT and the blockOfferListByKey (including the block offers themselves).
Remove the offers even if there are no FT entries
Concurrency: Make bootID an AtomicLong. It wasn't locked at all, and it would not be safe to use PeerNode.this as lock. It's used in the messaging layer and lots of other places. But there shouldn't be any consistency issues with it.
Separate lock for peer location and FOAF locations. This and the boot ID are the only things used by FTE, so hopefully this will prevent FTE deadlocks when we lock PeerNode first.
Factor out PeerLocation
Factor out Location.isValid
Fix locking for location reset check, and use Location.equals()
Call pn.offer() outside the FTE lock. We do not need to hold the lock here.
Delete bogus code
Clarify isConnected (logic and comments). No functional impact, the value should be the same when we exit the lock.
Hence we do not need to check currentTracker != null in isConnected()
Factor out BooleanLastTrueTracker, use it for isConnected, and pass now into exportMetadataFieldSet as the tracking needs now on setConnected and timeLastConnected() (hence is a bit more accurate).
Use new interface PeerNodeUnlocked to guarantee that FailureTableEntry never uses a method on PeerNode that is sync(this). This eliminates any deadlock risk from FailureTableEntry and also hopefully improves maximum wait times significantly.