java.lang.Object
i2p.susi.webmail.PersistentMailCache
Manages persistent on-disk email cache with custom compressed format. This is a custom format with subdirectories, gzipped files, and the encoded UIDL in the file name. We store either the headers or the full message. No, it is not Maildir format but we could add Maildir-style status suffixes (e.g. ":2.SR") later. Exporting to a Maildir format would be just ungzipping each file to a flat directory. This class should only be accessed from
MailCache.Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static classLoad files from in, add mail to out.Field Summary
Modifier and TypeFieldDescriptionprivate final FileDirectory for the drafts' attachments.private final FileDirectory holding the cached mail.private final I2PAppContextThe app context.private final booleanTrue for the drafts folder cache.private final ObjectLock for the cache state.private static final ConcurrentHashMap<String, Object> One lock for each user in the whole JVM, to protect against multiple sessions.private final LogLogger for the mail cache.private static final StringAlphabet of the base64 mail uids.private static final StringPrefix of the cache file names.static final StringDirectory holding draft attachment files, created only by the drafts cache.private static final StringName of the cache subdirectory.static final StringDirectory beside the cache holding imported .eml files, debug only.private static final StringPrefix of the per-user directory names.private static final StringName of the mail data directory.private static final StringPrefix of the mail file names.private static final StringSuffix of the full-message cache files.private static final StringSuffix of the header-only cache files.Constructor Summary
ConstructorsConstructorDescriptionPersistentMailCache(I2PAppContext ctx, String host, int port, String user, String pass, String folder) Use the params to generate a unique directory name.Method Summary
Modifier and TypeMethodDescriptionvoiddeleteMail(Mail mail) Delete both the full-message and the header-only file for this mail.voiddeleteMail(String uidl) Delete both the full-message and the header-only file for this uidl.Where draft attachments are stored, which only the drafts cache creates.private FileBuilds the cache file name for a uid.getFullBuffer(String uidl) For reading or writing a new full mail (NOT headers only).getFullFile(String uidl) The gzipped full-message file for this uidl.getHeaderFile(String uidl) The gzipped header-only file for this uidl.private static ObjectReturns the lock shared by one account.booleanFetch any needed data from disk, filling in the header, or the body if that is what was asked for and only a header file is on disk.Fetch all mails from disk, naming the folder in the completion log so a reader can tell which mailbox the counts belong to.private voidFor debugging.private static MailThis is for the initial load only.private booleanlocked_getMail(Mail mail, boolean headerOnly) Loads one cached mail, lock held.private Collection<Mail> locked_getMails(String folder) Lists the cached mails, lock held.private booleanlocked_saveMail(Mail mail) Writes one mail to the cache, lock held.private FilemakeCacheDirs(String host, int port, String user, String folder) ~/.i2p/susimail/cache/cache-xxxxx/cur/s[b64char]/mail-xxxxx.full.txt.gz folder1 is the base.private static BufferWrap a cache file in a decompressing buffer.booleanWrite the mail to disk as a full message when it has a body, otherwise as a header-only file.private booleanSave data to disk.
Field Details
_locks
One lock for each user in the whole JVM, to protect against multiple sessions. One big lock for the whole cache dir, not one for each file or subdir. Never expired. Sure, if we did a maildir format we wouldn't need this._lock
Lock for the cache state._cacheDir
Directory holding the cached mail._attachmentDir
Directory for the drafts' attachments._context
The app context._log
Logger for the mail cache._isDrafts
private final boolean _isDraftsTrue for the drafts folder cache.DIR_SUSI
DIR_CACHE
CACHE_PREFIX
Prefix of the cache file names.- See Also:
DIR_IMPORT
Directory beside the cache holding imported .eml files, debug only.- See Also:
DIR_ATTACHMENTS
Directory holding draft attachment files, created only by the drafts cache.- See Also:
DIR_PREFIX
Prefix of the per-user directory names.- See Also:
FILE_PREFIX
HDR_SUFFIX
Suffix of the header-only cache files.- See Also:
FULL_SUFFIX
Suffix of the full-message cache files.- See Also:
B64
Constructor Details
PersistentMailCache
public PersistentMailCache(I2PAppContext ctx, String host, int port, String user, String pass, String folder) throws IOException Use the params to generate a unique directory name. Does NOT load the mails in. Caller MUST callgetMails(String).- Parameters:
ctx- supplies the log manager and the base directoryhost- IMAP host, part of the directory nameport- IMAP port, part of the directory nameuser- mail account name, part of the directory namepass- not used; the cache is keyed on account name alonefolder- on-disk maildir name, one of theDIRSvalues, e.g.DIR_FOLDER; only DIR_DRAFTS gets an attachment directory- Throws:
IOException- if the cache directory cannot be created
Method Details
getMails
Fetch all mails from disk, naming the folder in the completion log so a reader can tell which mailbox the counts belong to.- Parameters:
folder- label for the log, null if the caller has none to give- Returns:
- a new collection
locked_getMails
Lists the cached mails, lock held.- Parameters:
folder- the folder to list- Returns:
- the mails found in the cache
getMail
Fetch any needed data from disk, filling in the header, or the body if that is what was asked for and only a header file is on disk.- Parameters:
mail- the mail to populate, matched on its uidlheaderOnly- true to load just the header, false to load the body too- Returns:
- true if the mail was populated; false if no file exists for the uidl or it could not be read
locked_getMail
Loads one cached mail, lock held.- Parameters:
mail- the mail to loadheaderOnly- true to load the headers only- Returns:
- true if the cache had the mail
saveMail
Write the mail to disk as a full message when it has a body, otherwise as a header-only file. An existing file is left alone.- Parameters:
mail- the mail to save- Returns:
- true if the file is on disk, either just written or already present; false if the mail carries neither body nor header, or the write failed
locked_saveMail
Writes one mail to the cache, lock held.- Parameters:
mail- the mail to save- Returns:
- true if the mail was written
deleteMail
Delete both the full-message and the header-only file for this mail.- Parameters:
mail- the mail to remove
deleteMail
Delete both the full-message and the header-only file for this uidl.- Parameters:
uidl- the unique ID of the mail to remove
getLock
makeCacheDirs
~/.i2p/susimail/cache/cache-xxxxx/cur/s[b64char]/mail-xxxxx.full.txt.gz folder1 is the base.- Parameters:
host- the mail server host, part of the cache keyport- the mail server port, part of the cache keyuser- the user name, part of the cache keyfolder- the folder base name, e.g. cur- Returns:
- the base folder directory, with one subdirectory per base64 character
- Throws:
IOException- if any of the directories cannot be created
getHeaderFile
getFullFile
getFullBuffer
For reading or writing a new full mail (NOT headers only). For writing, caller MUST call writeComplete() on rv. Does not necessarily exist.- Parameters:
uidl- the unique ID of the mail- Returns:
- a new buffer over the full message file
getAttachmentDir
Where draft attachments are stored, which only the drafts cache creates.- Returns:
- non-null only for Drafts
getFile
write
read
load
This is for the initial load only. Others will usegetMail(Mail, boolean).- Parameters:
f- the cache file to parse, in full or header formisDrafts- true if the file is in the drafts folder- Returns:
- null on failure
importMail
private void importMail()For debugging. Import .eml files from the import/ directory.