/******************************************************************************* * Copyright (c) 2015 Ericsson * * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bernd Hufmann - Initial API and implementation *******************************************************************************/ package org.eclipse.tracecompass.ctf.core.trace; import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.ctf.core.CTFException; import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer; import org.eclipse.tracecompass.internal.ctf.core.trace.StreamInputPacketIndex; /** * A CTF Stream output writer. Reads the packets of a given CTFStreamInput and * writes packets that are within a given time range to output stream file. * * @author Bernd Hufmann * @since 1.0 */ public class CTFStreamOutputWriter { // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ // Stream input when copying stream from an input // It is @Nullable for future implementations that doesn't use an input // stream @Nullable private final CTFStreamInput fStreamInput; @NonNull private final CTFStreamPacketOutputWriter fStreamPacketOutputWriter; @NonNull private final File fOutFile; // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ /** * Constructs a StreamInput. * * @param streamInput * The stream to which this StreamInput belongs to. * @param file * The output trace directory. * @throws CTFException * If a reading or writing error occurs */ public CTFStreamOutputWriter(@NonNull CTFStreamInput streamInput, @NonNull File file) throws CTFException { fStreamInput = streamInput; String inFileName = streamInput.getFile().getName(); Path outFilePath = FileSystems.getDefault().getPath(file.getAbsolutePath(), inFileName); try { fOutFile = checkNotNull(Files.createFile(outFilePath).toFile()); } catch (IOException e) { throw new CTFIOException("Output file can't be created: " + outFilePath, e); //$NON-NLS-1$ } fStreamPacketOutputWriter = new CTFStreamPacketOutputWriter(); } /** * Copies packets from the relevant input this input stream to a * corresponding output stream based on a given time range. The following * condition has to be met so that a packet is written to the output stream: * * startTime <= packet.getTimestampEnd() && packet.getTimestampStart() <= endTime * * @param startTime * the start time for packets to be written * @param endTime * the end time for packets to be written * @throws CTFException * if a reading or writing error occurs * @since 1.0 */ public void copyPackets(long startTime, long endTime) throws CTFException { CTFStreamInput streamInput = fStreamInput; if (streamInput == null) { throw new CTFIOException("StreamInput is null. Can't copy packets"); //$NON-NLS-1$ } try (FileChannel fc = checkNotNull(FileChannel.open(fOutFile.toPath(), StandardOpenOption.WRITE))) { StreamInputPacketIndex index = streamInput.getIndex(); int count = 0; try (FileChannel source = FileChannel.open(streamInput.getFile().toPath(), StandardOpenOption.READ)) { for (int i = 0; i < index.size(); i++) { ICTFPacketDescriptor entry = index.getElement(i); if ((entry.getTimestampEnd() >= startTime) && (entry.getTimestampBegin() <= endTime)) { ByteBuffer buffer = SafeMappedByteBuffer.map(source, MapMode.READ_ONLY, entry.getOffsetBytes(), entry.getPacketSizeBits() / Byte.SIZE); fStreamPacketOutputWriter.writePacket(buffer, fc); count++; } } } if (count == 0 && fOutFile.exists()) { boolean deleteResult = fOutFile.delete(); if (!deleteResult) { throw new CTFIOException("Could not delete " + fOutFile.getAbsolutePath()); //$NON-NLS-1$ } } } catch (IOException e) { throw new CTFIOException("Error copying packets: " + e.toString(), e); //$NON-NLS-1$ } } /** * Get the stream file to write. * * @return the stream file to write */ public File getOutFile() { return fOutFile; } }