java.lang.Object
net.i2p.router.networkdb.kademlia.TransientDataStore
net.i2p.router.networkdb.kademlia.PersistentDataStore
- All Implemented Interfaces:
DataStore
Persistent network database storage with disk I/O and memory management.
Writes RouterInfo entries to disk as received and periodically scans for unknown entries to load into memory. Newly discovered routers are automatically added to the routing table. Implements both flat and hierarchical directory structures for efficient file organization and access.
Public only for access to static methods by startup classes.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate classSchedules a delayed force disconnect for a banned peer.private classThis was mostly for manual reseeding, i.e.private classReads a single RouterInfo file from disk and stores it in memory.private static classPre-computed classification flags for a RouterInfo being written.private classThread writing the store changes to disk.Field Summary
Modifier and TypeFieldDescriptionprivate final BanLoggerBan logger.private final FileDatabase directory.private final KademliaNetworkDatabaseFacadeReference to the Kademlia facade for netdb operations.private final booleanFlat mode flag.private booleanInitialized flag.private final intNetwork ID.private final PersistentDataStore.ReadJobRead job that loads the database from disk.private final PersistentDataStore.WriterBackground thread for persisting RouterInfo files to disk.private static final StringBase64 alphabet used for directory naming.private intCached count of the router info entries.(package private) static final StringDirectory prefix for netDb files.private longWhen the cached count was taken.private static final intMax router files to load during startup initialization.private static final StringMinimum router version to persist to disk.private static final StringConfig property to enable flat directory layout.private static final long[]Stat rate periods for NetDb write metrics.private static final intInitial delay before first netdb scan.private static final intInterval between periodic netdb rescans.private static final longHow long the cached count stays valid.static final FileFilterFile filter for RouterInfo files.private static final StringPrefix for RouterInfo filenames on disk.private static final StringSuffix for RouterInfo filenames on disk.private static final longInterval between batch disk write cycles.private static final intHow many files to write every 10 minutes.Fields inherited from class TransientDataStore
_context, _logModifier and TypeFieldDescriptionprotected final RouterContextRouter context this store was constructed with.protected final LogLogger for this data store.Constructor Summary
ConstructorsConstructorDescriptionPersistentDataStore(RouterContext ctx, String dbDir, KademliaNetworkDatabaseFacade facade) Creates a new persistent data store.Method Summary
Modifier and TypeMethodDescriptionprivate booleancheckSpoofAndBan(Hash key, RouterInfo ri, PersistentDataStore.RiFlags f) Detect IP spoofing and apply ban decisions for non-storeable peers.intCount the number of RouterInfo files currently stored on disk.private PersistentDataStore.RiFlagsextractRiFlags(Hash key, RouterInfo ri) Extract classification flags from raw RouterInfo data.booleanforcePut(Hash key, DatabaseEntry data) Unconditionally store, bypassing all newer/older checks.The entry stored for the key, or null if not found.Prepare for having only a partial set in memory and the rest on disk.private FileResolve and prepare the database directory, creating subdirs if needed.private static HashExtract hash from a prefixed+suffixed filename.private static longgetPublishDate(DatabaseEntry data) Returns the publish date of an entry.static FilegetRouterInfoFile(RouterContext ctx, Hash hash) The persistent RI file for a hash.(package private) static HashgetRouterInfoHash(String filename) Package private for installer BundleRouterInfos.private StringgetRouterInfoName(Hash hash) Builds the router info file name for a hash.booleanWhether the data store has completed initial loading, either because the read job finished or because enough RouterInfos have been loaded for the netdb to be usable.static booleanCheck if the router is in a graceful or hard shutdown state.private static voidMigrate from one-level to two-level directory structure.private voidAt startup, this method scans existing RouterInfos and removes any categorized as slow, determined by the total number stored on disk.booleanput(Hash key, DatabaseEntry data) Store the entry and persist it to disk.booleanput(Hash key, DatabaseEntry data, boolean persist) Store the entry and optionally persist it to disk.Remove from memory and queue the file for disk deletion.Remove from memory and optionally queue disk deletion.private voidremoveFile(Hash key, File dir) Delete the RouterInfo file for a hash, if it is present.voidrescan()Trigger an immediate rescan if the store is initialized.private static booleanShould this RouterInfo be persisted to disk? Returns true only for reachable, non-degraded peers with sufficient bandwidth.voidstop()Stop the writer thread and clear the in-memory store.private static voidMigrate from two-level to one-level directory structure.private voidwrite(Hash key, DatabaseEntry data) Persist a single RouterInfo to disk, applying spoof/ban checks.private booleanwriteRiFile(Hash key, DatabaseEntry data, File dbFile) Write a single RouterInfo to disk.Methods inherited from class TransientDataStore
countLeaseSets, getEntries, getKeys, getMapEntries, isKnown, size, toString
Field Details
_dbDir
Database directory._facade
Reference to the Kademlia facade for netdb operations._writer
Background thread for persisting RouterInfo files to disk._readJob
Read job that loads the database from disk._banLogger
Ban logger._initialized
private volatile boolean _initializedInitialized flag._flat
private final boolean _flatFlat mode flag._networkID
private final int _networkIDNetwork ID.READ_DELAY
private static final int READ_DELAYInitial delay before first netdb scan.- See Also:
READ_INTERVAL
private static final int READ_INTERVALInterval between periodic netdb rescans.- See Also:
PROP_FLAT
Config property to enable flat directory layout.- See Also:
DIR_PREFIX
B64
Base64 alphabet used for directory naming.- See Also:
MAX_ROUTERS_INIT
private static final int MAX_ROUTERS_INITMax router files to load during startup initialization.- See Also:
MIN_VERSION
Minimum router version to persist to disk.- See Also:
RATES
private static final long[] RATESStat rate periods for NetDb write metrics.WRITE_LIMIT
private static final int WRITE_LIMITHow many files to write every 10 minutes. Doesn't make sense to limit it, they just back up in the queue hogging memory.- See Also:
WRITE_DELAY
private static final long WRITE_DELAYInterval between batch disk write cycles.- See Also:
cachedRiCount
private int cachedRiCountCached count of the router info entries.lastRiCountTime
private long lastRiCountTimeWhen the cached count was taken.RI_CACHE_TTL
private static final long RI_CACHE_TTLHow long the cached count stays valid.- See Also:
ROUTERINFO_PREFIX
Prefix for RouterInfo filenames on disk.- See Also:
ROUTERINFO_SUFFIX
Suffix for RouterInfo filenames on disk.- See Also:
RI_FILTER
File filter for RouterInfo files.
Constructor Details
PersistentDataStore
public PersistentDataStore(RouterContext ctx, String dbDir, KademliaNetworkDatabaseFacade facade) throws IOException Creates a new persistent data store.- Parameters:
ctx- the router contextdbDir- directory name resolved under the router directoryfacade- the network database facade- Throws:
IOException- if the database directory cannot be created or accessed
Method Details
isInitialized
public boolean isInitialized()Whether the data store has completed initial loading, either because the read job finished or because enough RouterInfos have been loaded for the netdb to be usable.- Specified by:
isInitializedin interfaceDataStore- Overrides:
isInitializedin classTransientDataStore- Returns:
- true if the data store has completed initial loading
stop
public void stop()Stop the writer thread and clear the in-memory store.The read job is not stopped: it is a recurring SimpleTimer2 event with no cancellation flag, so it keeps rescanning until the router's graceful shutdown begins and runJob() returns early. A rescan after this point re-reads an empty store and is harmless, but it is an open question whether
stop()should cancel the reader outright.- Specified by:
stopin interfaceDataStore- Overrides:
stopin classTransientDataStore
rescan
public void rescan()Trigger an immediate rescan if the store is initialized.- Specified by:
rescanin interfaceDataStore- Overrides:
rescanin classTransientDataStore
get
The entry stored for the key, or null if not found.- Specified by:
getin interfaceDataStore- Overrides:
getin classTransientDataStore- Parameters:
key- the key to look up- Returns:
- the entry or null if not found
get
Prepare for having only a partial set in memory and the rest on disk.- Specified by:
getin interfaceDataStore- Overrides:
getin classTransientDataStore- Parameters:
key- the hash key to look uppersist- if false, call super only, don't access disk- Returns:
- the database entry, or null if not found
remove
Remove from memory and queue the file for disk deletion.- Specified by:
removein interfaceDataStore- Overrides:
removein classTransientDataStore- Parameters:
key- the key to remove- Returns:
- the removed entry, or null if none was stored
remove
Remove from memory and optionally queue disk deletion.- Specified by:
removein interfaceDataStore- Overrides:
removein classTransientDataStore- Parameters:
key- the key to removepersist- if false, call super only, don't access disk- Returns:
- the removed entry, or null if none was stored
put
Store the entry and persist it to disk. Only RouterInfos are written; LeaseSets stay in memory.- Specified by:
putin interfaceDataStore- Overrides:
putin classTransientDataStore- Parameters:
key- the key to store underdata- the entry to store- Returns:
- true if the entry was stored
put
Store the entry and optionally persist it to disk. Only RouterInfos are written; LeaseSets stay in memory.- Specified by:
putin interfaceDataStore- Overrides:
putin classTransientDataStore- Parameters:
key- the key to store underdata- the entry to store, null to failpersist- if false, call super only, don't access disk- Returns:
- true if the entry was stored
forcePut
Unconditionally store, bypassing all newer/older checks. Persists for RouterInfos only.- Specified by:
forcePutin interfaceDataStore- Overrides:
forcePutin classTransientDataStore- Parameters:
key- non-nulldata- non-null- Returns:
- true if the entry was stored in the Kademlia structure
extractRiFlags
Extract classification flags from raw RouterInfo data.- Parameters:
key- the hash of the router, used for the banlist checksri- the router info to classify- Returns:
- a RiFlags snapshot of the version, capability, bandwidth, IP and banlist state used by the store decision
shouldStoreRi
Should this RouterInfo be persisted to disk? Returns true only for reachable, non-degraded peers with sufficient bandwidth.- Parameters:
f- the pre-computed classification flags for the peer- Returns:
- false if the RI should be skipped or deleted
checkSpoofAndBan
Detect IP spoofing and apply ban decisions for non-storeable peers. Called only for peers that failedshouldStoreRi(RiFlags)and are not banned.- Parameters:
key- the hash of the peer being checkedri- the peer's router info, used for the spoof check and ban loggingf- the pre-computed classification flags for the peer- Returns:
- true if the on-disk file should be deleted
writeRiFile
Write a single RouterInfo to disk. Skips if the file is already current.- Parameters:
key- the hash of the router, used for the log messagesdata- the RouterInfo entry to serializedbFile- the destination file; skipped when its last-modified time is already at or after the entry's publish date- Returns:
- true if the write failed (file should be deleted)
- Throws:
IOException- if the output stream cannot be opened or the data cannot be written
write
Persist a single RouterInfo to disk, applying spoof/ban checks.- Parameters:
key- the hash of the router to writedata- the entry to write; a null entry is ignored
countStoredRIs
public int countStoredRIs()Count the number of RouterInfo files currently stored on disk. This includes files in subdirectories if not using flat mode.- Returns:
- number of RI files on disk
getPublishDate
Returns the publish date of an entry.- Parameters:
data- the entry to read- Returns:
- the publish date
purgeSlowRouters
private void purgeSlowRouters()At startup, this method scans existing RouterInfos and removes any categorized as slow, determined by the total number stored on disk.getDbDir
Resolve and prepare the database directory, creating subdirs if needed.- Parameters:
dbDir- the database directory path, relative to the router directory- Returns:
- the directory, created and verified readable and writable
- Throws:
IOException- if the directory cannot be created, is not a directory, or is not readable or writable
unmigrate
Migrate from two-level to one-level directory structure.- Parameters:
dbdir- the NetDb root directory whose subdirs are emptied
migrate
getRouterInfoName
getRouterInfoFile
The persistent RI file for a hash. This is available before the netdb subsystem is running, so we can delete our old RI.- Parameters:
ctx- the router contexthash- the router hash- Returns:
- non-null, should be absolute, does not necessarily exist
getRouterInfoHash
Package private for installer BundleRouterInfos.- Parameters:
filename- the routerinfo filename, including the prefix and suffix added bygetRouterInfoFile(RouterContext, Hash)- Returns:
- the hash encoded in the name, or null if the name is malformed or the key does not decode
getHash
Extract hash from a prefixed+suffixed filename.- Parameters:
filename- the file name as stored on diskprefix- the leading part to strip, e.g. "routerInfo-"suffix- the trailing part to strip, e.g. ".dat"- Returns:
- the decoded hash, or null if the name is malformed or the embedded base64 key does not decode
removeFile
isShuttingDown
Check if the router is in a graceful or hard shutdown state.- Parameters:
ctx- the router context- Returns:
- true if shutdown is in progress