1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| package main
import ( "os" "sort" "syscall" )
const bufferSize = 1024 * 1024 * 1024
type File struct { fd int offset int64 size int }
func main() { storage := make(map[string][]*File)
if err := readFiles(storage); err != nil { panic(err) }
keys := make([]string, 0, len(storage)) for key := range storage { keys = append(keys, key) } sort.Strings(keys)
resultFd, err := syscall.Open("result", syscall.O_WRONLY|syscall.O_CREAT, 0644) if err != nil { panic(err) } defer syscall.Close(resultFd)
for _, key := range keys { files := storage[key] for _, file := range files { if _, err := syscall.Seek(file.fd, file.offset, 0); err != nil { panic(err) } buffer := make([]byte, file.size) if _, err := syscall.Read(file.fd, buffer); err != nil { panic(err) } if _, err := syscall.Write(resultFd, buffer[:file.size]); err != nil { panic(err) } } }
for _, files := range storage { for _, file := range files { syscall.Close(file.fd) } } }
func readFiles(storage map[string][]*File) error { files, err := os.ReadDir("data") if err != nil { return err }
for _, entry := range files { fd, err := syscall.Open("data/"+entry.Name(), syscall.O_RDONLY, 0) if err != nil { return err }
buffer := make([]byte, bufferSize) var lineBuffer []byte var offset int64
for { n, err := syscall.Read(fd, buffer) if err != nil { return err } if n == 0 { break }
for i := 0; i < n; i++ { if buffer[i] == '\n' { key := string(lineBuffer)[:3] storage[key] = append(storage[key], &File{fd: fd, offset: offset - int64(len(lineBuffer)), size: len(lineBuffer) + 1}) lineBuffer = nil } else { lineBuffer = append(lineBuffer, buffer[i]) } offset += 1 } } } return nil }
|