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