CrunchCache.cpp revision 8a39da80b33691b0c82458c3b7727e13ff71277e
1//
2// Copyright 2011 The Android Open Source Project
3//
4// Implementation file for CrunchCache
5// This file defines functions laid out and documented in
6// CrunchCache.h
7
8#include <utils/Vector.h>
9#include <utils/String8.h>
10
11#include "DirectoryWalker.h"
12#include "FileFinder.h"
13#include "CacheUpdater.h"
14#include "CrunchCache.h"
15
16using namespace android;
17
18CrunchCache::CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff)
19    : mSourcePath(sourcePath), mDestPath(destPath), mSourceFiles(0), mDestFiles(0), mFileFinder(ff)
20{
21    // We initialize the default value to return to 0 so if a file doesn't exist
22    // then all files are automatically "newer" than it.
23
24    // Set file extensions to look for. Right now just pngs.
25    mExtensions.push(String8(".png"));
26
27    // Load files into our data members
28    loadFiles();
29}
30
31size_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite)
32{
33    size_t numFilesUpdated = 0;
34
35    // Iterate through the source files and compare to cache.
36    // After processing a file, remove it from the source files and
37    // from the dest files.
38    // We're done when we're out of files in source.
39    String8 relativePath;
40    while (mSourceFiles.size() > 0) {
41        // Get the full path to the source file, then convert to a c-string
42        // and offset our beginning pointer to the length of the sourcePath
43        // This efficiently strips the source directory prefix from our path.
44        // Also, String8 doesn't have a substring method so this is what we've
45        // got to work with.
46        const char* rPathPtr = mSourceFiles.keyAt(0).string()+mSourcePath.length();
47        // Strip leading slash if present
48        int offset = 0;
49        if (rPathPtr[0] == OS_PATH_SEPARATOR)
50            offset = 1;
51        relativePath = String8(rPathPtr + offset);
52
53        if (forceOverwrite || needsUpdating(relativePath)) {
54            cu->processImage(mSourcePath.appendPathCopy(relativePath),
55                             mDestPath.appendPathCopy(relativePath));
56            numFilesUpdated++;
57            // crunchFile(relativePath);
58        }
59        // Delete this file from the source files and (if it exists) from the
60        // dest files.
61        mSourceFiles.removeItemsAt(0);
62        mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath));
63    }
64
65    // Iterate through what's left of destFiles and delete leftovers
66    while (mDestFiles.size() > 0) {
67        cu->deleteFile(mDestFiles.keyAt(0));
68        mDestFiles.removeItemsAt(0);
69    }
70
71    // Update our knowledge of the files cache
72    // both source and dest should be empty by now.
73    loadFiles();
74
75    return numFilesUpdated;
76}
77
78void CrunchCache::loadFiles()
79{
80    // Clear out our data structures to avoid putting in duplicates
81    mSourceFiles.clear();
82    mDestFiles.clear();
83
84    // Make a directory walker that points to the system.
85    DirectoryWalker* dw = new SystemDirectoryWalker();
86
87    // Load files in the source directory
88    mFileFinder->findFiles(mSourcePath, mExtensions, mSourceFiles,dw);
89
90    // Load files in the destination directory
91    mFileFinder->findFiles(mDestPath,mExtensions,mDestFiles,dw);
92
93    delete dw;
94}
95
96bool CrunchCache::needsUpdating(String8 relativePath) const
97{
98    // Retrieve modification dates for this file entry under the source and
99    // cache directory trees. The vectors will return a modification date of 0
100    // if the file doesn't exist.
101    time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath));
102    time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath));
103    return sourceDate > destDate;
104}