1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.hadoop.hdfs.util; 19 20 import java.io.BufferedReader; 21 import java.io.File; 22 import java.io.FileInputStream; 23 import java.io.IOException; 24 import java.io.InputStreamReader; 25 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 import org.apache.hadoop.classification.InterfaceAudience; 29 import org.apache.hadoop.io.IOUtils; 30 31 import com.google.common.base.Charsets; 32 33 /** 34 * Class that represents a file on disk which persistently stores 35 * a single <code>long</code> value. The file is updated atomically 36 * and durably (i.e fsynced). 37 */ 38 @InterfaceAudience.Private 39 public class PersistentLongFile { 40 private static final Log LOG = LogFactory.getLog( 41 PersistentLongFile.class); 42 43 private final File file; 44 private final long defaultVal; 45 46 private long value; 47 private boolean loaded = false; 48 PersistentLongFile(File file, long defaultVal)49 public PersistentLongFile(File file, long defaultVal) { 50 this.file = file; 51 this.defaultVal = defaultVal; 52 } 53 get()54 public long get() throws IOException { 55 if (!loaded) { 56 value = readFile(file, defaultVal); 57 loaded = true; 58 } 59 return value; 60 } 61 set(long newVal)62 public void set(long newVal) throws IOException { 63 if (value != newVal || !loaded) { 64 writeFile(file, newVal); 65 } 66 value = newVal; 67 loaded = true; 68 } 69 70 /** 71 * Atomically write the given value to the given file, including fsyncing. 72 * 73 * @param file destination file 74 * @param val value to write 75 * @throws IOException if the file cannot be written 76 */ writeFile(File file, long val)77 public static void writeFile(File file, long val) throws IOException { 78 AtomicFileOutputStream fos = new AtomicFileOutputStream(file); 79 try { 80 fos.write(String.valueOf(val).getBytes(Charsets.UTF_8)); 81 fos.write('\n'); 82 fos.close(); 83 fos = null; 84 } finally { 85 if (fos != null) { 86 fos.abort(); 87 } 88 } 89 } 90 readFile(File file, long defaultVal)91 public static long readFile(File file, long defaultVal) throws IOException { 92 long val = defaultVal; 93 if (file.exists()) { 94 BufferedReader br = 95 new BufferedReader(new InputStreamReader(new FileInputStream( 96 file), Charsets.UTF_8)); 97 try { 98 val = Long.parseLong(br.readLine()); 99 br.close(); 100 br = null; 101 } finally { 102 IOUtils.cleanup(LOG, br); 103 } 104 } 105 return val; 106 } 107 } 108