NewStorage creates a new storage
(chunkSize int64, maxChunks int, maxMmapSize int64, chunkFilePath string)
| 57 | |
| 58 | // NewStorage creates a new storage |
| 59 | func NewStorage(chunkSize int64, maxChunks int, maxMmapSize int64, chunkFilePath string) (*Storage, error) { |
| 60 | s := Storage{ |
| 61 | ChunkSize: chunkSize, |
| 62 | MaxChunks: maxChunks, |
| 63 | chunks: make(map[RequestID]int, maxChunks), |
| 64 | stack: NewStack(maxChunks), |
| 65 | buffers: make([]*Chunk, maxChunks, maxChunks), |
| 66 | signals: make(chan os.Signal, 1), |
| 67 | } |
| 68 | |
| 69 | journalSize := tocSize + int64(headerSize*maxChunks) |
| 70 | journalOffset := chunkSize * int64(maxChunks) |
| 71 | |
| 72 | // Non-empty string in chunkFilePath enables MMAP disk storage for chunks |
| 73 | if chunkFilePath != "" { |
| 74 | chunkFile, err := os.OpenFile(chunkFilePath, os.O_RDWR|os.O_CREATE, 0600) |
| 75 | if nil != err { |
| 76 | Log.Debugf("%v", err) |
| 77 | return nil, fmt.Errorf("Could not open chunk cache file") |
| 78 | } |
| 79 | s.ChunkFile = chunkFile |
| 80 | currentSize, err := chunkFile.Seek(0, os.SEEK_END) |
| 81 | if nil != err { |
| 82 | Log.Debugf("%v", err) |
| 83 | return nil, fmt.Errorf("Chunk file is not seekable") |
| 84 | } |
| 85 | wantedSize := journalOffset + journalSize |
| 86 | Log.Debugf("Current chunk cache file size: %v B (wanted: %v B)", currentSize, wantedSize) |
| 87 | if err := chunkFile.Truncate(currentSize); nil != err { |
| 88 | Log.Warningf("Could not truncate chunk cache, skip resizing") |
| 89 | } else if currentSize != wantedSize { |
| 90 | if currentSize > tocSize { |
| 91 | err = s.relocateJournal(currentSize, wantedSize, journalSize, journalOffset) |
| 92 | if nil != err { |
| 93 | Log.Errorf("%v", err) |
| 94 | } else { |
| 95 | Log.Infof("Relocated chunk cache journal") |
| 96 | } |
| 97 | } |
| 98 | if err := chunkFile.Truncate(wantedSize); nil != err { |
| 99 | Log.Debugf("%v", err) |
| 100 | return nil, fmt.Errorf("Could not resize chunk cache file") |
| 101 | } |
| 102 | } |
| 103 | Log.Infof("Created chunk cache file %v", chunkFile.Name()) |
| 104 | s.loadChunks = int(min(currentSize/chunkSize, int64(maxChunks))) |
| 105 | } |
| 106 | |
| 107 | // Alocate journal |
| 108 | if journal, err := s.mmap(journalOffset, journalSize); nil != err { |
| 109 | return nil, fmt.Errorf("Could not allocate journal: %v", err) |
| 110 | } else { |
| 111 | if err := unix.Madvise(journal, syscall.MADV_RANDOM); nil != err { |
| 112 | Log.Warningf("Madvise MADV_RANDOM for journal failed: %v", err) |
| 113 | } |
| 114 | tocOffset := journalSize - tocSize |
| 115 | header := journal[tocOffset:] |
| 116 | if valid := s.checkJournal(header, false); !valid { |
no test coverage detected