Exemplo n.º 1
0
 public static String toHex(IoBuffer buffer) {
   if (buffer == null) return null;
   if (buffer.limit() < 16) throw new RuntimeException("buffer不中不够16个指纹");
   int j = 16;
   char str[] = new char[j * 2];
   int k = 0;
   for (int i = 0; i < j; i++) {
     byte byte0 = buffer.get();
     str[k++] = hexDigits[byte0 >>> 4 & 0xf];
     str[k++] = hexDigits[byte0 & 0xf];
   }
   return new String(str);
 }
Exemplo n.º 2
0
  @Override
  public void run() {
    try {
      while (!this.shutdown) {
        try {
          FileChannel fc = this.scanner.getCurrChannel(this.checkPoint.getLastModify());
          if (fc == null) {
            Thread.sleep(this.logConfig.timeout);
            continue;
          }
          long position = this.getPosition(fc);
          // 定位到上一次读的位置
          fc.position(position);
          IoBuffer buf = IoBuffer.allocate(this.config.getMaxBufSize());
          int read = fc.read(buf.buf());
          if (read == -1) {
            if (this.scanner.getQueueSize() > 1) {
              this.checkPoint.setPosition(0);
              this.checkPoint.save();
              this.scanner.closeChannel();
              if (this.testFileChannel != null) {
                this.testFileChannel.close();
                this.testFileChannel = null;
              }
              continue;
            } else {
              Thread.sleep(this.logConfig.timeout);
              continue;
            }
          }
          buf.flip();
          MatchResult result = null;
          int sent = 0;
          while ((result = this.match(buf)) != null) {
            int index = result.index;
            if (index >= 0) {
              byte[] data = new byte[index - buf.position() + result.skip];
              buf.get(data);
              try {
                this.send(data);
                sent += data.length;
              } catch (InterruptedException e) {
                throw e;
              } catch (Exception e) {
                log.error("Send message failed", e);
                break;
              }
            } else {
              break;
            }
          }
          // 递增位置
          position += sent;
          // check point
          if (sent > 0) {
            this.checkPoint.setPosition(position);
            this.checkPoint.save();
          }
        } catch (InterruptedException e) {

        } catch (IOException t) {
          log.error("读取文件失败", t);
        } catch (Throwable t) {
          log.error("tail4j运行错误", t);
        }
      }
    } finally {
      this.close();
    }
  }
Exemplo n.º 3
0
/** @author boyan @Date 2011-5-17 */
public class Tail extends Thread {
  private final Scanner scanner;
  private final CheckPoint checkPoint;
  private final Sender sender;
  private volatile boolean shutdown = false;
  static final Log log = LogFactory.getLog(Tail.class);
  private final Config config;
  private final LogConfig logConfig;

  static final ByteBufferMatcher[] matchers = {
    new ShiftAndByteBufferMatcher(IoBuffer.wrap("\r\n".getBytes())),
    new ShiftAndByteBufferMatcher(IoBuffer.wrap("\n".getBytes())),
    new ShiftAndByteBufferMatcher(IoBuffer.wrap("\r".getBytes()))
  };

  static final int[] skips = {2, 1, 1};

  public Tail(Config config, LogConfig logConfig, MessageSessionFactory sessionFactory)
      throws IOException {
    this.scanner = new Scanner(logConfig);
    this.sender = new Sender(logConfig, sessionFactory.createProducer(logConfig.ordered));
    this.checkPoint = new CheckPoint(config, logConfig);
    this.config = config;
    this.logConfig = logConfig;
  }

  public void shutdown() {
    this.shutdown = true;
  }

