18a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin//
28a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// Copyright 2011 The Android Open Source Project
38a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin//
48a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// Implementation file for CrunchCache
58a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// This file defines functions laid out and documented in
68a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// CrunchCache.h
78a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
88a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/Vector.h>
98a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/String8.h>
108a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
118a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "DirectoryWalker.h"
128a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "FileFinder.h"
138a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "CacheUpdater.h"
148a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "CrunchCache.h"
158a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
168a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinusing namespace android;
178a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
188a39da80b33691b0c82458c3b7727e13ff71277eJosiah GaskinCrunchCache::CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff)
198a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    : mSourcePath(sourcePath), mDestPath(destPath), mSourceFiles(0), mDestFiles(0), mFileFinder(ff)
208a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
218a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // We initialize the default value to return to 0 so if a file doesn't exist
228a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // then all files are automatically "newer" than it.
238a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
248a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Set file extensions to look for. Right now just pngs.
258a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    mExtensions.push(String8(".png"));
268a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
278a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Load files into our data members
288a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    loadFiles();
298a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
308a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
318a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinsize_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite)
328a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
338a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    size_t numFilesUpdated = 0;
348a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
358a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Iterate through the source files and compare to cache.
368a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // After processing a file, remove it from the source files and
378a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // from the dest files.
388a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // We're done when we're out of files in source.
398a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    String8 relativePath;
408a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    while (mSourceFiles.size() > 0) {
418a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // Get the full path to the source file, then convert to a c-string
428a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // and offset our beginning pointer to the length of the sourcePath
438a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // This efficiently strips the source directory prefix from our path.
448a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // Also, String8 doesn't have a substring method so this is what we've
458a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // got to work with.
468a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        const char* rPathPtr = mSourceFiles.keyAt(0).string()+mSourcePath.length();
478a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // Strip leading slash if present
488a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        int offset = 0;
498a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        if (rPathPtr[0] == OS_PATH_SEPARATOR)
508a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            offset = 1;
518a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        relativePath = String8(rPathPtr + offset);
528a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
538a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        if (forceOverwrite || needsUpdating(relativePath)) {
548a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            cu->processImage(mSourcePath.appendPathCopy(relativePath),
558a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                             mDestPath.appendPathCopy(relativePath));
568a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            numFilesUpdated++;
578a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            // crunchFile(relativePath);
588a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        }
598a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // Delete this file from the source files and (if it exists) from the
608a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // dest files.
618a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        mSourceFiles.removeItemsAt(0);
628a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath));
638a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
648a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
658a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Iterate through what's left of destFiles and delete leftovers
668a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    while (mDestFiles.size() > 0) {
678a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        cu->deleteFile(mDestFiles.keyAt(0));
688a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        mDestFiles.removeItemsAt(0);
698a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
708a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
718a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Update our knowledge of the files cache
728a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // both source and dest should be empty by now.
738a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    loadFiles();
748a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
758a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    return numFilesUpdated;
768a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
778a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
788a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinvoid CrunchCache::loadFiles()
798a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
808a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Clear out our data structures to avoid putting in duplicates
818a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    mSourceFiles.clear();
828a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    mDestFiles.clear();
838a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
848a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Make a directory walker that points to the system.
858a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    DirectoryWalker* dw = new SystemDirectoryWalker();
868a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
878a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Load files in the source directory
888a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    mFileFinder->findFiles(mSourcePath, mExtensions, mSourceFiles,dw);
898a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
908a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Load files in the destination directory
918a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    mFileFinder->findFiles(mDestPath,mExtensions,mDestFiles,dw);
928a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
938a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    delete dw;
948a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
958a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
968a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinbool CrunchCache::needsUpdating(String8 relativePath) const
978a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
988a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Retrieve modification dates for this file entry under the source and
998a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // cache directory trees. The vectors will return a modification date of 0
1008a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // if the file doesn't exist.
1018a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath));
1028a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath));
1038a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    return sourceDate > destDate;
1048a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}