예제 #1
0
파일: file.go 프로젝트: eldarion-gondor/cli
func (x *fileIndex) Delete(indexedValues []interface{}, h int64) error {
	for i, indexedValue := range indexedValues {
		chunk, ok := indexedValue.(chunk)
		if ok {
			indexedValues[i] = chunk.b
		}
	}

	t := x.t
	var k []byte
	var err error
	switch {
	case !x.unique:
		k, err = lldb.EncodeScalars(append(indexedValues, h)...)
	case isIndexNull(indexedValues): // unique, NULL
		k, err = lldb.EncodeScalars(nil, h)
	default: // unique, non NULL
		k, err = lldb.EncodeScalars(append(indexedValues, int64(0))...)
	}
	if err != nil {
		return err
	}

	return t.Delete(k)
}
예제 #2
0
파일: file.go 프로젝트: eldarion-gondor/cli
func (t *fileTemp) Set(k, v []interface{}) (err error) {
	if err = expand(k); err != nil {
		return
	}

	if err = expand(v); err != nil {
		return
	}

	infer(k, &t.colsK)
	infer(v, &t.colsV)

	if err = t.flatten(k); err != nil {
		return
	}

	bk, err := lldb.EncodeScalars(k...)
	if err != nil {
		return
	}

	if err = t.flatten(v); err != nil {
		return
	}

	bv, err := lldb.EncodeScalars(v...)
	if err != nil {
		return
	}

	return t.t.Set(bk, bv)
}
예제 #3
0
파일: file.go 프로젝트: eldarion-gondor/cli
// The []byte version of the key in the BTree shares chunks, if any, with
// the value stored in the record.
func (x *fileIndex) Create(indexedValues []interface{}, h int64) error {
	for i, indexedValue := range indexedValues {
		chunk, ok := indexedValue.(chunk)
		if ok {
			indexedValues[i] = chunk.b
		}
	}

	t := x.t
	switch {
	case !x.unique:
		k, err := lldb.EncodeScalars(append(indexedValues, h)...)
		if err != nil {
			return err
		}

		return t.Set(k, gbZeroInt64)
	case isIndexNull(indexedValues): // unique, NULL
		k, err := lldb.EncodeScalars(nil, h)
		if err != nil {
			return err
		}

		return t.Set(k, gbZeroInt64)
	default: // unique, non NULL
		k, err := lldb.EncodeScalars(append(indexedValues, int64(0))...)
		if err != nil {
			return err
		}

		v, err := lldb.EncodeScalars(h)
		if err != nil {
			return err
		}

		_, _, err = t.Put(nil, k, func(key, old []byte) (new []byte, write bool, err error) {
			if old == nil {
				return v, true, nil
			}

			return nil, false, fmt.Errorf("(file-018) cannot insert into unique index: duplicate value(s): %v", indexedValues)
		})
		return err
	}
}
예제 #4
0
파일: file.go 프로젝트: eldarion-gondor/cli
func (s *file) Update(h int64, data ...interface{}) (err error) {
	b, err := lldb.EncodeScalars(data...)
	if err != nil {
		return
	}

	defer s.lock()()
	return s.a.Realloc(h, b)
}
예제 #5
0
파일: file.go 프로젝트: devick/flynn
func (x *fileIndex) Seek(indexedValue interface{}) (indexIterator, bool, error) { //TODO(indices) blobs: +test
	k, err := lldb.EncodeScalars(indexedValue, 0)
	if err != nil {
		return nil, false, err
	}

	en, hit, err := x.t.Seek(k)
	if err != nil {
		return nil, false, err
	}

	return &fileIndexIterator{x.f, en, x.unique}, hit, nil
}
예제 #6
0
파일: file.go 프로젝트: devick/flynn
// The []byte version of the key in the BTree shares chunks, if any, with
// the value stored in the record.
func (x *fileIndex) Create(indexedValue interface{}, h int64) error {
	t := x.t
	switch {
	case !x.unique:
		k, err := lldb.EncodeScalars(indexedValue, h)
		if err != nil {
			return err
		}

		return t.Set(k, gbZeroInt64)
	case indexedValue == nil: // unique, NULL
		k, err := lldb.EncodeScalars(nil, h)
		if err != nil {
			return err
		}

		return t.Set(k, gbZeroInt64)
	default: // unique, non NULL
		k, err := lldb.EncodeScalars(indexedValue, int64(0))
		if err != nil {
			return err
		}

		v, err := lldb.EncodeScalars(h)
		if err != nil {
			return err
		}

		_, _, err = t.Put(nil, k, func(key, old []byte) (new []byte, write bool, err error) {
			if old == nil {
				return v, true, nil
			}

			return nil, false, fmt.Errorf("(file-018) cannot insert into unique index: duplicate value: %v", indexedValue)
		})
		return err
	}
}
예제 #7
0
파일: file.go 프로젝트: devick/flynn
func (x *fileIndex) Delete(indexedValue interface{}, h int64) error {
	chunk, ok := indexedValue.(chunk)
	if ok {
		indexedValue = chunk.b
	}

	t := x.t
	var k []byte
	var err error
	switch {
	case !x.unique:
		k, err = lldb.EncodeScalars(indexedValue, h)
	case indexedValue == nil: // unique, NULL
		k, err = lldb.EncodeScalars(nil, h)
	default: // unique, non NULL
		k, err = lldb.EncodeScalars(indexedValue, int64(0))
	}
	if err != nil {
		return err
	}

	return t.Delete(k)
}
예제 #8
0
파일: file.go 프로젝트: eldarion-gondor/cli
func (s *file) Create(data ...interface{}) (h int64, err error) {
	if err = expand(data); err != nil {
		return
	}

	if err = s.flatten(data); err != nil {
		return
	}

	b, err := lldb.EncodeScalars(data...)
	if err != nil {
		return
	}

	defer s.lock()()
	return s.a.Alloc(b)
}
예제 #9
0
파일: file.go 프로젝트: eldarion-gondor/cli
func (x *fileIndex) Seek(indexedValues []interface{}) (indexIterator, bool, error) {
	data := append(indexedValues, 0)
	if err := x.flatten(data); err != nil {
		return nil, false, err
	}

	k, err := lldb.EncodeScalars(data...)
	if err != nil {
		return nil, false, err
	}

	en, hit, err := x.t.Seek(k)
	if err != nil {
		return nil, false, err
	}

	return &fileIndexIterator{x.f, en, x.unique}, hit, nil
}
예제 #10
0
파일: file.go 프로젝트: eldarion-gondor/cli
func (t *fileTemp) Get(k []interface{}) (v []interface{}, err error) {
	if err = expand(k); err != nil {
		return
	}

	if err = t.flatten(k); err != nil {
		return nil, err
	}

	bk, err := lldb.EncodeScalars(k...)
	if err != nil {
		return
	}

	bv, err := t.t.Get(nil, bk)
	if err != nil {
		return
	}

	return lldb.DecodeScalars(bv)
}
예제 #11
0
파일: file.go 프로젝트: eldarion-gondor/cli
// []interface{}{qltype, ...}->[]interface{}{lldb scalar type, ...}
func (x *fileIndex) flatten(data []interface{}) (err error) {
	for i, v := range data {
		tag := 0
		var b []byte
		switch xx := v.(type) {
		case []byte:
			tag = qBlob
			b = xx
		case *big.Int:
			tag = qBigInt
			b, err = x.codec.encode(xx)
		case *big.Rat:
			tag = qBigRat
			b, err = x.codec.encode(xx)
		case time.Time:
			tag = qTime
			b, err = x.codec.encode(xx)
		case time.Duration:
			tag = qDuration
			b, err = x.codec.encode(xx)
		default:
			continue
		}
		if err != nil {
			return
		}

		var buf []byte
		if buf, err = lldb.EncodeScalars([]interface{}{tag, b}...); err != nil {
			return
		}

		data[i] = buf
	}
	return
}
예제 #12
0
파일: file.go 프로젝트: eldarion-gondor/cli
func init() {
	var err error
	if gbZeroInt64, err = lldb.EncodeScalars(int64(0)); err != nil {
		panic(err)
	}
}
예제 #13
0
파일: file.go 프로젝트: eldarion-gondor/cli
// []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
}