Remove internal AtomicFile
Bug: 140590158 Test: m -j builds to confirm there are no remaining references Test: Presubmit tests to verify no change in functionality Change-Id: Iecc503435a8dab94317148a108865505c936685f
This commit is contained in:
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.os.Build;
|
||||
import android.os.FileUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Helper class for performing atomic operations on a file, by creating a
|
||||
* backup file until a write has successfully completed.
|
||||
* <p>
|
||||
* Atomic file guarantees file integrity by ensuring that a file has
|
||||
* been completely written and sync'd to disk before removing its backup.
|
||||
* As long as the backup file exists, the original file is considered
|
||||
* to be invalid (left over from a previous attempt to write the file).
|
||||
* </p><p>
|
||||
* Atomic file does not confer any file locking semantics.
|
||||
* Do not use this class when the file may be accessed or modified concurrently
|
||||
* by multiple threads or processes. The caller is responsible for ensuring
|
||||
* appropriate mutual exclusion invariants whenever it accesses the file.
|
||||
* </p>
|
||||
*/
|
||||
public final class AtomicFile {
|
||||
private final File mBaseName;
|
||||
private final File mBackupName;
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public AtomicFile(File baseName) {
|
||||
mBaseName = baseName;
|
||||
mBackupName = new File(baseName.getPath() + ".bak");
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
public File getBaseFile() {
|
||||
return mBaseName;
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public FileOutputStream startWrite() throws IOException {
|
||||
// Rename the current file so it may be used as a backup during the next read
|
||||
if (mBaseName.exists()) {
|
||||
if (!mBackupName.exists()) {
|
||||
if (!mBaseName.renameTo(mBackupName)) {
|
||||
Log.w("AtomicFile", "Couldn't rename file " + mBaseName
|
||||
+ " to backup file " + mBackupName);
|
||||
}
|
||||
} else {
|
||||
mBaseName.delete();
|
||||
}
|
||||
}
|
||||
FileOutputStream str = null;
|
||||
try {
|
||||
str = new FileOutputStream(mBaseName);
|
||||
} catch (FileNotFoundException e) {
|
||||
File parent = mBaseName.getParentFile();
|
||||
if (!parent.mkdir()) {
|
||||
throw new IOException("Couldn't create directory " + mBaseName);
|
||||
}
|
||||
FileUtils.setPermissions(
|
||||
parent.getPath(),
|
||||
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
|
||||
-1, -1);
|
||||
try {
|
||||
str = new FileOutputStream(mBaseName);
|
||||
} catch (FileNotFoundException e2) {
|
||||
throw new IOException("Couldn't create " + mBaseName);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public void finishWrite(FileOutputStream str) {
|
||||
if (str != null) {
|
||||
FileUtils.sync(str);
|
||||
try {
|
||||
str.close();
|
||||
mBackupName.delete();
|
||||
} catch (IOException e) {
|
||||
Log.w("AtomicFile", "finishWrite: Got exception:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public void failWrite(FileOutputStream str) {
|
||||
if (str != null) {
|
||||
FileUtils.sync(str);
|
||||
try {
|
||||
str.close();
|
||||
mBaseName.delete();
|
||||
mBackupName.renameTo(mBaseName);
|
||||
} catch (IOException e) {
|
||||
Log.w("AtomicFile", "failWrite: Got exception:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public FileOutputStream openAppend() throws IOException {
|
||||
try {
|
||||
return new FileOutputStream(mBaseName, true);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IOException("Couldn't append " + mBaseName);
|
||||
}
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public void truncate() throws IOException {
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(mBaseName);
|
||||
FileUtils.sync(fos);
|
||||
fos.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IOException("Couldn't append " + mBaseName);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return mBaseName.exists() || mBackupName.exists();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
mBaseName.delete();
|
||||
mBackupName.delete();
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public FileInputStream openRead() throws FileNotFoundException {
|
||||
if (mBackupName.exists()) {
|
||||
mBaseName.delete();
|
||||
mBackupName.renameTo(mBaseName);
|
||||
}
|
||||
return new FileInputStream(mBaseName);
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public byte[] readFully() throws IOException {
|
||||
FileInputStream stream = openRead();
|
||||
try {
|
||||
int pos = 0;
|
||||
int avail = stream.available();
|
||||
byte[] data = new byte[avail];
|
||||
while (true) {
|
||||
int amt = stream.read(data, pos, data.length-pos);
|
||||
//Log.i("foo", "Read " + amt + " bytes at " + pos
|
||||
// + " of avail " + data.length);
|
||||
if (amt <= 0) {
|
||||
//Log.i("foo", "**** FINISHED READING: pos=" + pos
|
||||
// + " len=" + data.length);
|
||||
return data;
|
||||
}
|
||||
pos += amt;
|
||||
avail = stream.available();
|
||||
if (avail > data.length-pos) {
|
||||
byte[] newData = new byte[pos+avail];
|
||||
System.arraycopy(data, 0, newData, 0, pos);
|
||||
data = newData;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user