func (s *file) freeChunks(enc []byte) (err error) { items, err := lldb.DecodeScalars(enc) if err != nil { return } var ok bool var next int64 switch len(items) { case 2: return case 3: if next, ok = items[1].(int64); !ok || next == 0 { return fmt.Errorf("(file-007) corrupted DB: first chunk link") } default: return fmt.Errorf("(file-008) corrupted DB: first chunk") } for next != 0 { b, err := s.a.Get(nil, next) if err != nil { return err } if items, err = lldb.DecodeScalars(b); err != nil { return err } var h int64 switch len(items) { case 1: // nop case 2: if h, ok = items[0].(int64); !ok { return fmt.Errorf("(file-009) corrupted DB: chunk link") } default: return fmt.Errorf("(file-010) corrupted DB: chunk items %d (%v)", len(items), items) } s.mu.Lock() if err = s.a.Free(next); err != nil { s.mu.Unlock() return err } s.mu.Unlock() next = h } return }
func (s *file) free(h int64, blobCols []*col) (err error) { b, err := s.a.Get(nil, h) //LATER +bufs if err != nil { return } rec, err := lldb.DecodeScalars(b) if err != nil { return } for _, col := range blobCols { if col.index >= len(rec) { return fmt.Errorf("(file-004) file.free: corrupted DB (record len)") } if col.index+2 >= len(rec) { continue } switch x := rec[col.index+2].(type) { case nil: // nop case []byte: if err = s.freeChunks(x); err != nil { return } } } defer s.lock()() return s.a.Free(h) }
func (it *fileBTreeIterator) Next() (k, v []interface{}, err error) { bk, bv, err := it.en.Next() if err != nil { return } if k, err = lldb.DecodeScalars(bk); err != nil { return } for i, val := range k { b, ok := val.([]byte) if !ok { continue } c := chunk{it.t.file, b} if k[i], err = c.expand(); err != nil { return nil, nil, err } } if err = enforce(k, it.t.colsK); err != nil { return } if v, err = lldb.DecodeScalars(bv); err != nil { return } for i, val := range v { b, ok := val.([]byte) if !ok { continue } c := chunk{it.t.file, b} if v[i], err = c.expand(); err != nil { return nil, nil, err } } err = enforce(v, it.t.colsV) return }
func (s *file) collate(a, b []byte) int { //TODO w/ error return da, err := lldb.DecodeScalars(a) if err != nil { panic(err) } if err = s.expandBytes(da); err != nil { panic(err) } db, err := lldb.DecodeScalars(b) if err != nil { panic(err) } if err = s.expandBytes(db); err != nil { panic(err) } //dbg("da: %v, db: %v", da, db) return collate(da, db) }
func (i *fileIndexIterator) nextPrev(f func() ([]byte, []byte, error)) ([]interface{}, int64, error) { //TODO(indices) blobs: +test bk, bv, err := f() if err != nil { return nil, -1, err } dk, err := lldb.DecodeScalars(bk) if err != nil { return nil, -1, err } b, ok := dk[0].([]byte) if ok { dk[0] = chunk{i.f, b} if expand(dk[:1]); err != nil { return nil, -1, err } } var k indexKey k.value = dk[:len(dk)-1] switch i.unique { case true: if isIndexNull(k.value) { return nil, dk[len(dk)-1].(int64), nil } dv, err := lldb.DecodeScalars(bv) if err != nil { return nil, -1, err } return k.value, dv[0].(int64), nil default: return k.value, dk[len(dk)-1].(int64), nil } }
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) }
func (s *file) loadChunks(enc []byte) (v interface{}, err error) { items, err := lldb.DecodeScalars(enc) if err != nil { return } var ok bool var next int64 switch len(items) { case 2: // nop case 3: if next, ok = items[1].(int64); !ok || next == 0 { return nil, fmt.Errorf("(file-011) corrupted DB: first chunk link") } default: //fmt.Printf("%d: %#v\n", len(items), items) return nil, fmt.Errorf("(file-012) corrupted DB: first chunk") } typ, ok := items[0].(int64) if !ok { return nil, fmt.Errorf("(file-013) corrupted DB: first chunk tag") } buf, ok := items[len(items)-1].([]byte) if !ok { return nil, fmt.Errorf("(file-014) corrupted DB: first chunk data") } for next != 0 { b, err := s.a.Get(nil, next) if err != nil { return nil, err } if items, err = lldb.DecodeScalars(b); err != nil { return nil, err } switch len(items) { case 1: next = 0 case 2: if next, ok = items[0].(int64); !ok { return nil, fmt.Errorf("(file-015) corrupted DB: chunk link") } items = items[1:] default: return nil, fmt.Errorf("(file-016) corrupted DB: chunk items %d (%v)", len(items), items) } if b, ok = items[0].([]byte); !ok { return nil, fmt.Errorf("(file-017) corrupted DB: chunk data") } buf = append(buf, b...) } return s.codec.decode(buf, int(typ)) }
func (s *file) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) { //NTYPE b, err := s.a.Get(nil, h) //LATER +bufs if err != nil { return } rec, err := lldb.DecodeScalars(b) if err != nil { return } for _, col := range cols { i := col.index + 2 if i >= len(rec) || rec[i] == nil { continue } switch col.typ { case 0: case qBool: case qComplex64: rec[i] = complex64(rec[i].(complex128)) case qComplex128: case qFloat32: rec[i] = float32(rec[i].(float64)) case qFloat64: case qInt8: rec[i] = int8(rec[i].(int64)) case qInt16: rec[i] = int16(rec[i].(int64)) case qInt32: rec[i] = int32(rec[i].(int64)) case qInt64: case qString: case qUint8: rec[i] = uint8(rec[i].(uint64)) case qUint16: rec[i] = uint16(rec[i].(uint64)) case qUint32: rec[i] = uint32(rec[i].(uint64)) case qUint64: case qBlob, qBigInt, qBigRat, qTime, qDuration: switch x := rec[i].(type) { case []byte: rec[i] = chunk{f: s, b: x} default: return nil, fmt.Errorf("(file-006) corrupted DB: non nil chunk type is not []byte") } default: panic("internal error 045") } } if cols != nil { for n, dn := len(cols)+2, len(rec); dn < n; dn++ { rec = append(rec, nil) } } return rec, nil }
//NTYPE func infer(from []interface{}, to *[]*col) { if len(*to) == 0 { *to = make([]*col, len(from)) for i := range *to { (*to)[i] = &col{} } } for i, c := range *to { if f := from[i]; f != nil { switch x := f.(type) { //case nil: case idealComplex: c.typ = qComplex128 from[i] = complex128(x) case idealFloat: c.typ = qFloat64 from[i] = float64(x) case idealInt: c.typ = qInt64 from[i] = int64(x) case idealRune: c.typ = qInt32 from[i] = int32(x) case idealUint: c.typ = qUint64 from[i] = uint64(x) case bool: c.typ = qBool case complex128: c.typ = qComplex128 case complex64: c.typ = qComplex64 case float64: c.typ = qFloat64 case float32: c.typ = qFloat32 case int8: c.typ = qInt8 case int16: c.typ = qInt16 case int32: c.typ = qInt32 case int64: c.typ = qInt64 case string: c.typ = qString case uint8: c.typ = qUint8 case uint16: c.typ = qUint16 case uint32: c.typ = qUint32 case uint64: c.typ = qUint64 case []byte: c.typ = qBlob case *big.Int: c.typ = qBigInt case *big.Rat: c.typ = qBigRat case time.Time: c.typ = qTime case time.Duration: c.typ = qDuration case chunk: vals, err := lldb.DecodeScalars([]byte(x.b)) if err != nil { panic(err) } if len(vals) == 0 { panic("internal error 040") } i, ok := vals[0].(int64) if !ok { panic("internal error 041") } c.typ = int(i) case map[string]interface{}: // map of ids of a cross join default: panic("internal error 042") } } } }