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
16 using namespace android;
17
CrunchCache(String8 sourcePath,String8 destPath,FileFinder * ff)18 CrunchCache::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
crunch(CacheUpdater * cu,bool forceOverwrite)31 size_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
loadFiles()78 void 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
needsUpdating(String8 relativePath) const96 bool 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 }