java.lang.Object
net.i2p.router.JobImpl
net.i2p.router.networkdb.kademlia.FloodfillVerifyStoreJob
- All Implemented Interfaces:
Job
Two-phase floodfill store verification.
Phase 1 queries the peer we stored to, confirming it still holds a fresh entry (store acceptance that outlives the DSM reply). Phase 2 waits longer for the flood to propagate, then queries a different floodfill. A missing or stale reply in phase 2 is retried once against the same peer before blaming the store and flooding again — a single under-aged sample must not condemn a flood that is merely in flight.
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static enumResult of querying a second floodfill (phase 2).(package private) static enumResult of querying the store peer (phase 1).private classHandles a verification reply.private classMatches the reply to one verification query.private classHandles a verification reply timeout.Field Summary
FieldsModifier and TypeFieldDescriptionprivate intFloodfills queried so far.private final BanLoggerRecords why routers were banned.private final HashThe client that published the data.private final longWhen this verify job was created (store success time).private longWhen the verified data expires.private final FloodfillNetworkDatabaseFacadeThe floodfill netdb we serve.private booleanOne same-peer flood-check retry already spent.Floodfills not to query again.private final MaskedIPSetMasked IPs of floodfills already tried.private final booleanTrue if verifying an LS2 lease set.private final booleanTrue if verifying a router info.private final HashThe key being verified.private final LogLogger for the verification job.private intCurrent phase of the verification.private final longDelay before the first verification phase.private final longDelay before the second verification phase.private final longWhen the client published the data.private booleanKeep the current phase-2 target instead of picking a new one.private final longDelay before retrying a query.private longWhen the current query was sent.private final HashThe floodfill the query was sent to.private HashThe floodfill currently holding the data.private final intThe message type used for the query.private MessageWrapper.WrappedMessageThe reply being verified.private static final intDefault delay before the first phase.private static final intDefault phase 2 delay for lease sets.private static final intDefault phase 2 delay for router infos.private static final intDefault delay before a retry.private static final intLeading address bytes that count as a close IP.private static final intFloodfills queried for one verification.private static final intPhase 2: confirm a different floodfill received the flood.private static final intPhase 1: confirm the store peer still has the entry.private static final StringConfig key for the first phase delay.private static final StringConfig key for the lease set phase 2 delay.private static final StringConfig key for the router info phase 2 delay.private static final StringConfig key for the query retry delay.private static final long[]Rate stat periods for the verification statistics.private static final intTotal time allowed for one verification.Constructor Summary
ConstructorsConstructorDescriptionFloodfillVerifyStoreJob(RouterContext ctx, Hash key, Hash client, long published, int type, Hash sentTo, Set<Hash> toSkip, FloodfillNetworkDatabaseFacade facade) Delay, then confirm the store peer still holds the entry; after a longer delay, confirm a different floodfill got the flood.Method Summary
Modifier and TypeMethodDescriptionprivate voidbanBadEntry(long delayMs) Ban a peer that returned an entry with a bad signature, then fail.private DatabaseLookupMessagebuildLookup(TunnelInfo replyTunnelInfo) Builds the database lookup message for verification.private static longclampDelay(long configured, int fallback) Reject nonsensical delay properties so a bad config cannot busy-loop.(package private) static FloodfillVerifyStoreJob.FloodCheckResultclassifyFloodCheck(boolean isStoreMsg, boolean entryFresh) Classify a phase-2 reply from the alternate floodfill.(package private) static FloodfillVerifyStoreJob.StoreCheckResultclassifyStoreCheck(boolean isStoreMsg, boolean entryFresh) Classify a phase-1 reply from the store peer.private voidLeave the store-peer check and schedule the flood check at created + phase2 delay (immediately if that time already passed).private voidfailFloodCheck(FloodfillVerifyStoreJob.FloodCheckResult result, long delayMs) Phase 2 still missing or stale after any retry — blame store peer for not flooding and the verify peer for not having it, then resend.private voidfailStoreCheck(FloodfillVerifyStoreJob.StoreCheckResult result, long delayMs) Store-peer said the entry is missing or stale — the store itself failed.private voidRelease the verify-in-progress slot for this key.getName()Descriptive name of the task.private voidhandleSearchReply(DatabaseSearchReplyMessage dsrm, long delayMs) Handle a search reply (peer does not have the key) for the current phase.private voidhandleStoreMessage(DatabaseEntry entry, long delayMs) Handle a store message (entry present) for the current phase.private booleanisFresh(DatabaseEntry entry) Is the entry at least as new as what we published?(package private) static longphase2StartTime(long createdMs, long phase2DelayMs) Absolute time phase 2 may start, relative to verify-job creation.private HashPick a responsive floodfill close to the key, but not the one we sent to.private voidresend()The netDb store failed to verify, so resend it to a random floodfill peer Fixme - since we now store closest-to-the-key, this is likely to store to the very same ff as last time, until the stats get bad enough to switch.voidrunJob()Run the current phase: first ask the peer we stored to, then a different floodfill after the flood-check delay has elapsed.private voidRe-query the same phase-2 peer after the retry delay (one shot).(package private) static booleanshouldRetryFloodCheck(FloodfillVerifyStoreJob.FloodCheckResult result, boolean alreadyRetried) Whether to re-query the same phase-2 peer once before blaming.(package private) static booleanWhether phase 1 proved the store failed (missing or stale at the peer we stored to).private voidsucceedFloodCheck(long delayMs) Full success: a different floodfill holds a fresh copy — the flood worked.Methods inherited from class JobImpl
dropped, getContext, getJobId, getMadeReadyOn, getTiming, madeReady, requeue, toStringModifier and TypeMethodDescriptionvoiddropped()Default implementation does nothing.final RouterContextThe router context that this job belongs to.longgetJobId()The unique job ID for this job.longThe timestamp when this job was last made ready for execution.The timing object for this job.voidmadeReady(long now) For JobQueue only, not for external use.protected voidrequeue(long delayMs) Requeue this job to run after the specified delay.toString()
Field Details
_log
Logger for the verification job._banLogger
Records why routers were banned._key
The key being verified._client
The client that published the data._target
The floodfill currently holding the data._sentTo
The floodfill the query was sent to._facade
The floodfill netdb we serve._expiration
private long _expirationWhen the verified data expires._sendTime
private long _sendTimeWhen the current query was sent._attempted
private int _attemptedFloodfills queried so far._published
private final long _publishedWhen the client published the data._type
private final int _typeThe message type used for the query._isRouterInfo
private final boolean _isRouterInfoTrue if verifying a router info._isLS2
private final boolean _isLS2True if verifying an LS2 lease set._wrappedMessage
The reply being verified._ignore
_ipSet
Masked IPs of floodfills already tried.PHASE_STORE_CHECK
private static final int PHASE_STORE_CHECKPhase 1: confirm the store peer still has the entry.- See Also:
PHASE_FLOOD_CHECK
private static final int PHASE_FLOOD_CHECKPhase 2: confirm a different floodfill received the flood.- See Also:
_phase
private int _phaseCurrent phase of the verification._floodRetried
private boolean _floodRetriedOne same-peer flood-check retry already spent._requerySame
private boolean _requerySameKeep the current phase-2 target instead of picking a new one._created
private final long _createdWhen this verify job was created (store success time)._phase1DelayMs
private final long _phase1DelayMsDelay before the first verification phase._phase2DelayMs
private final long _phase2DelayMsDelay before the second verification phase._retryDelayMs
private final long _retryDelayMsDelay before retrying a query.PROP_PHASE1_DELAY
Config key for the first phase delay.- See Also:
PROP_PHASE2_DELAY_LS
Config key for the lease set phase 2 delay.- See Also:
PROP_PHASE2_DELAY_RI
Config key for the router info phase 2 delay.- See Also:
PROP_RETRY_DELAY
Config key for the query retry delay.- See Also:
DEFAULT_PHASE1_DELAY
private static final int DEFAULT_PHASE1_DELAYDefault delay before the first phase.- See Also:
DEFAULT_PHASE2_DELAY_LS
private static final int DEFAULT_PHASE2_DELAY_LSDefault phase 2 delay for lease sets.- See Also:
DEFAULT_PHASE2_DELAY_RI
private static final int DEFAULT_PHASE2_DELAY_RIDefault phase 2 delay for router infos.- See Also:
DEFAULT_RETRY_DELAY
private static final int DEFAULT_RETRY_DELAYDefault delay before a retry.- See Also:
VERIFY_TIMEOUT
private static final int VERIFY_TIMEOUTTotal time allowed for one verification.- See Also:
MAX_PEERS_TO_TRY
private static final int MAX_PEERS_TO_TRYFloodfills queried for one verification.- See Also:
IP_CLOSE_BYTES
private static final int IP_CLOSE_BYTESLeading address bytes that count as a close IP.- See Also:
RATES
private static final long[] RATESRate stat periods for the verification statistics.
Constructor Details
FloodfillVerifyStoreJob
public FloodfillVerifyStoreJob(RouterContext ctx, Hash key, Hash client, long published, int type, Hash sentTo, Set<Hash> toSkip, FloodfillNetworkDatabaseFacade facade) Delay, then confirm the store peer still holds the entry; after a longer delay, confirm a different floodfill got the flood.- Parameters:
ctx- the router contextkey- the hash of the store entry being verifiedclient- generally the same as key, unless encrypted LS2; non-nullpublished- getDate() for RI or LS1, getPublished() for LS2type- the database entry typesentTo- who to give the credit or blame to, can be nulltoSkip- don't query any of these peers, may be nullfacade- the floodfill network database facade
Method Details
classifyStoreCheck
static FloodfillVerifyStoreJob.StoreCheckResult classifyStoreCheck(boolean isStoreMsg, boolean entryFresh) Classify a phase-1 reply from the store peer.- Parameters:
isStoreMsg- true if the reply was a DatabaseStoreMessage, false for a search replyentryFresh- true if the entry's date/published is at least what we stored- Returns:
- the store-check result
storeCheckFailed
Whether phase 1 proved the store failed (missing or stale at the peer we stored to). An indeterminate result must not blame the store peer.- Parameters:
result- phase-1 classification- Returns:
- true if verify should fail immediately and resend
classifyFloodCheck
static FloodfillVerifyStoreJob.FloodCheckResult classifyFloodCheck(boolean isStoreMsg, boolean entryFresh) Classify a phase-2 reply from the alternate floodfill.- Parameters:
isStoreMsg- true if the reply was a DatabaseStoreMessage, false for a search replyentryFresh- true if the entry's date/published is at least what we stored- Returns:
- the flood-check result
shouldRetryFloodCheck
static boolean shouldRetryFloodCheck(FloodfillVerifyStoreJob.FloodCheckResult result, boolean alreadyRetried) Whether to re-query the same phase-2 peer once before blaming. Missing and stale are the only retryable outcomes, and only on the first miss.- Parameters:
result- phase-2 classificationalreadyRetried- true if a same-peer retry was already performed- Returns:
- true to schedule a retry against the same target
phase2StartTime
static long phase2StartTime(long createdMs, long phase2DelayMs) Absolute time phase 2 may start, relative to verify-job creation.- Parameters:
createdMs- when the verify job was createdphase2DelayMs- configured flood-check delay- Returns:
- epoch ms at which the flood check may begin
clampDelay
private static long clampDelay(long configured, int fallback) Reject nonsensical delay properties so a bad config cannot busy-loop.- Parameters:
configured- value from the router configfallback- default to use when configured is out of range- Returns:
- a delay between 0 and 2 minutes
getName
runJob
public void runJob()Run the current phase: first ask the peer we stored to, then a different floodfill after the flood-check delay has elapsed.Phase 1 failure (missing/stale at the store peer) resends immediately. Phase 2 missing/stale retries the same peer once, then resends.
enterFloodCheck
private void enterFloodCheck()Leave the store-peer check and schedule the flood check at created + phase2 delay (immediately if that time already passed). Does not release the verify-in-progress slot.scheduleFloodRetry
private void scheduleFloodRetry()Re-query the same phase-2 peer after the retry delay (one shot). Does not release the verify-in-progress slot.pickTarget
Pick a responsive floodfill close to the key, but not the one we sent to.- Returns:
- the floodfill to verify against; falls back to the floodfill we already stored to when no other peer is available
buildLookup
Builds the database lookup message for verification.- Parameters:
replyTunnelInfo- the tunnel to receive the reply on, source of the reply tunnel id and the From field- Returns:
- non-null
isFresh
Is the entry at least as new as what we published?- Parameters:
entry- entry the floodfill returned, compared against what we published- Returns:
- true if fresh enough to count as success
finishVerify
private void finishVerify()Release the verify-in-progress slot for this key.banBadEntry
private void banBadEntry(long delayMs) Ban a peer that returned an entry with a bad signature, then fail.- Parameters:
delayMs- reply latency for stats
failStoreCheck
Store-peer said the entry is missing or stale — the store itself failed. Blame only the store peer, then resend. No alternate peer was queried yet.- Parameters:
result- never FRESH or INDETERMINATEdelayMs- reply latency for stats
succeedFloodCheck
private void succeedFloodCheck(long delayMs) Full success: a different floodfill holds a fresh copy — the flood worked.- Parameters:
delayMs- reply latency for stats
failFloodCheck
Phase 2 still missing or stale after any retry — blame store peer for not flooding and the verify peer for not having it, then resend.- Parameters:
result- FRESH is not a failuredelayMs- reply latency for stats
handleSearchReply
Handle a search reply (peer does not have the key) for the current phase.- Parameters:
dsrm- the search replydelayMs- reply latency for stats
handleStoreMessage
Handle a store message (entry present) for the current phase.- Parameters:
entry- the entry from the replydelayMs- reply latency for stats
resend
private void resend()The netDb store failed to verify, so resend it to a random floodfill peer Fixme - since we now store closest-to-the-key, this is likely to store to the very same ff as last time, until the stats get bad enough to switch. Therefore, pass the failed ff through as a don't-store-to. Let's also add the one we just tried to verify with, as they could be a pair of no-flooders. So at least we'll try THREE ffs round-robin if things continue to fail...