All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flume.serialization.DurablePositionTracker Maven / Gradle / Ivy

There is a newer version: 4.15.0-HBase-1.5
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.flume.serialization;

import java.io.File;
import java.io.IOException;

import com.google.common.base.Preconditions;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.specific.SpecificDatumWriter;
import org.apache.flume.annotations.InterfaceAudience;
import org.apache.flume.annotations.InterfaceStability;
import org.apache.flume.tools.PlatformDetect;

/**
 * 

Class that stores object state in an avro container file. * The file is only ever appended to. * At construction time, the object reads data from the end of the file and * caches that data for use by a client application. After construction, reads * never go to disk. * Writes always flush to disk. * *

Note: This class is not thread-safe. */ @InterfaceAudience.Private @InterfaceStability.Evolving public class DurablePositionTracker implements PositionTracker { private final File trackerFile; private final DataFileWriter writer; private final DataFileReader reader; private final TransferStateFileMeta metaCache; private String target; private boolean isOpen; /** * If the file exists at startup, then read it, roll it, and open a new one. * We go through this to avoid issues with partial reads at the end of the * file from a previous crash. If we append to a bad record, * our writes may never be visible. * @param trackerFile * @param target * @return * @throws IOException */ public static DurablePositionTracker getInstance(File trackerFile, String target) throws IOException { if (!trackerFile.exists()) { return new DurablePositionTracker(trackerFile, target); } // exists DurablePositionTracker oldTracker = new DurablePositionTracker(trackerFile, target); String existingTarget = oldTracker.getTarget(); long targetPosition = oldTracker.getPosition(); oldTracker.close(); File tmpMeta = File.createTempFile(trackerFile.getName(), ".tmp", trackerFile.getParentFile()); tmpMeta.delete(); DurablePositionTracker tmpTracker = new DurablePositionTracker(tmpMeta, existingTarget); tmpTracker.storePosition(targetPosition); tmpTracker.close(); // On windows, things get messy with renames... // FIXME: This is not atomic. Consider implementing a recovery procedure // so that if it does not exist at startup, check for a rolled version // before creating a new file from scratch. if (PlatformDetect.isWindows()) { if (!trackerFile.delete()) { throw new IOException("Unable to delete existing meta file " + trackerFile); } } // rename tmp file to meta if (!tmpMeta.renameTo(trackerFile)) { throw new IOException("Unable to rename " + tmpMeta + " to " + trackerFile); } // return a new known-good version that is open for append DurablePositionTracker newTracker = new DurablePositionTracker(trackerFile, existingTarget); return newTracker; } /** * If the file exists, read it and open it for append. * @param trackerFile * @param target * @throws IOException */ DurablePositionTracker(File trackerFile, String target) throws IOException { Preconditions.checkNotNull(trackerFile, "trackerFile must not be null"); Preconditions.checkNotNull(target, "target must not be null"); this.trackerFile = trackerFile; this.target = target; DatumWriter dout = new SpecificDatumWriter( TransferStateFileMeta.SCHEMA$); DatumReader din = new SpecificDatumReader( TransferStateFileMeta.SCHEMA$); writer = new DataFileWriter(dout); if (trackerFile.exists()) { // open it for append writer.appendTo(trackerFile); reader = new DataFileReader(trackerFile, din); this.target = reader.getMetaString("file"); } else { // create the file this.target = target; writer.setMeta("file", target); writer.create(TransferStateFileMeta.SCHEMA$, trackerFile); reader = new DataFileReader(trackerFile, din); } target = getTarget(); // initialize @ line = 0; metaCache = TransferStateFileMeta.newBuilder().setOffset(0L).build(); initReader(); isOpen = true; } /** * Read the last record in the file. */ private void initReader() throws IOException { long syncPos = trackerFile.length() - 256L; if (syncPos < 0) syncPos = 0L; reader.sync(syncPos); while (reader.hasNext()) { reader.next(metaCache); } } @Override public synchronized void storePosition(long position) throws IOException { metaCache.setOffset(position); writer.append(metaCache); writer.sync(); writer.flush(); } @Override public synchronized long getPosition() { return metaCache.getOffset(); } @Override public String getTarget() { return target; } @Override public void close() throws IOException { if (isOpen) { writer.close(); reader.close(); isOpen = false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy