package jocket.net;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode;

import jocket.impl.Const;
import jocket.impl.JocketReader;
import jocket.impl.JocketWriter;

/**
 * Creates or opens an exchange file wrapped in a mapped byte buffer and makes
 * it easy to obtain a JocketReader or JocketWriter instance.
 * 
 * @author pcdv
 */
public class JocketFile {

  private final MappedByteBuffer buf;
  private final RandomAccessFile io;
  private final JocketReader reader;
  private final JocketWriter writer;
  private final int npackets;
  private final int size;
  private final File file;

  public JocketFile() throws IOException {
    this(File.createTempFile("jocket", ""), true);
    file.deleteOnExit();
  }

  public JocketFile(File file, boolean create) throws IOException {
    if (!create && !file.exists())
      throw new FileNotFoundException("File does not exist");

    this.file = file;
    this.io = new RandomAccessFile(file, "rw");

    // TODO: this information should be configurable (in create mode) or
    // present in file (in !create mode)
    this.npackets = 1024;
    this.size = 1024 * 1024 + Const.PACKET_INFO + npackets
        * Const.LEN_PACKET_INFO;

    if (create) {
      io.setLength(0);
      io.setLength(size);
    }

    this.buf = io.getChannel().map(MapMode.READ_WRITE, 0, size);
    this.reader = new JocketReader(buf, npackets);
    this.writer = new JocketWriter(buf, npackets);
  }

  public JocketReader reader() {
    return reader;
  }

  public JocketWriter writer() {
    return writer;
  }

  public String getPath() {
    return file.getAbsolutePath();
  }

  /**
   * Deletes the file to make it harder to sniff stream. Can be called (at least
   * under linux) after both endpoints have opened the file.
   */
  public void deleteFile() {
    file.delete();
  }
}

@@ -208,16 +208,79 @@
 nnel
-.MapMode
+;%0Aimport java.nio.channels.FileChannel.MapMode;%0Aimport java.util.Random
 ;%0A%0Ai
@@ -856,74 +856,374 @@
 his(
-File.createTempFile(%22jocket%22, %22%22), true);%0A    file.deleteOnExit();
+createTempFile(), true);%0A    file.deleteOnExit();%0A  %7D%0A%0A  private static File createTempFile() throws IOException %7B%0A    try %7B%0A      // under linux, try to use tmpfs%0A      File dir = new File(%22/dev/shm%22);%0A      return new File(dir, %22jocket-%22 + new Random().nextInt(Integer.MAX_VALUE));%0A    %7D catch (Exception ex) %7B%0A      return File.createTempFile(%22jocket%22, %22%22);%0A    %7D
 %0A  %7D
@@ -1776,66 +1776,138 @@
     
-this.buf = io.getChannel().map(MapMode.READ_WRITE, 0, size
+FileChannel channel = io.getChannel();%0A    this.buf = channel.map(MapMode.READ_WRITE, 0, size);%0A    buf.load();%0A    channel.close(
 );%0A 

use tmpfs when under linux