1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-05-07 20:45:53 +08:00

feat: unified writing/reading table

These changes table reading/writing to single read/write operation,
and layout to machine byteorder, so db file will be unsupported with
wrong byteorder.
This commit is contained in:
wdvxdr 2021-09-28 16:43:50 +08:00
parent d620fce1ae
commit 4da6584f10
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
2 changed files with 34 additions and 90 deletions

View File

@ -12,8 +12,8 @@ import (
const ( const (
sha1Size = 20 // md5 sha1 sha1Size = 20 // md5 sha1
tableSize = (4096 - 1) / int(unsafe.Sizeof(item{})) tableSize = (2048 - 1) / int(unsafe.Sizeof(item{}))
cacheSlots = 23 // prime cacheSlots = 13 // prime
superSize = int(unsafe.Sizeof(super{})) superSize = int(unsafe.Sizeof(super{}))
tableStructSize = int(unsafe.Sizeof(table{})) tableStructSize = int(unsafe.Sizeof(table{}))
) )

View File

@ -1,8 +1,8 @@
package btree package btree
import ( import (
"encoding/binary"
"io" "io"
"reflect"
"unsafe" "unsafe"
) )
@ -47,119 +47,63 @@ func resetsha1(sha1 *byte) {
// reading table // reading table
func read64(r io.Reader) (int64, error) {
var b = make([]byte, 8)
_, err := r.Read(b)
if err != nil {
return 0, err
}
return int64(binary.LittleEndian.Uint64(b)), nil
}
func read32(r io.Reader) (int32, error) { func read32(r io.Reader) (int32, error) {
var b = make([]byte, 4) var b = make([]byte, 4)
_, err := r.Read(b) _, err := r.Read(b)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return int32(binary.LittleEndian.Uint32(b)), nil return *(*int32)(unsafe.Pointer(&b[0])), nil
} }
func readTable(r io.Reader, t *table) error { func readTable(r io.Reader, t *table) error {
for i := 0; i < tableSize; i++ { buf := make([]byte, tableStructSize)
err := readItem(r, &t.items[i]) _, err := r.Read(buf)
if err != nil {
return err
}
}
switch unsafe.Sizeof(0) {
case 8:
i, err := read64(r)
t.size = int(i)
return err
case 4:
i, err := read32(r)
t.size = int(i)
return err
default:
panic("unreachable")
}
}
func readItem(r io.Reader, i *item) error {
_, err := r.Read(i.sha1[:])
if err != nil { if err != nil {
return err return err
} }
i.offset, err = read64(r) *t = *(*table)(unsafe.Pointer(&buf[0]))
if err != nil { return nil
return err
}
i.child, err = read64(r)
return err
} }
func readSuper(r io.Reader, s *super) error { func readSuper(r io.Reader, s *super) error {
var err error buf := make([]byte, superSize)
if s.top, err = read64(r); err != nil { _, err := r.Read(buf)
if err != nil {
return err return err
} }
if s.freeTop, err = read64(r); err != nil { *s = *(*super)(unsafe.Pointer(&buf[0]))
return err return nil
}
s.alloc, err = read64(r)
return err
} }
// write table // write table
func write64(w io.Writer, i int64) error { func write32(w io.Writer, t int32) error {
var b = make([]byte, 8) var p []byte
binary.LittleEndian.PutUint64(b, uint64(i)) ph := (*reflect.SliceHeader)(unsafe.Pointer(&p))
_, err := w.Write(b) ph.Data = uintptr(unsafe.Pointer(&t))
return err ph.Len = 4
} ph.Cap = 4
_, err := w.Write(p)
func write32(w io.Writer, i int32) error {
var b = make([]byte, 4)
binary.LittleEndian.PutUint32(b, uint32(i))
_, err := w.Write(b)
return err return err
} }
func writeTable(w io.Writer, t *table) error { func writeTable(w io.Writer, t *table) error {
for i := 0; i < tableSize; i++ { var p []byte
err := writeItem(w, &t.items[i]) ph := (*reflect.SliceHeader)(unsafe.Pointer(&p))
if err != nil { ph.Data = uintptr(unsafe.Pointer(t))
return err ph.Len = tableStructSize
} ph.Cap = tableStructSize
} _, err := w.Write(p)
switch unsafe.Sizeof(0) { return err
case 8:
return write64(w, int64(t.size))
case 4:
return write32(w, int32(t.size))
default:
panic("unreachable")
}
}
func writeItem(w io.Writer, i *item) error {
if _, err := w.Write(i.sha1[:]); err != nil {
return err
}
if err := write64(w, i.offset); err != nil {
return err
}
return write64(w, i.child)
} }
func writeSuper(w io.Writer, s *super) error { func writeSuper(w io.Writer, s *super) error {
if err := write64(w, s.top); err != nil { var p []byte
return err ph := (*reflect.SliceHeader)(unsafe.Pointer(&p))
} ph.Data = uintptr(unsafe.Pointer(s))
if err := write64(w, s.freeTop); err != nil { ph.Len = superSize
return err ph.Cap = superSize
} _, err := w.Write(p)
return write64(w, s.alloc) return err
} }