  @Override
  public void run() {
    try {
      while (!this.shutdown) {
        try {
          FileChannel fc = this.scanner.getCurrChannel(this.checkPoint.getLastModify());
          if (fc == null) {
            Thread.sleep(this.logConfig.timeout);
            continue;
          }
          long position = this.getPosition(fc);
          // 定位到上一次读的位置
          fc.position(position);
          IoBuffer buf = IoBuffer.allocate(this.config.getMaxBufSize());
          int read = fc.read(buf.buf());
          if (read == -1) {
            if (this.scanner.getQueueSize() > 1) {
              this.checkPoint.setPosition(0);
              this.checkPoint.save();
              this.scanner.closeChannel();
              if (this.testFileChannel != null) {
                this.testFileChannel.close();
                this.testFileChannel = null;
              }
              continue;
            } else {
              Thread.sleep(this.logConfig.timeout);
              continue;
            }
          }
          buf.flip();
          MatchResult result = null;
          int sent = 0;
          while ((result = this.match(buf)) != null) {
            int index = result.index;
            if (index >= 0) {
              byte[] data = new byte[index - buf.position() + result.skip];
              buf.get(data);
              try {
                this.send(data);
                sent += data.length;
              } catch (InterruptedException e) {
                throw e;
              } catch (Exception e) {
                log.error("Send message failed", e);
                break;
              }
            } else {
              break;
            }
          }
          // 递增位置
          position += sent;
          // check point
          if (sent > 0) {
            this.checkPoint.setPosition(position);
            this.checkPoint.save();
          }
        } catch (InterruptedException e) {

        } catch (IOException t) {
          log.error("读取文件失败", t);
        } catch (Throwable t) {
          log.error("tail4j运行错误", t);
        }
      }
    } finally {
      this.close();
    }
  }

  private void close() {
    try {
      this.scanner.close();
      this.sender.close();
      this.checkPoint.close();
      if (this.testFileChannel != null) {
        this.testFileChannel.close();
      }
    } catch (IOException e) {
      log.error("Close failed", e);
    }
  }

  private FileChannel testFileChannel;

  private void send(byte[] data) throws IOException, InterruptedException {
    String currentLogPath = this.scanner.getCurrLogFile().getAbsolutePath();
    // 是否使用测试目录
    if (!StringUtils.isBlank(this.config.getTestPath())) {
      // 求相对路径
      String canonicalPath = currentLogPath.substring(this.logConfig.logBasePath.length());

      if (this.testFileChannel == null) {
        final File file = new File(this.config.getTestPath() + File.separator + canonicalPath);
        File parent = file.getParentFile();
        if (!parent.exists()) {
          parent.mkdirs();
        }
        if (!file.exists()) {
          file.createNewFile();
        }
        this.testFileChannel = new RandomAccessFile(file, "rw").getChannel();
        // move to tail
        this.testFileChannel.position(this.testFileChannel.size());
      }
      final ByteBuffer buf = ByteBuffer.wrap(data);
      while (buf.hasRemaining()) {
        this.testFileChannel.write(buf);
      }

    } else {
      this.sender.send(data, currentLogPath);
    }
  }

  private long getPosition(FileChannel fc) throws IOException {
    String savePos = this.checkPoint.getPosition();
    long result = 0L;
    if (!StringUtils.isBlank(savePos)) {
      result = Long.parseLong(savePos);
    }
    if (result == 0) {
      this.checkPoint.setLastModify(this.scanner.getCurrLogFile().lastModified());
    }
    return result;
  }

  private static class MatchResult {
    int index;
    int skip;

    public MatchResult(int index, int skip) {
      super();
      this.index = index;
      this.skip = skip;
    }
  }

  public MatchResult match(IoBuffer buf) {
    int i = 0;
    for (ByteBufferMatcher matcher : matchers) {
      int index = matcher.matchFirst(buf);
      i++;
      if (index >= 0) {
        return new MatchResult(index, skips[i - 1]);
      }
    }
    return new MatchResult(-1, 0);
  }
}
Exemplo n.º 4
0
 @Override
 public IoBuffer encode() {
   return IoBuffer.wrap(
       (MetaEncodeCommand.VERSION_CMD + " " + this.getOpaque() + "\r\n").getBytes());
 }