package com.wenweihu86.raft.storage;

import com.wenweihu86.raft.proto.Raft;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * Created by wenweihu86 on 2017/5/3.
 */
public class SegmentedLog {

    private static Logger LOG = LoggerFactory.getLogger(SegmentedLog.class);

    private String logDir;

    public List<Segment> readSegments() {
        File dir = new File(getClass().getResource(logDir).getFile());
        File[] files = dir.listFiles();
        Arrays.sort(files, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                if (o1.isDirectory() && o2.isFile()) {
                    return -1;
                }
                if (o1.isFile() && o2.isDirectory()) {
                    return 1;
                }
                return o2.getName().compareTo(o1.getName());
            }
        });

        List<Segment> segments = new ArrayList<>();
        for (File file : files) {
            if (file.getName().equals("metadata1")
                    || file.getName().equals("metadata2")) {
                continue;
            }
            String fileName = file.getName();
            String[] splitArray = fileName.split("-");
            if (splitArray.length != 2) {
                LOG.warn("segment filename[{}] is not valid", fileName);
                continue;
            }
            Segment segment = new Segment();
            segment.setFileName(file.getName());
            segment.setFileSize(0);
            if (splitArray[0].equals("open")) {
                segment.setOpen(true);
                segment.setStartIndex(-1);
                segment.setEndIndex(-1);
                segments.add(segment);
            } else {
                try {
                    segment.setStartIndex(Long.parseLong(splitArray[0]));
                    segment.setEndIndex(Long.parseLong(splitArray[1]));
                    segment.setOpen(false);
                    segments.add(segment);
                } catch (NumberFormatException ex) {
                    LOG.warn("segment filename[{}] is not valid", fileName);
                    continue;
                }
            }
        }
        return segments;
    }

    public Raft.Metadata readMetadata(String fileName) {
        String filePath = logDir + File.pathSeparator + fileName;
        try {
            File file = new File(getClass().getResource(filePath).getFile());
            FileInputStream inputStream = new FileInputStream(file);
            // TODO
        } catch (FileNotFoundException ex) {
            LOG.warn("meta file not exist, name={}", filePath);
            return null;
        }
        return null;
    }

}

@@ -31,16 +31,46 @@
 orage;%0A%0A
+import com.google.protobuf.*;%0A
 import c
@@ -173,20 +173,17 @@
 java.io.
-File
+*
 ;%0Aimport
@@ -192,64 +192,55 @@
 ava.
-io.FileInputStream;%0Aimport java.io.FileNotFoundException
+lang.reflect.*;%0Aimport java.lang.reflect.Method
 ;%0Aim
@@ -341,16 +341,44 @@
 il.List;
+%0Aimport java.util.zip.CRC32;
 %0A%0A/**%0A *
@@ -2700,62 +2700,74 @@
     
-FileInputStream inputStream = new FileInputStream(file
+RandomAccessFile randomAccessFile = new RandomAccessFile(file, %22r%22
 );%0A 
@@ -2921,32 +2921,32 @@
 null;%0A        %7D%0A
-
         return n
@@ -2957,10 +2957,1193 @@
 %0A    %7D%0A%0A
+    public %3CT extends GeneratedMessageV3%3E T readProtoFromFile(RandomAccessFile raf, Class%3CT%3E clazz) %7B%0A        try %7B%0A            long checksum = raf.readLong();%0A            int dataLen = raf.readInt();%0A            int hasReadLen = Long.SIZE / Byte.SIZE + Integer.SIZE / Byte.SIZE;%0A%0A            if (raf.length() - hasReadLen %3C dataLen) %7B%0A                LOG.warn(%22file remainLength %3C dataLen%22);%0A                return null;%0A            %7D%0A            byte%5B%5D data = new byte%5BdataLen%5D;%0A            int readLen = raf.read(data);%0A            if (readLen != dataLen) %7B%0A                LOG.warn(%22readLen != dataLen%22);%0A                return null;%0A            %7D%0A%0A            CRC32 crc32Obj = new CRC32();%0A            crc32Obj.update(data);%0A            if (crc32Obj.getValue() != checksum) %7B%0A                LOG.warn(%22crc32 check failed%22);%0A                return null;%0A            %7D%0A%0A            Method method = clazz.getMethod(%22parseFrom%22, byte%5B%5D.class);%0A            T message = (T) method.invoke(clazz, data);%0A            return message;%0A        %7D catch (Exception ex) %7B%0A            LOG.warn(%22readProtoFromFile meet exception, %7B%7D%22, ex.getMessage());%0A            return null;%0A        %7D%0A    %7D%0A%0A
 %7D%0A

add readProtoFromFile