#include "assemblyDefinitionFileCache.h"
#include <sys/types.h>          
#include <sys/stat.h>
#include <cassert>
#include <utility>
namespace {
AssemblyDefinitionFileCache fsTheInstance;
}
AssemblyDefinitionFileCache::Timestamp::Timestamp(
const MString& path)
    : fFileSize(-1)
{
    struct stat stat_buf;
    if (stat(path.
asChar(), &stat_buf) != 0)
 
        return;
    fFileSize      = stat_buf.st_size;
    fMTime         = stat_buf.st_mtime;
}
    
inline bool operator==(const AssemblyDefinitionFileCache::Timestamp& lhs,
                       const AssemblyDefinitionFileCache::Timestamp& rhs)
{
    return (lhs.fFileSize == rhs.fFileSize &&
            lhs.fMTime    == rhs.fMTime    );
}
void AssemblyDefinitionFileCache::Entry::Deleter::operator()(Entry* entry)
{
    AssemblyDefinitionFileCache& cache =
        AssemblyDefinitionFileCache::getInstance();
    Entries::iterator it = cache.fEntries.find(entry->fDefnFile);
    
    
    
    
    if (it != cache.fEntries.end()) {
        
        
        
        
        
        
        if (it->second.expired()) {
            cache.fEntries.erase(it);
        }
    }
    
    delete entry;
}
AssemblyDefinitionFileCache& AssemblyDefinitionFileCache::getInstance()
{
    return fsTheInstance;
}
AssemblyDefinitionFileCache::EntryPtr
AssemblyDefinitionFileCache::get(
const MString& defnFile)
{
    using namespace std::rel_ops;
    Entries::iterator it = fEntries.find(std::string(defnFile.
asChar()));
    if (it == fEntries.end()) return EntryPtr();
    EntryPtr entry(it->second);
    if (!entry) return EntryPtr();
    const Timestamp timestamp(defnFile);
    if (entry->getTimestamp() != timestamp) {
        
        
        fEntries.erase(it);
        return EntryPtr();
    }
    return entry;
}
    
AssemblyDefinitionFileCache::EntryPtr
AssemblyDefinitionFileCache::insert(
    const RepCreationArgsList&  repCreationArgsList)
{
    const std::string defnFileString(defnFile.
asChar());
 
    EntryPtr entry(
        new Entry(defnFileString,
                  Timestamp(defnFile),
                  repCreationArgsList),
        Entry::Deleter());
        
#ifndef NDEBUG
    std::pair<Entries::iterator, bool> result =
#endif            
        fEntries.insert(std::make_pair(defnFileString, entry));
    assert(result.second);
    return entry;
}