X-Git-Url: http://git.giacomolli.uk/onechat/blobdiff_plain/feda522eba3e2a27c91741c77d0d01f1840c0004..0a98ccb:/records.go?ds=sidebyside diff --git a/records.go b/records.go index 73a9d83..abd88a8 100644 --- a/records.go +++ b/records.go @@ -11,19 +11,9 @@ import ( // positionBytes is the size of an encoded position. const positionBytes = 16 -// records is a file of fixed-size records, numbered from 0. Record n starts at -// byte n*size. A record that was never written reads as zeros. An index is data -// that the day files can give again, so records cuts a partial record at the -// end of the file. -type records struct { - file *os.File - size int - count int -} - // openRecords opens or creates the record file at path with records of size // bytes. -func openRecords(path string, size int) (*records, error) { +func openRecords(path string, size int) (*Records, error) { file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600) if err != nil { return nil, fmt.Errorf("open index: %w", err) @@ -34,7 +24,7 @@ func openRecords(path string, size int) (*records, error) { return nil, errors.Join(fmt.Errorf("read index size: %w", err), file.Close()) } - r := &records{ + r := &Records{ file: file, size: size, count: int(info.Size()) / size, @@ -50,8 +40,34 @@ func openRecords(path string, size int) (*records, error) { return r, nil } +// encodePosition writes place into the first positionBytes bytes of record. +func encodePosition(record []byte, place Position) { + binary.LittleEndian.PutUint32(record[0:], place.day) + binary.LittleEndian.PutUint32(record[4:], place.length) + binary.LittleEndian.PutUint64(record[8:], place.offset) +} + +// decodePosition reads a position from the first positionBytes bytes of record. +func decodePosition(record []byte) Position { + return Position{ + day: binary.LittleEndian.Uint32(record[0:]), + length: binary.LittleEndian.Uint32(record[4:]), + offset: binary.LittleEndian.Uint64(record[8:]), + } +} + +// Records is a file of fixed-size Records, numbered from 0. Record n starts at +// byte n*size. A record that was never written reads as zeros. An index is data +// that the day files can give again, so Records cuts a partial record at the +// end of the file. +type Records struct { + file *os.File + size int + count int +} + // Read returns record n, or false when the file does not reach it. -func (r *records) Read(n int) ([]byte, bool, error) { +func (r *Records) Read(n int) ([]byte, bool, error) { if n >= r.count { return nil, false, nil } @@ -66,7 +82,7 @@ func (r *records) Read(n int) ([]byte, bool, error) { } // Write writes record n. -func (r *records) Write(n int, record []byte) error { +func (r *Records) Write(n int, record []byte) error { _, err := r.file.WriteAt(record, int64(n*r.size)) if err != nil { return fmt.Errorf("write index record %d: %w", n, err) @@ -78,27 +94,11 @@ func (r *records) Write(n int, record []byte) error { } // Append writes the record after the last one. -func (r *records) Append(record []byte) error { +func (r *Records) Append(record []byte) error { return r.Write(r.count, record) } // Close closes the file. -func (r *records) Close() error { +func (r *Records) Close() error { return r.file.Close() } - -// encodePosition writes place into the first positionBytes bytes of record. -func encodePosition(record []byte, place position) { - binary.LittleEndian.PutUint32(record[0:], place.day) - binary.LittleEndian.PutUint32(record[4:], place.length) - binary.LittleEndian.PutUint64(record[8:], place.offset) -} - -// decodePosition reads a position from the first positionBytes bytes of record. -func decodePosition(record []byte) position { - return position{ - day: binary.LittleEndian.Uint32(record[0:]), - length: binary.LittleEndian.Uint32(record[4:]), - offset: binary.LittleEndian.Uint64(record[8:]), - } -}