1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2011 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Implementation file for CrunchCache
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// This file defines functions laid out and documented in
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// CrunchCache.h
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Vector.h>
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/String8.h>
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "DirectoryWalker.h"
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "FileFinder.h"
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "CacheUpdater.h"
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "CrunchCache.h"
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android;
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiCrunchCache::CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff)
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    : mSourcePath(sourcePath), mDestPath(destPath), mSourceFiles(0), mDestFiles(0), mFileFinder(ff)
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // We initialize the default value to return to 0 so if a file doesn't exist
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // then all files are automatically "newer" than it.
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Set file extensions to look for. Right now just pngs.
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mExtensions.push(String8(".png"));
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load files into our data members
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    loadFiles();
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite)
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    size_t numFilesUpdated = 0;
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Iterate through the source files and compare to cache.
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // After processing a file, remove it from the source files and
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // from the dest files.
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // We're done when we're out of files in source.
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    String8 relativePath;
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (mSourceFiles.size() > 0) {
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Get the full path to the source file, then convert to a c-string
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // and offset our beginning pointer to the length of the sourcePath
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // This efficiently strips the source directory prefix from our path.
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Also, String8 doesn't have a substring method so this is what we've
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // got to work with.
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        const char* rPathPtr = mSourceFiles.keyAt(0).string()+mSourcePath.length();
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Strip leading slash if present
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int offset = 0;
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (rPathPtr[0] == OS_PATH_SEPARATOR)
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            offset = 1;
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        relativePath = String8(rPathPtr + offset);
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (forceOverwrite || needsUpdating(relativePath)) {
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            cu->processImage(mSourcePath.appendPathCopy(relativePath),
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                             mDestPath.appendPathCopy(relativePath));
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            numFilesUpdated++;
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // crunchFile(relativePath);
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Delete this file from the source files and (if it exists) from the
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // dest files.
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mSourceFiles.removeItemsAt(0);
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath));
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Iterate through what's left of destFiles and delete leftovers
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (mDestFiles.size() > 0) {
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        cu->deleteFile(mDestFiles.keyAt(0));
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mDestFiles.removeItemsAt(0);
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Update our knowledge of the files cache
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // both source and dest should be empty by now.
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    loadFiles();
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return numFilesUpdated;
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid CrunchCache::loadFiles()
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Clear out our data structures to avoid putting in duplicates
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mSourceFiles.clear();
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mDestFiles.clear();
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Make a directory walker that points to the system.
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DirectoryWalker* dw = new SystemDirectoryWalker();
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load files in the source directory
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mFileFinder->findFiles(mSourcePath, mExtensions, mSourceFiles,dw);
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Load files in the destination directory
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mFileFinder->findFiles(mDestPath,mExtensions,mDestFiles,dw);
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    delete dw;
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool CrunchCache::needsUpdating(String8 relativePath) const
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Retrieve modification dates for this file entry under the source and
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // cache directory trees. The vectors will return a modification date of 0
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // if the file doesn't exist.
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath));
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath));
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return sourceDate > destDate;
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}