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
17package com.android.internal.util;
18
19import java.io.File;
20import java.io.IOException;
21
22/**
23 * @deprecated Use {@link com.android.internal.os.AtomicFile} instead.  It would
24 * be nice to update all existing uses of this to switch to AtomicFile, but since
25 * their on-file semantics are slightly different that would run the risk of losing
26 * data if at the point of the platform upgrade to the new code it would need to
27 * roll back to the backup file.  This can be solved...  but is it worth it and
28 * all of the testing needed to make sure it is correct?
29 */
30@Deprecated
31public class JournaledFile {
32    File mReal;
33    File mTemp;
34    boolean mWriting;
35
36    public JournaledFile(File real, File temp) {
37        mReal = real;
38        mTemp = temp;
39    }
40
41    /** Returns the file for you to read.
42     * @more
43     * Prefers the real file.  If it doesn't exist, uses the temp one, and then copies
44     * it to the real one.  If there is both a real file and a temp one, assumes that the
45     * temp one isn't fully written and deletes it.
46     */
47    public File chooseForRead() {
48        File result;
49        if (mReal.exists()) {
50            result = mReal;
51            if (mTemp.exists()) {
52                mTemp.delete();
53            }
54        } else if (mTemp.exists()) {
55            result = mTemp;
56            mTemp.renameTo(mReal);
57        } else {
58            return mReal;
59        }
60        return result;
61    }
62
63    /**
64     * Returns a file for you to write.
65     * @more
66     * If a write is already happening, throws.  In other words, you must provide your
67     * own locking.
68     * <p>
69     * Call {@link #commit} to commit the changes, or {@link #rollback} to forget the changes.
70     */
71    public File chooseForWrite() {
72        if (mWriting) {
73            throw new IllegalStateException("uncommitted write already in progress");
74        }
75        if (!mReal.exists()) {
76            // If the real one doesn't exist, it's either because this is the first time
77            // or because something went wrong while copying them.  In this case, we can't
78            // trust anything that's in temp.  In order to have the chooseForRead code not
79            // use the temporary one until it's fully written, create an empty file
80            // for real, which will we'll shortly delete.
81            try {
82                mReal.createNewFile();
83            } catch (IOException e) {
84                // Ignore
85            }
86        }
87
88        if (mTemp.exists()) {
89            mTemp.delete();
90        }
91        mWriting = true;
92        return mTemp;
93    }
94
95    /**
96     * Commit changes.
97     */
98    public void commit() {
99        if (!mWriting) {
100            throw new IllegalStateException("no file to commit");
101        }
102        mWriting = false;
103        mTemp.renameTo(mReal);
104    }
105
106    /**
107     * Roll back changes.
108     */
109    public void rollback() {
110        if (!mWriting) {
111            throw new IllegalStateException("no file to roll back");
112        }
113        mWriting = false;
114        mTemp.delete();
115    }
116}
117