1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package vogar;
18 
19 import java.io.File;
20 import java.lang.ProcessHandle;
21 import java.util.List;
22 import vogar.commands.Command;
23 import vogar.commands.Mkdir;
24 
25 public class HostFileCache implements FileCache {
26     private final File CACHE_ROOT = new File("/tmp/vogar-md5-cache");
27 
28     private final Log log;
29     private final Mkdir mkdir;
30 
HostFileCache(Log log, Mkdir mkdir)31     public HostFileCache(Log log, Mkdir mkdir) {
32         this.log = log;
33         this.mkdir = mkdir;
34     }
35 
cp(File source, File destination)36     private void cp(File source, File destination) {
37         List<String> rawResult = new Command.Builder(log).args("cp", source, destination).execute();
38         // A successful copy returns no results.
39         if (!rawResult.isEmpty()) {
40             throw new RuntimeException("Couldn't copy " + source + " to " + destination
41                     + ": " + rawResult.get(0));
42         }
43     }
44 
mv(File source, File destination)45     private void mv(File source, File destination) {
46         List<String> rawResult = new Command.Builder(log).args("mv", source, destination).execute();
47         // A successful move returns no results.
48         // Note that other process might have moved the file to the destination at the same time.
49         if (!rawResult.isEmpty() && !destination.exists()) {
50             throw new RuntimeException("Couldn't move " + source + " to " + destination
51                     + ": " + rawResult.get(0));
52         }
53     }
54 
copyFromCache(String key, File destination)55     public void copyFromCache(String key, File destination) {
56         File cachedFile = new File(CACHE_ROOT, key);
57         cp(cachedFile, destination);
58     }
59 
copyToCache(File source, String key)60     public void copyToCache(File source, String key) {
61         File cachedFile = new File(CACHE_ROOT, key);
62         mkdir.mkdirs(CACHE_ROOT);
63         // Copy it onto the same file system first, then atomically move it into place.
64         // That way, if we fail, we don't leave anything dangerous lying around.
65         File temporary = new File(cachedFile + ".tmp" + String.valueOf(ProcessHandle.current().pid()));
66         cp(source, temporary);
67         mv(temporary, cachedFile);
68     }
69 
existsInCache(String key)70     public boolean existsInCache(String key) {
71         return new File(CACHE_ROOT, key).exists();
72     }
73 }
74