--- title: HTTP Cache slug: Mozilla/HTTP_cache translation_of: Mozilla/HTTP_cache ---
Este documento describe la Nueva caché HTTP versión 2.
El código reside en /network/cache2.
Aquí hay una descripción detallada de la API de caché HTTP v2, con ejemplos incluidos. Este documento sólo contiene lo que no se puede encontrar o puede no estar claro directamente de los comentarios de los archivos IDL.
Cuando no hay perfil, la nueva caché HTTP funciona, pero todo se almacena solo en la memoria que no obedece a ningún límite en particular.
Está fuertemente codificado para NO USAR más la ANTIGUA API de caché - nsICacheService
y otros. Pronto será completamente obsoleto y eliminado (bug 913828).
El punto de entrada de la memoria caché HTTP. Accesible solo como un servicio, totalmente seguro para subprocesos y programable.
https://dxr.mozilla.org/mozilla-central/source/netwerk/cache2/nsICacheStorageService.idl
"@mozilla.org/netwerk/cache-storage-service;1"
Proporciona métodos para acceder a los objetos de “almacenamiento” – ver nsICacheStorage
más abajo – para obtener más acceso a las entradas de caché – ver nsICacheEntry
más abajo – por URL específica.
Actualmente hay 3 tipos de almacenamientos, todos los métodos de acceso devuelve un objeto nsICacheStorage
:
memory-only (memoryCacheStorage
): Almacena datos solo en memoria caché, los datos en este almacenamiento nunca se guardan en disco.
disk (diskCacheStorage
): Almacena datos en el disco, pero para entradas existentes además busca dentro del storage de memory-only;
cuando se le indica a través de un argumento especial, también busca principalmente en la cache de aplicacion.
application cache (appCacheStorage
): Cuando un cliente tiene un objeto nsIApplicationCache
especifico (i.e. una version particular de app cache en un grupo ) en manos, este almacenamiento provee acceso de lectura y escritura a los registros en la aplicacion de Cache, cuando la app de Cache no ha sido especificada, el almacenamiento opera, sobre todas las app de cache.
El servicio también proporciona métodos para limpiar todo el disco y el contenido de la memoria caché o purgar cualquier estructura intermedia de memoria:
clear
– after it returns, all entries are no longer accessible through the cache APIs; the method is fast to execute and non-blocking in any way; the actual erase happens in background
purgeFromMemory
– removes (schedules to remove) any intermediate cache data held in memory for faster access (more about the intermediate cache below)
Distingue el scope del almacenamiento demandado para abrir.
Argumento obligatorio de *Storage
metodos de nsICacheStorageService
.
https://dxr.mozilla.org/mozilla-central/source/netwerk/base/public/nsILoadContextInfo.idl
Es una interaz de ayuda que se ajusta siguiendo 4 argumentos en uno solo:
private-browsing boolean flag
anonymous load boolean flag
app ID number (0
for no app)
is-in-browser boolean flag
Helper functions to create nsILoadContextInfo objects:
C++ consumers: functions at LoadContextInfo.h
exported header
JS consumers: resource://gre/modules/LoadContextInfo.jsm
module methods
Dos objectos de almacenamiento creados con el mismo set de nsILoadContextInfo
argumentos son identicos, conteniedo las mismas entredas de cache.
Two storage objects created with in any way different nsILoadContextInfo
arguments are strictly and completely distinct and cache entries in them do not overlap even when having the same URIs.
https://dxr.mozilla.org/mozilla-central/source/netwerk/cache2/nsICacheStorage.idl
Obtained from call to one of the *Storage
methods on nsICacheStorageService
.
Represents a distinct storage area (or scope) to put and get cache entries mapped by URLs into and from it.
Similarity with the old cache: this interface may be with some limitations considered as a mirror to nsICacheSession
, but less generic and not inclining to abuse.
Unimplemented or underimplemented functionality:
asyncEvictStorage (bug 977766), asyncVisitStorage (bug 916052)
https://dxr.mozilla.org/mozilla-central/source/netwerk/cache2/nsICacheEntryOpenCallback.idl
The result of nsICacheStorage.asyncOpenURI
is always and only sent to callbacks on this interface.
These callbacks are ensured to be invoked when asyncOpenURI
returns NS_OK
.
Important difference in behavior from the old cache: when the cache entry object is already present in memory or open as “force-new” (a.k.a “open-truncate”) this callback is invoked sooner then the asyncOpenURI
method returns (i.e. immediately); there is currently no way to opt out of this feature (watch bug 938186).
https://dxr.mozilla.org/mozilla-central/source/netwerk/cache2/nsICacheEntry.idl
Obtained asynchronously or pseudo-asynchronously by a call to nsICacheStorage.asyncOpenURI
.
Provides access to a cached entry data and meta data for reading or writing or in some cases both, see below.
Como una entrada es inicialmente vacia (ningun dato o metado es almacenado en este).
El argumento aNew
en onCacheEntryAvailable
es true
para este y nuevos ingresos.
Only one consumer (the so called "writer") may have such an entry available (obtained via onCacheEntryAvailable
).
Other parallel openers of the same cache entry are blocked (wait) for invocation of their onCacheEntryAvailable
until one of the following occurs:
This applies in general, writers throwing away the cache entry means a failure to write the cache entry and a new writer is being looked for again, the cache entry remains empty (a.k.a. "new").
metaDataReady
on it: other consumers now get the entry and may examine and potentially modify the meta data and read the data (if any) of the cache entry.metaDataReady
.Important difference in behavior from the old cache: the cache now supports reading a cache entry data while it is still being written by the first consumer - the writer.
This can only be engaged for resumable responses that (bug 960902) don't need revalidation. Reason is that when the writer is interrupted (by e.g. external canceling of the loading channel) concurrent readers would not be able to reach the remaning unread content.
This could be improved by keeping the network load running and being stored to the cache entry even after the writing channel has been canceled.
When the writer is interrupted, the first concurrent reader in line does a range request for the rest of the data - and becomes that way a new writer. The rest of the readers are still concurrently reading the content since output stream for the cache entry is again open and kept by the current writer.
nsICacheEntryOpenCallback.onCacheEntryCheck
callback, where it has to be checked for completeness.Content-Length
(or different indicator) header doesn't equal to the data size reported by the cache entry.ENTRY_NEEDS_REVALIDATION
from onCacheEntryCheck
.setValid
on the cache entry.setValid
to unblock other pending openers.nsICacheEntryOpenCallback.onCacheEntryCheck
callback, where the consumer finds out it must be revalidated with the server before use.ENTRY_NEEDS_REVALIDATION
from onCacheEntryCheck
.setValid
on the cache entry.recreate
on the cache entry. This returns a new empty entry to write the meta data and data to, the writer exchanges its cache entry by this new one and handles it as a new one.metaDataReady
on it.Should there be a need to add a new distinct storage for which the current scoping model would not be sufficient - use one of the two following ways:
<Your>Storage
method on nsICacheStorageService
and if needed give it any arguments to specify the storage scope even more. Implementation only should need to enhance the context key generation and parsing code and enhance current - or create new when needed - nsICacheStorage
implementations to carry any additional information down to the cache service.nsILoadContextInfo
; be careful here, since some arguments on the context may not be known during the load time, what may lead to inter-context data leaking or implementation problems. Adding more distinction to nsILoadContextInfo
also affects all existing storages which may not be always desirable.See context keying details for more information.
TBD
The cache API is fully thread-safe.
The cache is using a single background thread where any IO operations like opening, reading, writing and erasing happen. Also memory pool management, eviction, visiting loops happen on this thread.
The thread supports several priority levels. Dispatching to a level with a lower number is executed sooner then dispatching to higher number layers; also any loop on lower levels yields to higher levels so that scheduled deletion of 1000 files will not block opening cache entries.
NOTE: Special case for eviction - when an eviction is scheduled on the IO thread, all operations pending on the OPEN level are first merged to the OPEN_PRIORITY level. The eviction preparation operation - i.e. clearing of the internal IO state - is then put to the end of the OPEN_PRIORITY level. All this happens atomically. This functionality is currently pending in bug 976866.
A scope key string used to map the storage scope is based on the arguments of nsILoadContextInfo
. The form is following (currently pending in bug 968593):
a,b,i1009,p,
(.([^,]+)?,)*
0
)CacheStorageService
keeps a global hashtable mapped by the scope key. Elements in this global hashtable are hashtables of cache entries. The cache entries are mapped by concantation of Enhance ID and URI passed to nsICacheStorage.asyncOpenURI
. So that when an entry is beeing looked up, first the global hashtable is searched using the scope key. An entries hashtable is found. Then this entries hashtable is searched using <enhance-id:><uri> string. The elemets in this hashtable are CacheEntry classes, see below.
The hash tables keep a strong reference to CacheEntry
objects. The only way to remove CacheEntry
objects from memory is by exhausting a memory limit for intermediate memory caching, what triggers a background process of purging expired and then least used entries from memory. Another way is to directly call the nsICacheStorageService.purge
method. That method is also called automatically on the "memory-pressure"
indication.
Access to the hashtables is protected by a global lock. We also - in a thread-safe manner - count the number of consumers keeping a reference on each entry. The open callback actually doesn't give the consumer directly the CacheEntry
object but a small wrapper class that manages the 'consumer reference counter' on its cache entry. This both mechanisms ensure thread-safe access and also inability to have more then a single instance of a CacheEntry
for a single <scope+enhanceID+URL> key.
CacheStorage
, implementing the nsICacheStorage
interface, is forwarding all calls to internal methods of CacheStorageService
passing itself as an argument. CacheStorageService
then generates the scope key using the nsILoadContextInfo
of the storage. Note: CacheStorage keeps a thread-safe copy of nsILoadContextInfo
passed to a *Storage
method on nsICacheStorageService
.
CacheEntry
, implementing the nsICacheEntry
interface, is responsible for managing the cache entry internal state and to properly invoke onCacheEntryCheck
and onCacheEntryAvaiable
callbacks to all callers of nsICacheStorage.asyncOpenURI
.
CacheFile
object that holds actual data and meta data and, when told to, persists it to the disk.The openers FIFO is an array of CacheEntry::Callback
objects. CacheEntry::Callback
keeps a strong reference to the opener plus the opening flags. nsICacheStorage.asyncOpenURI
forwards to CacheEntry::AsyncOpen
and triggers the following pseudo-code:
CacheStorage::AsyncOpenURI - the API entry point:
CacheEntry
in CacheStorageService
hash tables upCacheEntry::AsyncOpen (entry atomic):
CacheFile
is created as 'new', state = EMPTYCacheFile
is created and load on it startedCacheEntry::OnFileReady
notification is now expectedCacheEntry::InvokeCallbacks (entry atomic):
AsyncOpen
callCacheFile
openmetaDataReady
or setValid
on the entry has been callednull
for the cache entryaNew = true
and this entry is invoked (on the caller thread) for the writerRecheckAfterWrite
onCacheEntryCheck
is re-invoked on themCacheEntry::SetValid
is calledaNew = false
and the entryonCacheEntryAvailable
is invoked on the opener with null
for the entryCacheEntry::OnFileReady (entry atomic):
CacheEntry::OnHandleClosed (entry atomic):
metaDataReady
on the entry - state = EMPTYsetValid
on the entry - state = READYAll consumers release the reference:
This is a description of this feature status that is currently only a patch in bug 986179. Current behavior is simpler and causes a serious memory consumption regression (bug 975367).
For the disk cache entries we keep some of the most recent and most used cache entries' meta data in memory for immediate zero-thread-loop opening. The default size of this meta data memory pool is only 250kB and is controlled by a new browser.cache.disk.metadata_memory_limit
preference. When the limit is exceeded, we purge (throw away) first expired and then least used entries to free up memory again.
Only CacheEntry
objects that are already loaded and filled with data and having the 'consumer reference == 0' (bug 942835) can be purged.
The 'least used' entries are recognized by the lowest value of frecency we re-compute for each entry on its every access. The decay time is controlled by the browser.cache.frecency_half_life_hours
preference and defaults to 6 hours. The best decay time will be based on results of an experiment.
The memory pool is represented by two lists (strong refering ordered arrays) of CacheEntry
objects:
We have two such pools, one for memory-only entries actually representing the memory-only cache and one for disk cache entries for which we only keep the meta data. Each pool has a different limit checking - the memory cache pool is controlled by browser.cache.memory.capacity
, the disk entries pool is already described above. The pool can be accessed and modified only on the cache background thread.