forked from I2P_Developers/i2p.i2p
Merge branch '465-subdb-ri' into 'master'
NetDB: Enforce no RIs in subdbs (Gitlab #465) Closes #465 See merge request i2p-hackers/i2p.i2p!143
This commit is contained in:
@@ -95,7 +95,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
|
|||||||
// for ISJ
|
// for ISJ
|
||||||
_context.statManager().createRateStat("netDb.RILookupDirect", "Was an iterative RI lookup sent directly?", "NetworkDatabase", rate);
|
_context.statManager().createRateStat("netDb.RILookupDirect", "Was an iterative RI lookup sent directly?", "NetworkDatabase", rate);
|
||||||
// No need to start the FloodfillMonitorJob for client subDb.
|
// No need to start the FloodfillMonitorJob for client subDb.
|
||||||
if (!isMainDb())
|
if (isClientDb())
|
||||||
_ffMonitor = null;
|
_ffMonitor = null;
|
||||||
else
|
else
|
||||||
_ffMonitor = new FloodfillMonitorJob(_context, this);
|
_ffMonitor = new FloodfillMonitorJob(_context, this);
|
||||||
@@ -107,7 +107,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
|
|||||||
super.startup();
|
super.startup();
|
||||||
if (_ffMonitor != null)
|
if (_ffMonitor != null)
|
||||||
_context.jobQueue().addJob(_ffMonitor);
|
_context.jobQueue().addJob(_ffMonitor);
|
||||||
if (!isMainDb()) {
|
if (isClientDb()) {
|
||||||
isFF = false;
|
isFF = false;
|
||||||
} else {
|
} else {
|
||||||
isFF = _context.getBooleanProperty(FloodfillMonitorJob.PROP_FLOODFILL_PARTICIPANT);
|
isFF = _context.getBooleanProperty(FloodfillMonitorJob.PROP_FLOODFILL_PARTICIPANT);
|
||||||
@@ -116,7 +116,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
|
|||||||
}
|
}
|
||||||
|
|
||||||
long down = _context.router().getEstimatedDowntime();
|
long down = _context.router().getEstimatedDowntime();
|
||||||
if (!_context.commSystem().isDummy() && isMainDb() &&
|
if (!_context.commSystem().isDummy() && !isClientDb() &&
|
||||||
(down == 0 || (!isFF && down > 30*60*1000) || (isFF && down > 24*60*60*1000))) {
|
(down == 0 || (!isFF && down > 30*60*1000) || (isFF && down > 24*60*60*1000))) {
|
||||||
// refresh old routers
|
// refresh old routers
|
||||||
Job rrj = new RefreshRoutersJob(_context, this);
|
Job rrj = new RefreshRoutersJob(_context, this);
|
||||||
@@ -128,7 +128,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
|
|||||||
@Override
|
@Override
|
||||||
protected void createHandlers() {
|
protected void createHandlers() {
|
||||||
// Only initialize the handlers for the flooodfill netDb.
|
// Only initialize the handlers for the flooodfill netDb.
|
||||||
if (isMainDb()) {
|
if (!isClientDb()) {
|
||||||
if (_log.shouldInfo())
|
if (_log.shouldInfo())
|
||||||
_log.info("[dbid: " + super._dbid + "] Initializing the message handlers");
|
_log.info("[dbid: " + super._dbid + "] Initializing the message handlers");
|
||||||
_context.inNetMessagePool().registerHandlerJobBuilder(DatabaseLookupMessage.MESSAGE_TYPE, new FloodfillDatabaseLookupMessageHandler(_context, this));
|
_context.inNetMessagePool().registerHandlerJobBuilder(DatabaseLookupMessage.MESSAGE_TYPE, new FloodfillDatabaseLookupMessageHandler(_context, this));
|
||||||
@@ -435,13 +435,6 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected PeerSelector createPeerSelector() {
|
|
||||||
if (_peerSelector != null)
|
|
||||||
return _peerSelector;
|
|
||||||
return new FloodfillPeerSelector(_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public, called from console. This wakes up the floodfill monitor,
|
* Public, called from console. This wakes up the floodfill monitor,
|
||||||
* which will rebuild the RI and log in the event log,
|
* which will rebuild the RI and log in the event log,
|
||||||
|
@@ -148,11 +148,11 @@ class FloodfillVerifyStoreJob extends JobImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// garlic encrypt to hide contents from the OBEP
|
// garlic encrypt to hide contents from the OBEP
|
||||||
RouterInfo peer = _facade.lookupRouterInfoLocally(_target);
|
RouterInfo peer = ctx.netDb().lookupRouterInfoLocally(_target);
|
||||||
if (peer == null) {
|
if (peer == null) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("(JobId: " + getJobId()
|
_log.warn("(JobId: " + getJobId()
|
||||||
+ "; dbid: " + _facade._dbid
|
+ "; db: " + _facade
|
||||||
+ ") Fail looking up RI locally for target " + _target);
|
+ ") Fail looking up RI locally for target " + _target);
|
||||||
_facade.verifyFinished(_key);
|
_facade.verifyFinished(_key);
|
||||||
return;
|
return;
|
||||||
@@ -245,7 +245,7 @@ class FloodfillVerifyStoreJob extends JobImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("[JobId: " + getJobId() + "; dbid: " + _facade._dbid
|
_log.info("[JobId: " + getJobId() + "; db: " + _facade
|
||||||
+ "]: Starting verify (stored " + _key + " to " + _sentTo + "), asking " + _target);
|
+ "]: Starting verify (stored " + _key + " to " + _sentTo + "), asking " + _target);
|
||||||
_sendTime = ctx.clock().now();
|
_sendTime = ctx.clock().now();
|
||||||
_expiration = _sendTime + VERIFY_TIMEOUT;
|
_expiration = _sendTime + VERIFY_TIMEOUT;
|
||||||
@@ -277,7 +277,7 @@ class FloodfillVerifyStoreJob extends JobImpl {
|
|||||||
if (peers.isEmpty())
|
if (peers.isEmpty())
|
||||||
break;
|
break;
|
||||||
Hash peer = peers.get(0);
|
Hash peer = peers.get(0);
|
||||||
RouterInfo ri = _facade.lookupRouterInfoLocally(peer);
|
RouterInfo ri = getContext().netDb().lookupRouterInfoLocally(peer);
|
||||||
//if (ri != null && StoreJob.supportsCert(ri, keyCert)) {
|
//if (ri != null && StoreJob.supportsCert(ri, keyCert)) {
|
||||||
if (ri != null && StoreJob.shouldStoreTo(ri) &&
|
if (ri != null && StoreJob.shouldStoreTo(ri) &&
|
||||||
//(!_isLS2 || (StoreJob.shouldStoreLS2To(ri) &&
|
//(!_isLS2 || (StoreJob.shouldStoreLS2To(ri) &&
|
||||||
@@ -334,18 +334,7 @@ class FloodfillVerifyStoreJob extends JobImpl {
|
|||||||
return _key.equals(dsm.getKey());
|
return _key.equals(dsm.getKey());
|
||||||
} else if (type == DatabaseSearchReplyMessage.MESSAGE_TYPE) {
|
} else if (type == DatabaseSearchReplyMessage.MESSAGE_TYPE) {
|
||||||
DatabaseSearchReplyMessage dsrm = (DatabaseSearchReplyMessage)message;
|
DatabaseSearchReplyMessage dsrm = (DatabaseSearchReplyMessage)message;
|
||||||
boolean rv = _key.equals(dsrm.getSearchKey());
|
return _key.equals(dsrm.getSearchKey());
|
||||||
if (rv) {
|
|
||||||
if (_log.shouldInfo())
|
|
||||||
_log.info("[JobId: " + getJobId() + "; dbid: " + _facade._dbid
|
|
||||||
+ "DSRM key match successful.");
|
|
||||||
} else {
|
|
||||||
if (_log.shouldWarn())
|
|
||||||
_log.warn("[JobId: " + getJobId() + "; dbid: " + _facade._dbid
|
|
||||||
+ "]: DSRM key mismatch for key " + _key
|
|
||||||
+ " with DSRM: " + message);
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -413,21 +402,16 @@ class FloodfillVerifyStoreJob extends JobImpl {
|
|||||||
// assume 0 old, all new, 0 invalid, 0 dup
|
// assume 0 old, all new, 0 invalid, 0 dup
|
||||||
pm.dbLookupReply(_target, 0,
|
pm.dbLookupReply(_target, 0,
|
||||||
dsrm.getNumReplies(), 0, 0, delay);
|
dsrm.getNumReplies(), 0, 0, delay);
|
||||||
// ToDo: Clarify the following log message.
|
// The peer we asked did not have the key, so _sentTo failed to flood it
|
||||||
// This message is phrased in a manner that draws attention, and indicates
|
|
||||||
// the possibility of a problem that may need follow-up. But examination
|
|
||||||
// of the code did not provide insight as to what is being verified,
|
|
||||||
// and what is failing. This message will be displayed unconditionally
|
|
||||||
// every time a DSRM is handled here.
|
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn(getJobId() + ": DSRM verify failed (dbid: "
|
_log.warn(getJobId() + ": DSRM verify failed (db: "
|
||||||
+ _facade._dbid + ") for " + _key);
|
+ _facade + ") for " + _key);
|
||||||
// only for RI... LS too dangerous?
|
// only for RI... LS too dangerous?
|
||||||
if (_isRouterInfo) {
|
if (_isRouterInfo) {
|
||||||
if (_facade.isClientDb())
|
if (_facade.isClientDb())
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("[Jobid: " + getJobId() + "; dbid: " + _facade._dbid
|
_log.warn("[Jobid: " + getJobId() + "; db: " + _facade
|
||||||
+ "Warning! Client is starting a SingleLookupJob (DIRECT?) for RouterInfo");
|
+ "] Warning! Client is starting a SingleLookupJob (DIRECT?) for RouterInfo");
|
||||||
ctx.jobQueue().addJob(new SingleLookupJob(ctx, dsrm));
|
ctx.jobQueue().addJob(new SingleLookupJob(ctx, dsrm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,12 +442,7 @@ class FloodfillVerifyStoreJob extends JobImpl {
|
|||||||
* So at least we'll try THREE ffs round-robin if things continue to fail...
|
* So at least we'll try THREE ffs round-robin if things continue to fail...
|
||||||
*/
|
*/
|
||||||
private void resend() {
|
private void resend() {
|
||||||
// It's safe to check the default netDb first, but if the lookup is for
|
|
||||||
// a client, nearly all RI is expected to be found in the FF netDb.
|
|
||||||
DatabaseEntry ds = _facade.lookupLocally(_key);
|
DatabaseEntry ds = _facade.lookupLocally(_key);
|
||||||
if ((ds == null) && _facade.isClientDb() && _isRouterInfo)
|
|
||||||
// It's safe to check the floodfill netDb for RI
|
|
||||||
ds = getContext().netDb().lookupLocally(_key);
|
|
||||||
if (ds != null) {
|
if (ds != null) {
|
||||||
// By the time we get here, a minute or more after the store started,
|
// By the time we get here, a minute or more after the store started,
|
||||||
// we may have already started a new store
|
// we may have already started a new store
|
||||||
|
@@ -177,22 +177,24 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
_dbid = dbid;
|
_dbid = dbid;
|
||||||
_log = _context.logManager().getLog(getClass());
|
_log = _context.logManager().getLog(getClass());
|
||||||
_networkID = context.router().getNetworkID();
|
_networkID = context.router().getNetworkID();
|
||||||
_peerSelector = createPeerSelector();
|
|
||||||
_publishingLeaseSets = new HashMap<Hash, RepublishLeaseSetJob>(8);
|
_publishingLeaseSets = new HashMap<Hash, RepublishLeaseSetJob>(8);
|
||||||
_activeRequests = new HashMap<Hash, SearchJob>(8);
|
_activeRequests = new HashMap<Hash, SearchJob>(8);
|
||||||
if (!isMainDb()) {
|
if (isClientDb()) {
|
||||||
_reseedChecker = null;
|
_reseedChecker = null;
|
||||||
_blindCache = null;
|
_blindCache = null;
|
||||||
_exploreKeys = null;
|
_exploreKeys = null;
|
||||||
|
_erj = null;
|
||||||
|
_peerSelector = ((KademliaNetworkDatabaseFacade) context.netDb()).getPeerSelector();
|
||||||
} else {
|
} else {
|
||||||
_reseedChecker = new ReseedChecker(context);
|
_reseedChecker = new ReseedChecker(context);
|
||||||
_blindCache = new BlindCache(context);
|
_blindCache = new BlindCache(context);
|
||||||
_exploreKeys = new ConcurrentHashSet<Hash>(64);
|
_exploreKeys = new ConcurrentHashSet<Hash>(64);
|
||||||
|
// We don't have a comm system here to check for ctx.commSystem().isDummy()
|
||||||
|
// we'll check before starting in startup()
|
||||||
|
_erj = new ExpireRoutersJob(_context, this);
|
||||||
|
_peerSelector = createPeerSelector();
|
||||||
}
|
}
|
||||||
_elj = new ExpireLeasesJob(_context, this);
|
_elj = new ExpireLeasesJob(_context, this);
|
||||||
// We don't have a comm system here to check for ctx.commSystem().isDummy()
|
|
||||||
// we'll check before starting in startup()
|
|
||||||
_erj = new ExpireRoutersJob(_context, this);
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Created KademliaNetworkDatabaseFacade for id: " + dbid);
|
_log.debug("Created KademliaNetworkDatabaseFacade for id: " + dbid);
|
||||||
context.statManager().createRateStat("netDb.lookupDeferred", "how many lookups are deferred?", "NetworkDatabase", new long[] { 60*60*1000 });
|
context.statManager().createRateStat("netDb.lookupDeferred", "how many lookups are deferred?", "NetworkDatabase", new long[] { 60*60*1000 });
|
||||||
@@ -218,13 +220,24 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
return _initialized && _ds != null && _ds.isInitialized();
|
return _initialized && _ds != null && _ds.isInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract PeerSelector createPeerSelector();
|
/**
|
||||||
|
* Only for main DB
|
||||||
|
*/
|
||||||
|
protected PeerSelector createPeerSelector() {
|
||||||
|
if (isClientDb())
|
||||||
|
throw new IllegalStateException();
|
||||||
|
return new FloodfillPeerSelector(_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the main DB's peer selector. Client DBs do not have their own.
|
||||||
|
*/
|
||||||
public PeerSelector getPeerSelector() { return _peerSelector; }
|
public PeerSelector getPeerSelector() { return _peerSelector; }
|
||||||
|
|
||||||
/** @since 0.9 */
|
/** @since 0.9 */
|
||||||
@Override
|
@Override
|
||||||
public ReseedChecker reseedChecker() {
|
public ReseedChecker reseedChecker() {
|
||||||
if (!isMainDb())
|
if (isClientDb())
|
||||||
return null;
|
return null;
|
||||||
return _reseedChecker;
|
return _reseedChecker;
|
||||||
}
|
}
|
||||||
@@ -238,11 +251,14 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected BlindCache blindCache() {
|
protected BlindCache blindCache() {
|
||||||
if (isMainDb())
|
if (!isClientDb())
|
||||||
return _blindCache;
|
return _blindCache;
|
||||||
return _context.netDb().blindCache();
|
return _context.netDb().blindCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the main DB's KBucketSet. Client DBs do not have their own.
|
||||||
|
*/
|
||||||
KBucketSet<Hash> getKBuckets() { return _kb; }
|
KBucketSet<Hash> getKBuckets() { return _kb; }
|
||||||
DataStore getDataStore() { return _ds; }
|
DataStore getDataStore() { return _ds; }
|
||||||
|
|
||||||
@@ -255,20 +271,20 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
|
|
||||||
/** @return unmodifiable set */
|
/** @return unmodifiable set */
|
||||||
public Set<Hash> getExploreKeys() {
|
public Set<Hash> getExploreKeys() {
|
||||||
if (!_initialized || !isMainDb())
|
if (!_initialized || isClientDb())
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
return Collections.unmodifiableSet(_exploreKeys);
|
return Collections.unmodifiableSet(_exploreKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeFromExploreKeys(Collection<Hash> toRemove) {
|
public void removeFromExploreKeys(Collection<Hash> toRemove) {
|
||||||
if (!_initialized || !isMainDb())
|
if (!_initialized || isClientDb())
|
||||||
return;
|
return;
|
||||||
_exploreKeys.removeAll(toRemove);
|
_exploreKeys.removeAll(toRemove);
|
||||||
_context.statManager().addRateData("netDb.exploreKeySet", _exploreKeys.size());
|
_context.statManager().addRateData("netDb.exploreKeySet", _exploreKeys.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queueForExploration(Collection<Hash> keys) {
|
public void queueForExploration(Collection<Hash> keys) {
|
||||||
if (!_initialized || !isMainDb())
|
if (!_initialized || isClientDb())
|
||||||
return;
|
return;
|
||||||
for (Iterator<Hash> iter = keys.iterator(); iter.hasNext() && _exploreKeys.size() < MAX_EXPLORE_QUEUE; ) {
|
for (Iterator<Hash> iter = keys.iterator(); iter.hasNext() && _exploreKeys.size() < MAX_EXPLORE_QUEUE; ) {
|
||||||
_exploreKeys.add(iter.next());
|
_exploreKeys.add(iter.next());
|
||||||
@@ -280,16 +296,19 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
* Cannot be restarted.
|
* Cannot be restarted.
|
||||||
*/
|
*/
|
||||||
public synchronized void shutdown() {
|
public synchronized void shutdown() {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("DB shutdown " + this);
|
||||||
_initialized = false;
|
_initialized = false;
|
||||||
if (!_context.commSystem().isDummy() && isMainDb() &&
|
if (!_context.commSystem().isDummy() && !isClientDb() &&
|
||||||
_context.router().getUptime() > ROUTER_INFO_EXPIRATION_FLOODFILL + 10*60*1000 + 60*1000) {
|
_context.router().getUptime() > ROUTER_INFO_EXPIRATION_FLOODFILL + 10*60*1000 + 60*1000) {
|
||||||
// expire inline before saving RIs in _ds.stop()
|
// expire inline before saving RIs in _ds.stop()
|
||||||
Job erj = new ExpireRoutersJob(_context, this);
|
Job erj = new ExpireRoutersJob(_context, this);
|
||||||
erj.runJob();
|
erj.runJob();
|
||||||
}
|
}
|
||||||
_context.jobQueue().removeJob(_elj);
|
_context.jobQueue().removeJob(_elj);
|
||||||
_context.jobQueue().removeJob(_erj);
|
if (_erj != null)
|
||||||
if (_kb != null)
|
_context.jobQueue().removeJob(_erj);
|
||||||
|
if (_kb != null && !isClientDb())
|
||||||
_kb.clear();
|
_kb.clear();
|
||||||
if (_ds != null)
|
if (_ds != null)
|
||||||
_ds.stop();
|
_ds.stop();
|
||||||
@@ -297,7 +316,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
_exploreKeys.clear();
|
_exploreKeys.clear();
|
||||||
if (_negativeCache != null)
|
if (_negativeCache != null)
|
||||||
_negativeCache.stop();
|
_negativeCache.stop();
|
||||||
if (isMainDb())
|
if (!isClientDb())
|
||||||
blindCache().shutdown();
|
blindCache().shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,29 +359,18 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the database is the main netDb. This is the one we're normally using
|
|
||||||
* if you're acting as a floodfill.
|
|
||||||
*
|
|
||||||
* @return true if _dbid == FNDS.MAIN_DBID
|
|
||||||
* @since 0.9.60
|
|
||||||
*/
|
|
||||||
protected boolean isMainDb() {
|
|
||||||
// This is a null check in disguise, don't use equals() here.
|
|
||||||
// FNDS.MAIN_DBID is always null.
|
|
||||||
if (_dbid == FloodfillNetworkDatabaseSegmentor.MAIN_DBID)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void startup() {
|
public synchronized void startup() {
|
||||||
_log.info("Starting up the kademlia network database");
|
if (_log.shouldInfo())
|
||||||
|
_log.info("Starting up the " + this);
|
||||||
RouterInfo ri = _context.router().getRouterInfo();
|
RouterInfo ri = _context.router().getRouterInfo();
|
||||||
String dbDir = _context.getProperty(PROP_DB_DIR, DEFAULT_DB_DIR);
|
String dbDir = _context.getProperty(PROP_DB_DIR, DEFAULT_DB_DIR);
|
||||||
_kb = new KBucketSet<Hash>(_context, ri.getIdentity().getHash(),
|
if (isClientDb())
|
||||||
|
_kb = _context.netDb().getKBuckets();
|
||||||
|
else
|
||||||
|
_kb = new KBucketSet<Hash>(_context, ri.getIdentity().getHash(),
|
||||||
BUCKET_SIZE, KAD_B, new RejectTrimmer<Hash>());
|
BUCKET_SIZE, KAD_B, new RejectTrimmer<Hash>());
|
||||||
try {
|
try {
|
||||||
if (isMainDb()) {
|
if (!isClientDb()) {
|
||||||
_ds = new PersistentDataStore(_context, dbDir, this);
|
_ds = new PersistentDataStore(_context, dbDir, this);
|
||||||
} else {
|
} else {
|
||||||
_ds = new TransientDataStore(_context);
|
_ds = new TransientDataStore(_context);
|
||||||
@@ -372,7 +380,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
}
|
}
|
||||||
_dbDir = dbDir;
|
_dbDir = dbDir;
|
||||||
_negativeCache = new NegativeLookupCache(_context);
|
_negativeCache = new NegativeLookupCache(_context);
|
||||||
if (isMainDb())
|
if (!isClientDb())
|
||||||
blindCache().startup();
|
blindCache().startup();
|
||||||
|
|
||||||
createHandlers();
|
createHandlers();
|
||||||
@@ -387,7 +395,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
|
|
||||||
//// expire some routers
|
//// expire some routers
|
||||||
// Don't run until after RefreshRoutersJob has run, and after validate() will return invalid for old routers.
|
// Don't run until after RefreshRoutersJob has run, and after validate() will return invalid for old routers.
|
||||||
if (!_context.commSystem().isDummy()) {
|
if (!isClientDb() && !_context.commSystem().isDummy()) {
|
||||||
boolean isFF = _context.getBooleanProperty(FloodfillMonitorJob.PROP_FLOODFILL_PARTICIPANT);
|
boolean isFF = _context.getBooleanProperty(FloodfillMonitorJob.PROP_FLOODFILL_PARTICIPANT);
|
||||||
long down = _context.router().getEstimatedDowntime();
|
long down = _context.router().getEstimatedDowntime();
|
||||||
long delay = (down == 0 || (!isFF && down > 30*60*1000) || (isFF && down > 24*60*60*1000)) ?
|
long delay = (down == 0 || (!isFF && down > 30*60*1000) || (isFF && down > 24*60*60*1000)) ?
|
||||||
@@ -398,7 +406,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!QUIET) {
|
if (!QUIET) {
|
||||||
if (isMainDb()) {
|
if (!isClientDb()) {
|
||||||
// fill the search queue with random keys in buckets that are too small
|
// fill the search queue with random keys in buckets that are too small
|
||||||
// Disabled since KBucketImpl.generateRandomKey() is b0rked,
|
// Disabled since KBucketImpl.generateRandomKey() is b0rked,
|
||||||
// and anyway, we want to search for a completely random key,
|
// and anyway, we want to search for a completely random key,
|
||||||
@@ -420,7 +428,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
_log.warn("Operating in quiet mode - not exploring or pushing data proactively, simply reactively");
|
_log.warn("Operating in quiet mode - not exploring or pushing data proactively, simply reactively");
|
||||||
_log.warn("This should NOT be used in production");
|
_log.warn("This should NOT be used in production");
|
||||||
}
|
}
|
||||||
if (isMainDb()) {
|
if (!isClientDb()) {
|
||||||
// periodically update and resign the router's 'published date', which basically
|
// periodically update and resign the router's 'published date', which basically
|
||||||
// serves as a version
|
// serves as a version
|
||||||
Job plrij = new PublishLocalRouterInfoJob(_context);
|
Job plrij = new PublishLocalRouterInfoJob(_context);
|
||||||
@@ -451,6 +459,10 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
* @param peersToIgnore can be null
|
* @param peersToIgnore can be null
|
||||||
*/
|
*/
|
||||||
public Set<Hash> findNearestRouters(Hash key, int maxNumRouters, Set<Hash> peersToIgnore) {
|
public Set<Hash> findNearestRouters(Hash key, int maxNumRouters, Set<Hash> peersToIgnore) {
|
||||||
|
if (isClientDb()) {
|
||||||
|
_log.warn("Subdb", new Exception("I did it"));
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
if (!_initialized) return Collections.emptySet();
|
if (!_initialized) return Collections.emptySet();
|
||||||
return new HashSet<Hash>(_peerSelector.selectNearest(key, maxNumRouters, peersToIgnore, _kb));
|
return new HashSet<Hash>(_peerSelector.selectNearest(key, maxNumRouters, peersToIgnore, _kb));
|
||||||
}
|
}
|
||||||
@@ -475,8 +487,16 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
}
|
}
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
/** get the hashes for all known routers */
|
/**
|
||||||
|
* Get the hashes for all known routers
|
||||||
|
*
|
||||||
|
* @return empty set if this is a client DB
|
||||||
|
*/
|
||||||
public Set<Hash> getAllRouters() {
|
public Set<Hash> getAllRouters() {
|
||||||
|
if (isClientDb()) {
|
||||||
|
_log.warn("Subdb", new Exception("I did it"));
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
if (!_initialized) return Collections.emptySet();
|
if (!_initialized) return Collections.emptySet();
|
||||||
Set<Map.Entry<Hash, DatabaseEntry>> entries = _ds.getMapEntries();
|
Set<Map.Entry<Hash, DatabaseEntry>> entries = _ds.getMapEntries();
|
||||||
Set<Hash> rv = new HashSet<Hash>(entries.size());
|
Set<Hash> rv = new HashSet<Hash>(entries.size());
|
||||||
@@ -493,6 +513,8 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
* both the kbuckets AND the data store, which was fine when the kbuckets held everything.
|
* both the kbuckets AND the data store, which was fine when the kbuckets held everything.
|
||||||
* But now that is probably not what you want.
|
* But now that is probably not what you want.
|
||||||
* Just return the count in the data store.
|
* Just return the count in the data store.
|
||||||
|
*
|
||||||
|
* @return 0 if this is a client DB
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getKnownRouters() {
|
public int getKnownRouters() {
|
||||||
@@ -502,6 +524,10 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
_kb.getAll(count);
|
_kb.getAll(count);
|
||||||
return count.size();
|
return count.size();
|
||||||
****/
|
****/
|
||||||
|
if (isClientDb()) {
|
||||||
|
_log.warn("Subdb", new Exception("I did it"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (_ds == null) return 0;
|
if (_ds == null) return 0;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
for (DatabaseEntry ds : _ds.getEntries()) {
|
for (DatabaseEntry ds : _ds.getEntries()) {
|
||||||
@@ -815,12 +841,16 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
* However, this may still fire off a lookup if the RI is present but expired (and will return null).
|
* However, this may still fire off a lookup if the RI is present but expired (and will return null).
|
||||||
* This may result in deadlocks.
|
* This may result in deadlocks.
|
||||||
* For true local only, use lookupLocallyWithoutValidation()
|
* For true local only, use lookupLocallyWithoutValidation()
|
||||||
|
*
|
||||||
|
* @return null always for client dbs
|
||||||
*/
|
*/
|
||||||
public RouterInfo lookupRouterInfoLocally(Hash key) {
|
public RouterInfo lookupRouterInfoLocally(Hash key) {
|
||||||
if (!_initialized) return null;
|
if (!_initialized) return null;
|
||||||
// Client netDb shouldn't have RI, search for RI in the floodfill netDb.
|
// Client netDb shouldn't have RI, search for RI in the floodfill netDb.
|
||||||
if (isClientDb())
|
if (isClientDb()) {
|
||||||
return _context.netDb().lookupRouterInfoLocally(key);
|
_log.warn("Subdb", new Exception("I did it"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
DatabaseEntry ds = _ds.get(key);
|
DatabaseEntry ds = _ds.get(key);
|
||||||
if (ds != null) {
|
if (ds != null) {
|
||||||
if (ds.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
|
if (ds.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
|
||||||
@@ -904,8 +934,11 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
* Stores to local db only.
|
* Stores to local db only.
|
||||||
* Overridden in FNDF to actually send to the floodfills.
|
* Overridden in FNDF to actually send to the floodfills.
|
||||||
* @throws IllegalArgumentException if the local router info is invalid
|
* @throws IllegalArgumentException if the local router info is invalid
|
||||||
|
* or if this is a client DB
|
||||||
*/
|
*/
|
||||||
public void publish(RouterInfo localRouterInfo) throws IllegalArgumentException {
|
public void publish(RouterInfo localRouterInfo) throws IllegalArgumentException {
|
||||||
|
if (isClientDb())
|
||||||
|
throw new IllegalArgumentException("RI publish to client DB");
|
||||||
if (!_initialized) return;
|
if (!_initialized) return;
|
||||||
if (_context.router().gracefulShutdownInProgress())
|
if (_context.router().gracefulShutdownInProgress())
|
||||||
return;
|
return;
|
||||||
@@ -1334,6 +1367,8 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
*/
|
*/
|
||||||
RouterInfo store(Hash key, RouterInfo routerInfo, boolean persist) throws IllegalArgumentException {
|
RouterInfo store(Hash key, RouterInfo routerInfo, boolean persist) throws IllegalArgumentException {
|
||||||
if (!_initialized) return null;
|
if (!_initialized) return null;
|
||||||
|
if (isClientDb())
|
||||||
|
throw new IllegalArgumentException("RI store to client DB");
|
||||||
|
|
||||||
RouterInfo rv;
|
RouterInfo rv;
|
||||||
try {
|
try {
|
||||||
@@ -1435,7 +1470,8 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
DatabaseEntry o = _ds.get(dbEntry);
|
DatabaseEntry o = _ds.get(dbEntry);
|
||||||
if (o == null) {
|
if (o == null) {
|
||||||
// if we dont know the key, lets make sure it isn't a now-dead peer
|
// if we dont know the key, lets make sure it isn't a now-dead peer
|
||||||
_kb.remove(dbEntry);
|
if (_kb != null)
|
||||||
|
_kb.remove(dbEntry);
|
||||||
_context.peerManager().removeCapabilities(dbEntry);
|
_context.peerManager().removeCapabilities(dbEntry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1451,7 +1487,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
// are any updates
|
// are any updates
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("Dropping a lease: " + dbEntry);
|
_log.info("Dropping a lease: " + dbEntry);
|
||||||
if (isMainDb()) {
|
if (!isClientDb()) {
|
||||||
_ds.remove(dbEntry, false);
|
_ds.remove(dbEntry, false);
|
||||||
} else {
|
} else {
|
||||||
// if this happens it's because we're a TransientDataStore instead,
|
// if this happens it's because we're a TransientDataStore instead,
|
||||||
@@ -1471,6 +1507,10 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
* Do NOT use for leasesets.
|
* Do NOT use for leasesets.
|
||||||
*/
|
*/
|
||||||
void dropAfterLookupFailed(Hash peer) {
|
void dropAfterLookupFailed(Hash peer) {
|
||||||
|
if (isClientDb()) {
|
||||||
|
_log.warn("Subdb", new Exception("I did it"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
_context.peerManager().removeCapabilities(peer);
|
_context.peerManager().removeCapabilities(peer);
|
||||||
_negativeCache.cache(peer);
|
_negativeCache.cache(peer);
|
||||||
_kb.remove(peer);
|
_kb.remove(peer);
|
||||||
@@ -1558,9 +1598,17 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
return leases;
|
return leases;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** public for NetDbRenderer in routerconsole */
|
/**
|
||||||
|
* Public for NetDbRenderer in routerconsole
|
||||||
|
*
|
||||||
|
* @return empty set if this is a client DB
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<RouterInfo> getRouters() {
|
public Set<RouterInfo> getRouters() {
|
||||||
|
if (isClientDb()) {
|
||||||
|
_log.warn("Subdb", new Exception("I did it"));
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
if (!_initialized) return null;
|
if (!_initialized) return null;
|
||||||
Set<RouterInfo> routers = new HashSet<RouterInfo>();
|
Set<RouterInfo> routers = new HashSet<RouterInfo>();
|
||||||
for (DatabaseEntry o : getDataStore().getEntries()) {
|
for (DatabaseEntry o : getDataStore().getEntries()) {
|
||||||
@@ -1654,6 +1702,8 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void renderStatusHTML(Writer out) throws IOException {
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
|
if (_kb == null)
|
||||||
|
return;
|
||||||
out.write(_kb.toString().replace("\n", "<br>\n"));
|
out.write(_kb.toString().replace("\n", "<br>\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1662,7 +1712,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (isMainDb())
|
if (!isClientDb())
|
||||||
return "Main NetDB";
|
return "Main NetDB";
|
||||||
return "Client NetDB " + _dbid.toBase64();
|
return "Client NetDB " + _dbid.toBase64();
|
||||||
}
|
}
|
||||||
|
@@ -390,10 +390,7 @@ class SearchJob extends JobImpl {
|
|||||||
Hash rkey = getContext().routingKeyGenerator().getRoutingKey(key);
|
Hash rkey = getContext().routingKeyGenerator().getRoutingKey(key);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug(getJobId() + ": Current routing key for " + key + ": " + rkey);
|
_log.debug(getJobId() + ": Current routing key for " + key + ": " + rkey);
|
||||||
if (_facade.isClientDb())
|
return _peerSelector.selectNearestExplicit(rkey, numClosest, alreadyChecked, _facade.getKBuckets());
|
||||||
return getContext().netDb().getPeerSelector().selectNearestExplicit(rkey, numClosest, alreadyChecked, _facade.getKBuckets());
|
|
||||||
else
|
|
||||||
return _peerSelector.selectNearestExplicit(rkey, numClosest, alreadyChecked, _facade.getKBuckets());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -89,7 +89,7 @@ abstract class StoreJob extends JobImpl {
|
|||||||
_onFailure = onFailure;
|
_onFailure = onFailure;
|
||||||
_timeoutMs = timeoutMs;
|
_timeoutMs = timeoutMs;
|
||||||
_expiration = context.clock().now() + timeoutMs;
|
_expiration = context.clock().now() + timeoutMs;
|
||||||
_peerSelector = facade.createPeerSelector();
|
_peerSelector = facade.getPeerSelector();
|
||||||
if (data.isLeaseSet()) {
|
if (data.isLeaseSet()) {
|
||||||
_connectChecker = null;
|
_connectChecker = null;
|
||||||
_connectMask = 0;
|
_connectMask = 0;
|
||||||
@@ -318,18 +318,10 @@ abstract class StoreJob extends JobImpl {
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
private List<Hash> getClosestFloodfillRouters(Hash key, int numClosest, Set<Hash> alreadyChecked) {
|
private List<Hash> getClosestFloodfillRouters(Hash key, int numClosest, Set<Hash> alreadyChecked) {
|
||||||
List<Hash> rv;
|
|
||||||
Hash rkey = getContext().routingKeyGenerator().getRoutingKey(key);
|
Hash rkey = getContext().routingKeyGenerator().getRoutingKey(key);
|
||||||
KBucketSet<Hash> ks = _facade.getKBuckets();
|
KBucketSet<Hash> ks = _facade.getKBuckets();
|
||||||
if (ks == null) return new ArrayList<Hash>();
|
if (ks == null) return new ArrayList<Hash>();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
List<Hash> rv = ((FloodfillPeerSelector)_peerSelector).selectFloodfillParticipants(rkey, numClosest, alreadyChecked, ks);
|
||||||
_log.debug(getJobId() + "(dbid: " + _facade._dbid + "): Selecting Floodfill Participants");
|
|
||||||
if (_facade.isClientDb()) {
|
|
||||||
FloodfillPeerSelector ffNetDbPS = (FloodfillPeerSelector)getContext().netDb().getPeerSelector();
|
|
||||||
rv = ffNetDbPS.selectFloodfillParticipants(rkey, numClosest, alreadyChecked, ks);
|
|
||||||
} else {
|
|
||||||
rv = ((FloodfillPeerSelector)_peerSelector).selectFloodfillParticipants(rkey, numClosest, alreadyChecked, ks);
|
|
||||||
}
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -138,11 +138,7 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
|
|||||||
return;
|
return;
|
||||||
if (!ri.isValid())
|
if (!ri.isValid())
|
||||||
return;
|
return;
|
||||||
RouterInfo oldri = null;
|
RouterInfo oldri = _context.netDb().lookupRouterInfoLocally(key);
|
||||||
if (_client != null)
|
|
||||||
oldri = _context.clientNetDb(_client).lookupRouterInfoLocally(key);
|
|
||||||
else
|
|
||||||
oldri = _context.netDb().lookupRouterInfoLocally(key);
|
|
||||||
// only update if RI is newer and non-ff
|
// only update if RI is newer and non-ff
|
||||||
if (oldri != null && oldri.getPublished() < ri.getPublished() &&
|
if (oldri != null && oldri.getPublished() < ri.getPublished() &&
|
||||||
!FloodfillNetworkDatabaseFacade.isFloodfill(ri)) {
|
!FloodfillNetworkDatabaseFacade.isFloodfill(ri)) {
|
||||||
|
Reference in New Issue
Block a user