Java tutorial
// // Copyright (C) 2010-2016 Micromata GmbH // // 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 de.micromata.genome.logging.spi.ifiles; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.sql.Timestamp; import java.util.List; import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import de.micromata.genome.logging.BaseLogging; import de.micromata.genome.logging.EndOfSearch; import de.micromata.genome.logging.LogAttribute; import de.micromata.genome.logging.LogAttributeType; import de.micromata.genome.logging.LogAttributeTypeWrapper; import de.micromata.genome.logging.LogEntry; import de.micromata.genome.logging.LogEntryCallback; import de.micromata.genome.logging.LogLevel; import de.micromata.genome.logging.Logging.OrderBy; import de.micromata.genome.util.types.Pair; /** * * @author Roger Rene Kommer (r.kommer.extern@micromata.de) * */ public class IndexedReader implements Closeable { public static final Charset logCharset = IndexedWriter.logCharset; IndexFileLoggingImpl logger; File logFile; File indexFile; RandomAccessFile idxRandomAccessFile; FileChannel indexChannel;; MappedByteBuffer indexByteBuffer; RandomAccessFile logRandomAccessFile; // FileChannel logChannel;; // MappedByteBuffer logByteBuffer; IndexHeader indexHeader; public IndexedReader(IndexFileLoggingImpl logger, File logFile, File indexFile) throws IOException { this.logger = logger; this.logFile = logFile; this.indexFile = indexFile; idxRandomAccessFile = new RandomAccessFile(indexFile, "r"); indexChannel = idxRandomAccessFile.getChannel(); long chsize = indexChannel.size(); indexByteBuffer = indexChannel.map(FileChannel.MapMode.READ_ONLY, 0, chsize); indexHeader = IndexHeader.openIndexHeader(indexByteBuffer, indexChannel.size()); } public void selectLogsImpl(Timestamp start, Timestamp end, Integer loglevel, String category, String msg, List<Pair<String, String>> logAttributes, int startRow, int maxRow, List<OrderBy> orderBy, boolean masterOnly, LogEntryCallback callback) throws EndOfSearch, IOException { int skipRows = startRow; int rowsSelected = 0; int indexMaxSize = (int) indexChannel.size(); List<Pair<Integer, Integer>> offsets = indexHeader.getCandiates(start, end, indexByteBuffer, indexMaxSize); if (offsets.isEmpty() == true) { return; } logRandomAccessFile = new RandomAccessFile(logFile, "r"); // logChannel = logRandomAccessFile.getChannel(); // logByteBuffer = logChannel.map(FileChannel.MapMode.READ_ONLY, 0, logChannel.size()); if (orderBy != null && orderBy.isEmpty() == false) { } for (Pair<Integer, Integer> offset : offsets) { if (rowsSelected >= maxRow) { return; } if (apply(offset.getFirst(), loglevel, category, msg, logAttributes) == false) { continue; } if (skipRows > 0) { --skipRows; continue; } callback.onRow(select(offset.getFirst(), masterOnly)); ++rowsSelected; } } boolean apply(Integer offset, Integer loglevel, String category, String msg, List<Pair<String, String>> logAttributes) throws IOException { String s; if (loglevel != null) { s = indexHeader.readSearchFromLog(offset, logRandomAccessFile, StdSearchFields.Level.name()); if (s != null) { LogLevel ll = LogLevel.fromString(s, LogLevel.Fatal); if (ll.getLevel() < loglevel) { return false; } } } if (category != null) { s = indexHeader.readSearchFromLog(offset, logRandomAccessFile, StdSearchFields.Category.name()); if (s != null) { if (StringUtils.containsIgnoreCase(s, category) == false) { return false; } } } if (msg != null) { s = indexHeader.readSearchFromLog(offset, logRandomAccessFile, StdSearchFields.ShortMessage.name()); if (s != null) { if (StringUtils.containsIgnoreCase(s, msg) == false) { return false; } } } if (logAttributes == null || logAttributes.isEmpty() == true) { return true; } for (Pair<String, String> attr : logAttributes) { s = indexHeader.readSearchFromLog(offset, logRandomAccessFile, attr.getFirst()); if (StringUtils.containsIgnoreCase(s, attr.getSecond()) == false) { return false; } } return true; } private LogAttribute createLogAttribute(String name, String value) { Map<String, LogAttributeType> map = BaseLogging.getRegisterdLogAttributes(); LogAttributeType attrt = map.get(name); if (attrt == null) { attrt = new LogAttributeTypeWrapper(name); } return new LogAttribute(attrt, value); } private long buildLogPk(int offset) { return IndexDirectory.buildLogIdByIndexDirectoryAndOffset(indexHeader.indexDirectoryIdx, offset); } private boolean seekNextLine(int fromPos) throws IOException { logRandomAccessFile.seek(fromPos); int ch; while ((ch = logRandomAccessFile.read()) != -1) { if (ch == '\n') { long curpos = logRandomAccessFile.getFilePointer(); ch = logRandomAccessFile.read(); if (ch == -1) { return false; } if (ch == '\r') { return true; } else { logRandomAccessFile.seek(curpos); return true; } } } return false; } public LogEntry select(int startOffset, boolean masterOnly) throws IOException { if (logRandomAccessFile == null) { logRandomAccessFile = new RandomAccessFile(logFile, "r"); // logChannel = logRandomAccessFile.getChannel(); // logByteBuffer = logChannel.map(FileChannel.MapMode.READ_ONLY, 0, logChannel.size()); } LogEntry le = new LogEntry(); le.setLogEntryIndex(buildLogPk(startOffset)); logRandomAccessFile.seek(startOffset); for (Pair<String, Integer> pair : indexHeader.headerOrder) { String name = pair.getFirst(); Integer length = pair.getSecond(); String value = NIOUtils.readString(logRandomAccessFile, length, logCharset); logRandomAccessFile.read(); // | character StdSearchFields sf = StdSearchFields.findFromString(name); if (sf != null) { sf.getValueSetter().accept(le, value); } else { le.getAttributes().add(createLogAttribute(name, value)); } } if (masterOnly == true) { return le; } if (seekNextLine(startOffset) == false) { return le; } int ch; do { ch = logRandomAccessFile.read(); if (ch != '@') { break; } LogAttribute attr = parseLogAttributeFromPos(); if (attr == null) { break; } if (attr.getType().name().equals("message") == true) { le.setMessage(attr.getValue()); } else { le.getAttributes().add(attr); } } while (ch != -1); return le; } private LogAttribute parseLogAttributeFromPos() throws IOException { StringBuilder key = new StringBuilder(); int ch = 0; boolean keyFound = false; while (keyFound == false && ch != -1) { ch = logRandomAccessFile.read(); switch (ch) { case -1: return null; case '\r': case '\n': return null; case ':': keyFound = true; break; default: key.append((char) ch); break; } } if (key.length() == 0) { return null; } StringBuilder value = new StringBuilder(); boolean valueFound = false; while (valueFound == false && ch != -1) { ch = logRandomAccessFile.read(); switch (ch) { case '\n': long cpos = logRandomAccessFile.getFilePointer(); ch = logRandomAccessFile.read(); if (ch == '\r') { ++cpos; ch = logRandomAccessFile.read(); } if (ch == '\t') { value.append("\n"); continue; } else { logRandomAccessFile.seek(cpos); valueFound = true; break; } default: value.append((char) ch); break; } } String skey = key.toString(); String svalue = value.toString(); if (skey.startsWith(" ") == true) { skey = skey.substring(1); } if (svalue.startsWith(" ") == true) { svalue = svalue.substring(1); } return createLogAttribute(skey, svalue); } @Override public void close() throws IOException { NIOUtils.unmap(indexChannel, indexByteBuffer); // NIOUtils.unmap(logChannel, logByteBuffer); IOUtils.closeQuietly(indexChannel); IOUtils.closeQuietly(idxRandomAccessFile); // IOUtils.closeQuietly(logChannel); IOUtils.closeQuietly(logRandomAccessFile); } }