// Seek implements http.File. func (f *HTTPFile) Seek(offset int64, whence int) (int64, error) { if f.closed { return 0, os.ErrInvalid } if offset < 0 { return int64(f.off), fmt.Errorf("cannot seek before start of file") } switch whence { case 0: noff := int64(f.off) + offset if noff > mathutil.MaxInt { return int64(f.off), fmt.Errorf("seek target overflows int: %d", noff) } f.off = mathutil.Min(int(offset), len(f.content)) if f.off == int(offset) { return offset, nil } return int64(f.off), io.EOF case 1: noff := int64(f.off) + offset if noff > mathutil.MaxInt { return int64(f.off), fmt.Errorf("seek target overflows int: %d", noff) } off := mathutil.Min(f.off+int(offset), len(f.content)) if off == f.off+int(offset) { f.off = off return int64(off), nil } f.off = off return int64(off), io.EOF case 2: noff := int64(f.off) - offset if noff < 0 { return int64(f.off), fmt.Errorf("cannot seek before start of file") } f.off = len(f.content) - int(offset) return int64(f.off), nil default: return int64(f.off), fmt.Errorf("seek: invalid whence %d", whence) } }
func (f *bitFiler) ReadAt(b []byte, off int64) (n int, err error) { avail := f.size - off pgI := off >> bfBits pgO := int(off & bfMask) rem := len(b) if int64(rem) >= avail { rem = int(avail) err = io.EOF } for rem != 0 && avail > 0 { pg := f.m[pgI] if pg == nil { pg = &bitPage{} if f.parent != nil { _, err = f.parent.ReadAt(pg.data[:], off&^bfMask) if err != nil && !fileutil.IsEOF(err) { return } err = nil } f.m[pgI] = pg } nc := copy(b[:mathutil.Min(rem, bfSize)], pg.data[pgO:]) pgI++ pgO = 0 rem -= nc n += nc b = b[nc:] off += int64(nc) } return }
func (c *cache) get2(n int) (r *node, isZeroed bool) { s := *c lens := len(s) if lens == 0 { return &node{b: make([]byte, n, mathutil.Min(2*n, maxBuf))}, true } i := sort.Search(lens, func(x int) bool { return len(s[x].b) >= n }) if i == lens { i-- s[i].b, isZeroed = make([]byte, n, mathutil.Min(2*n, maxBuf)), true } r = s[i] r.b = r.b[:n] copy(s[i:], s[i+1:]) s = s[:lens-1] *c = s return }
// Readdir implements http.File. func (f *HTTPFile) Readdir(count int) ([]os.FileInfo, error) { if f.isFile { return nil, fmt.Errorf("not a directory: %s", f.name) } if count <= 0 { r := f.dirEntries f.dirEntries = f.dirEntries[:0] return r, nil } rq := mathutil.Min(count, len(f.dirEntries)) r := f.dirEntries[:rq] f.dirEntries = f.dirEntries[rq:] if len(r) != 0 { return r, nil } return nil, io.EOF }
// ReadAt implements Filer. func (f *MemFiler) ReadAt(b []byte, off int64) (n int, err error) { avail := f.size - off pgI := off >> pgBits pgO := int(off & pgMask) rem := len(b) if int64(rem) >= avail { rem = int(avail) err = io.EOF } for rem != 0 && avail > 0 { pg := f.m[pgI] if pg == nil { pg = &zeroPage } nc := copy(b[:mathutil.Min(rem, pgSize)], pg[pgO:]) pgI++ pgO = 0 rem -= nc n += nc b = b[nc:] } return }
func BenchmarkRollbackFiler(b *testing.B) { rng := rand.New(rand.NewSource(42)) type t struct { off int64 b []byte } a := []t{} for rem := b.N; rem > 0; { off := rng.Int63() n := mathutil.Min(rng.Intn(1e3)+1, rem) a = append(a, t{off, rndBytes(rng, n)}) rem -= n } var r *RollbackFiler f := NewMemFiler() checkpoint := func(sz int64) (err error) { return f.Truncate(sz) } r, err := NewRollbackFiler(f, checkpoint, f) if err != nil { b.Fatal(err) } if err := r.BeginUpdate(); err != nil { b.Fatal(err) } b.ResetTimer() for _, v := range a { if _, err := r.WriteAt(v.b, v.off); err != nil { b.Fatal(err) } } }
func TestMarshal(t *testing.T) { now := time.Now() dur := time.Millisecond schema8 := testSchema8{ A: true, //B: 1, C: 2, D: 3, E: 4, F: 5, //G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: -1, O: -2, P: []byte("abc"), Q: *big.NewInt(1), R: *big.NewRat(3, 2), S: "string", T: now, U: dur, } schema8.PA = &schema8.A //schema8.PB = &schema8.B schema8.PC = &schema8.C schema8.PD = &schema8.D schema8.PE = &schema8.E schema8.PF = &schema8.F //schema8.PG = &schema8.G schema8.PH = &schema8.H schema8.PI = &schema8.I schema8.PJ = &schema8.J schema8.PK = &schema8.K schema8.PL = &schema8.L schema8.PM = &schema8.M schema8.PN = &schema8.N schema8.PO = &schema8.O schema8.PP = &schema8.P schema8.PQ = &schema8.Q schema8.PR = &schema8.R schema8.PS = &schema8.S schema8.PT = &schema8.T schema8.PU = &schema8.U type u int tab := []struct { inst interface{} err bool r []interface{} }{ {42, true, nil}, {new(u), true, nil}, {testSchema8{}, false, []interface{}{ false, //int64(0), int8(0), int16(0), int32(0), int64(0), //uint64(0), uint8(0), uint16(0), uint32(0), uint64(0), float32(0), float64(0), complex64(0), complex128(0), []byte(nil), big.Int{}, big.Rat{}, "", time.Time{}, time.Duration(0), nil, //nil, nil, nil, nil, nil, //nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, }}, {&testSchema8{}, false, []interface{}{ false, //int64(0), int8(0), int16(0), int32(0), int64(0), //uint64(0), uint8(0), uint16(0), uint32(0), uint64(0), float32(0), float64(0), complex64(0), complex128(0), []byte(nil), big.Int{}, big.Rat{}, "", time.Time{}, time.Duration(0), nil, //nil, nil, nil, nil, nil, //nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, }}, {schema8, false, []interface{}{ true, //int64(1), int8(2), int16(3), int32(4), int64(5), //uint64(6), uint8(7), uint16(8), uint32(9), uint64(10), float32(11), float64(12), complex64(-1), complex128(-2), []byte("abc"), *big.NewInt(1), *big.NewRat(3, 2), "string", now, dur, true, //int64(1), int8(2), int16(3), int32(4), int64(5), //uint64(6), uint8(7), uint16(8), uint32(9), uint64(10), float32(11), float64(12), complex64(-1), complex128(-2), []byte("abc"), *big.NewInt(1), *big.NewRat(3, 2), "string", now, dur, }}, {&schema8, false, []interface{}{ true, //int64(1), int8(2), int16(3), int32(4), int64(5), //uint64(6), uint8(7), uint16(8), uint32(9), uint64(10), float32(11), float64(12), complex64(-1), complex128(-2), []byte("abc"), *big.NewInt(1), *big.NewRat(3, 2), "string", now, dur, true, //int64(1), int8(2), int16(3), int32(4), int64(5), //uint64(6), uint8(7), uint16(8), uint32(9), uint64(10), float32(11), float64(12), complex64(-1), complex128(-2), []byte("abc"), *big.NewInt(1), *big.NewRat(3, 2), "string", now, dur, }}, } for iTest, test := range tab { r, err := Marshal(test.inst) if g, e := err != nil, test.err; g != e { t.Fatal(iTest, g, e) } if err != nil { t.Log(err) continue } for i := 0; i < mathutil.Min(len(r), len(test.r)); i++ { g, e := r[i], test.r[i] use(e) switch x := g.(type) { case bool: switch y := e.(type) { case bool: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case int: switch y := e.(type) { case int64: if int64(x) != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case int8: switch y := e.(type) { case int8: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case int16: switch y := e.(type) { case int16: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case int32: switch y := e.(type) { case int32: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case int64: switch y := e.(type) { case int64: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case uint: switch y := e.(type) { case uint64: if uint64(x) != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case uint8: switch y := e.(type) { case uint8: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case uint16: switch y := e.(type) { case uint16: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case uint32: switch y := e.(type) { case uint32: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case uint64: switch y := e.(type) { case uint64: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case float32: switch y := e.(type) { case float32: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case float64: switch y := e.(type) { case float64: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case complex64: switch y := e.(type) { case complex64: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case complex128: switch y := e.(type) { case complex128: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case []byte: switch y := e.(type) { case []byte: if bytes.Compare(x, y) != 0 { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case big.Int: switch y := e.(type) { case big.Int: if x.Cmp(&y) != 0 { t.Fatal(iTest, &x, &y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case big.Rat: switch y := e.(type) { case big.Rat: if x.Cmp(&y) != 0 { t.Fatal(iTest, &x, &y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case string: switch y := e.(type) { case string: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case time.Time: switch y := e.(type) { case time.Time: if !x.Equal(y) { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case time.Duration: switch y := e.(type) { case time.Duration: if x != y { t.Fatal(iTest, x, y) } default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } case nil: switch y := e.(type) { case nil: // ok default: t.Fatalf("%d: %T <-> %T", iTest, x, y) } default: panic(fmt.Errorf("%T", x)) } } if g, e := len(r), len(test.r); g != e { t.Fatal(iTest, g, e) } } }
// []interface{}{qltype, ...}->[]interface{}{lldb scalar type, ...} // + long blobs are (pre)written to a chain of chunks. func (s *file) flatten(data []interface{}) (err error) { for i, v := range data { tag := 0 var b []byte switch x := v.(type) { case []byte: tag = qBlob b = x case *big.Int: tag = qBigInt b, err = s.codec.encode(x) case *big.Rat: tag = qBigRat b, err = s.codec.encode(x) case time.Time: tag = qTime b, err = s.codec.encode(x) case time.Duration: tag = qDuration b, err = s.codec.encode(x) default: continue } if err != nil { return } const chunk = 1 << 16 chunks := 0 var next int64 var buf []byte for rem := len(b); rem > shortBlob; { n := mathutil.Min(rem, chunk) part := b[rem-n:] b = b[:rem-n] rem -= n switch next { case 0: // last chunk buf, err = lldb.EncodeScalars([]interface{}{part}...) default: // middle chunk buf, err = lldb.EncodeScalars([]interface{}{next, part}...) } if err != nil { return } s.mu.Lock() h, err := s.a.Alloc(buf) s.mu.Unlock() if err != nil { return err } next = h chunks++ } switch next { case 0: // single chunk buf, err = lldb.EncodeScalars([]interface{}{tag, b}...) default: // multi chunks buf, err = lldb.EncodeScalars([]interface{}{tag, next, b}...) } if err != nil { return } data[i] = buf } return }