예제 #1
0
파일: httpfs.go 프로젝트: matomesc/rkt
// 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)
	}
}
예제 #2
0
파일: xact.go 프로젝트: matomesc/rkt
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
}
예제 #3
0
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
}
예제 #4
0
파일: httpfs.go 프로젝트: matomesc/rkt
// 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
}
예제 #5
0
파일: memfiler.go 프로젝트: matomesc/rkt
// 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
}
예제 #6
0
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)
		}
	}
}
예제 #7
0
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)
		}

	}
}
예제 #8
0
파일: file.go 프로젝트: matomesc/rkt
// []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
}