/** * 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.activemq.store.kahadb.disk.journal; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * An AsyncDataManager that works in read only mode against multiple data directories. * Useful for reading back archived data files. */ public class ReadOnlyJournal extends Journal { private final ArrayList<File> dirs; public ReadOnlyJournal(final ArrayList<File> dirs) { this.dirs = dirs; } public synchronized void start() throws IOException { if (started) { return; } started = true; ArrayList<File> files = new ArrayList<File>(); for (File directory : dirs) { final File d = directory; File[] f = d.listFiles(new FilenameFilter() { public boolean accept(File dir, String n) { return dir.equals(d) && n.startsWith(filePrefix); } }); for (int i = 0; i < f.length; i++) { files.add(f[i]); } } for (File file : files) { try { String n = file.getName(); String numStr = n.substring(filePrefix.length(), n.length()); int num = Integer.parseInt(numStr); DataFile dataFile = new ReadOnlyDataFile(file, num); fileMap.put(dataFile.getDataFileId(), dataFile); totalLength.addAndGet(dataFile.getLength()); } catch (NumberFormatException e) { // Ignore file that do not match the pattern. } } // Sort the list so that we can link the DataFiles together in the // right order. List<DataFile> list = new ArrayList<DataFile>(fileMap.values()); Collections.sort(list); for (DataFile df : list) { dataFiles.addLast(df); fileByFileMap.put(df.getFile(), df); } // // Need to check the current Write File to see if there was a partial // // write to it. // if (!dataFiles.isEmpty()) { // // // See if the lastSyncedLocation is valid.. // Location l = lastAppendLocation.get(); // if (l != null && l.getDataFileId() != dataFiles.getTail().getDataFileId().intValue()) { // l = null; // } // // // If we know the last location that was ok.. then we can skip lots // // of checking // try { // l = recoveryCheck(dataFiles.getTail(), l); // lastAppendLocation.set(l); // } catch (IOException e) { // LOG.warn("recovery check failed", e); // } // } } public synchronized void close() throws IOException { if (!started) { return; } accessorPool.close(); fileMap.clear(); fileByFileMap.clear(); started = false; } public Location getFirstLocation() throws IllegalStateException, IOException { if( dataFiles.isEmpty() ) { return null; } DataFile first = dataFiles.getHead(); Location cur = new Location(); cur.setDataFileId(first.getDataFileId()); cur.setOffset(0); cur.setSize(0); return getNextLocation(cur); } @Override public synchronized boolean delete() throws IOException { throw new RuntimeException("Cannot delete a ReadOnlyAsyncDataManager"); } }