• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 com.android.server;
18 
19 import java.io.File;
20 import java.io.IOException;
21 
22 public class JournaledFile {
23     File mReal;
24     File mTemp;
25     boolean mWriting;
26 
JournaledFile(File real, File temp)27     public JournaledFile(File real, File temp) {
28         mReal = real;
29         mTemp = temp;
30     }
31 
32     /** Returns the file for you to read.
33      * @more
34      * Prefers the real file.  If it doesn't exist, uses the temp one, and then copies
35      * it to the real one.  If there is both a real file and a temp one, assumes that the
36      * temp one isn't fully written and deletes it.
37      */
chooseForRead()38     public File chooseForRead() {
39         File result;
40         if (mReal.exists()) {
41             result = mReal;
42             if (mTemp.exists()) {
43                 mTemp.delete();
44             }
45         } else if (mTemp.exists()) {
46             result = mTemp;
47             mTemp.renameTo(mReal);
48         } else {
49             return mReal;
50         }
51         return result;
52     }
53 
54     /**
55      * Returns a file for you to write.
56      * @more
57      * If a write is already happening, throws.  In other words, you must provide your
58      * own locking.
59      * <p>
60      * Call {@link #commit} to commit the changes, or {@link #rollback} to forget the changes.
61      */
chooseForWrite()62     public File chooseForWrite() {
63         if (mWriting) {
64             throw new IllegalStateException("uncommitted write already in progress");
65         }
66         if (!mReal.exists()) {
67             // If the real one doesn't exist, it's either because this is the first time
68             // or because something went wrong while copying them.  In this case, we can't
69             // trust anything that's in temp.  In order to have the chooseForRead code not
70             // use the temporary one until it's fully written, create an empty file
71             // for real, which will we'll shortly delete.
72             try {
73                 mReal.createNewFile();
74             } catch (IOException e) {
75                 // Ignore
76             }
77         }
78 
79         if (mTemp.exists()) {
80             mTemp.delete();
81         }
82         mWriting = true;
83         return mTemp;
84     }
85 
86     /**
87      * Commit changes.
88      */
commit()89     public void commit() {
90         if (!mWriting) {
91             throw new IllegalStateException("no file to commit");
92         }
93         mWriting = false;
94         mTemp.renameTo(mReal);
95     }
96 
97     /**
98      * Roll back changes.
99      */
rollback()100     public void rollback() {
101         if (!mWriting) {
102             throw new IllegalStateException("no file to roll back");
103         }
104         mWriting = false;
105         mTemp.delete();
106     }
107 }
108