internal virtual long GetAccessTime(string key)
        {
            string interned = Intern(key);

            lock (interned)
            {
                SharedCacheResource resource = cachedResources[interned];
                return(resource == null ? -1 : resource.GetAccessTime());
            }
        }
        /// <summary>Adds the given resource to the store under the key and the filename.</summary>
        /// <remarks>
        /// Adds the given resource to the store under the key and the filename. If the
        /// entry is already found, it returns the existing filename. It represents the
        /// state of the store at the time of this query. The entry may change or even
        /// be removed once this method returns. The caller should be prepared to
        /// handle that situation.
        /// </remarks>
        /// <returns>
        /// the filename of the newly inserted resource or that of the existing
        /// resource
        /// </returns>
        public override string AddResource(string key, string fileName)
        {
            string interned = Intern(key);

            lock (interned)
            {
                SharedCacheResource resource = cachedResources[interned];
                if (resource == null)
                {
                    resource = new SharedCacheResource(fileName);
                    cachedResources[interned] = resource;
                }
                return(resource.GetFileName());
            }
        }
        /// <summary>
        /// Returns the list of resource references currently registered under the
        /// cache entry.
        /// </summary>
        /// <remarks>
        /// Returns the list of resource references currently registered under the
        /// cache entry. If the list is empty, it returns an empty collection. The
        /// returned collection is unmodifiable and a snapshot of the information at
        /// the time of the query. The state may change after this query returns. The
        /// caller should handle the situation that some or all of these resource
        /// references are no longer relevant.
        /// </remarks>
        /// <returns>
        /// the collection that contains the resource references associated
        /// with the resource; or an empty collection if no resource references
        /// are registered under this resource
        /// </returns>
        public override ICollection <SharedCacheResourceReference> GetResourceReferences(string
                                                                                         key)
        {
            string interned = Intern(key);

            lock (interned)
            {
                SharedCacheResource resource = cachedResources[interned];
                if (resource == null)
                {
                    return(Sharpen.Collections.EmptySet());
                }
                ICollection <SharedCacheResourceReference> refs = new HashSet <SharedCacheResourceReference
                                                                               >(resource.GetResourceReferences());
                return(Sharpen.Collections.UnmodifiableSet(refs));
            }
        }
        /// <summary>
        /// Adds the provided resource reference to the cache resource under the key,
        /// and updates the access time.
        /// </summary>
        /// <remarks>
        /// Adds the provided resource reference to the cache resource under the key,
        /// and updates the access time. If it returns a non-null value, the caller may
        /// safely assume that the resource will not be removed at least until the app
        /// in this resource reference has terminated.
        /// </remarks>
        /// <returns>the filename of the resource, or null if the resource is not found</returns>
        public override string AddResourceReference(string key, SharedCacheResourceReference
                                                    @ref)
        {
            string interned = Intern(key);

            lock (interned)
            {
                SharedCacheResource resource = cachedResources[interned];
                if (resource == null)
                {
                    // it's not mapped
                    return(null);
                }
                resource.AddReference(@ref);
                resource.UpdateAccessTime();
                return(resource.GetFileName());
            }
        }
        /// <summary>Removes the given resource from the store.</summary>
        /// <remarks>
        /// Removes the given resource from the store. Returns true if the resource is
        /// found and removed or if the resource is not found. Returns false if it was
        /// unable to remove the resource because the resource reference list was not
        /// empty.
        /// </remarks>
        public override bool RemoveResource(string key)
        {
            string interned = Intern(key);

            lock (interned)
            {
                SharedCacheResource resource = cachedResources[interned];
                if (resource == null)
                {
                    return(true);
                }
                if (!resource.GetResourceReferences().IsEmpty())
                {
                    return(false);
                }
                // no users
                Sharpen.Collections.Remove(cachedResources, interned);
                return(true);
            }
        }
        /// <summary>Removes the provided collection of resource references from the resource.
        ///     </summary>
        /// <remarks>
        /// Removes the provided collection of resource references from the resource.
        /// If the resource does not exist, nothing will be done.
        /// </remarks>
        public override void RemoveResourceReferences(string key, ICollection <SharedCacheResourceReference
                                                                               > refs, bool updateAccessTime)
        {
            string interned = Intern(key);

            lock (interned)
            {
                SharedCacheResource resource = cachedResources[interned];
                if (resource != null)
                {
                    ICollection <SharedCacheResourceReference> resourceRefs = resource.GetResourceReferences
                                                                                  ();
                    resourceRefs.RemoveAll(refs);
                    if (updateAccessTime)
                    {
                        resource.UpdateAccessTime();
                    }
                }
            }
        }
        /// <summary>Removes the provided resource reference from the resource.</summary>
        /// <remarks>
        /// Removes the provided resource reference from the resource. If the resource
        /// does not exist, nothing will be done.
        /// </remarks>
        public override bool RemoveResourceReference(string key, SharedCacheResourceReference
                                                     @ref, bool updateAccessTime)
        {
            string interned = Intern(key);

            lock (interned)
            {
                bool removed = false;
                SharedCacheResource resource = cachedResources[interned];
                if (resource != null)
                {
                    ICollection <SharedCacheResourceReference> resourceRefs = resource.GetResourceReferences
                                                                                  ();
                    removed = resourceRefs.Remove(@ref);
                    if (updateAccessTime)
                    {
                        resource.UpdateAccessTime();
                    }
                }
                return(removed);
            }
        }
        /// <exception cref="System.IO.IOException"/>
        private void Bootstrap(Configuration conf)
        {
            IDictionary <string, string> initialCachedResources = GetInitialCachedResources(FileSystem
                                                                                            .Get(conf), conf);

            Log.Info("Bootstrapping from " + initialCachedResources.Count + " cache resources located in the file system"
                     );
            IEnumerator <KeyValuePair <string, string> > it = initialCachedResources.GetEnumerator
                                                                  ();

            while (it.HasNext())
            {
                KeyValuePair <string, string> e = it.Next();
                string key      = Intern(e.Key);
                string fileName = e.Value;
                SharedCacheResource resource = new SharedCacheResource(fileName);
                // we don't hold the lock for this as it is done as part of serviceInit
                cachedResources[key] = resource;
                // clear out the initial resource to reduce the footprint
                it.Remove();
            }
            Log.Info("Bootstrapping complete");
        }