// Close all file handles. func (part *Partition) Close() error { var err error if e := part.col.Close(); e != nil { tdlog.CritNoRepeat("Failed to close %s: %v", part.col.Path, e) err = dberr.New(dberr.ErrorIO) } if e := part.lookup.Close(); e != nil { tdlog.CritNoRepeat("Failed to close %s: %v", part.lookup.Path, e) err = dberr.New(dberr.ErrorIO) } return err }
// Return number of the next chained bucket. func (ht *HashTable) nextBucket(bucket int) int { if bucket >= ht.numBuckets { return 0 } bucketAddr := bucket * BUCKET_SIZE nextUint, err := binary.Varint(ht.Buf[bucketAddr : bucketAddr+10]) next := int(nextUint) if next == 0 { return 0 } else if err < 0 || next <= bucket || next >= ht.numBuckets || next < INITIAL_BUCKETS { tdlog.CritNoRepeat("Bad hash table - repair ASAP %s", ht.Path) return 0 } else { return next } }
// Look for indexed integer values within the specified integer range. func IntRange(intFrom interface{}, expr map[string]interface{}, src *Col, result *map[int]struct{}) (err error) { path, hasPath := expr["in"] if !hasPath { return errors.New("Missing path `in`") } // Figure out the path vecPath := make([]string, 0) if vecPathInterface, ok := path.([]interface{}); ok { for _, v := range vecPathInterface { vecPath = append(vecPath, fmt.Sprint(v)) } } else { return errors.New(fmt.Sprintf("Expecting vector path `in`, but %v given", path)) } // Figure out result number limit intLimit := int(0) if limit, hasLimit := expr["limit"]; hasLimit { if floatLimit, ok := limit.(float64); ok { intLimit = int(floatLimit) } else if _, ok := limit.(int); ok { intLimit = limit.(int) } else { return dberr.New(dberr.ErrorExpectingInt, limit) } } // Figure out the range ("from" value & "to" value) from, to := int(0), int(0) if floatFrom, ok := intFrom.(float64); ok { from = int(floatFrom) } else if _, ok := intFrom.(int); ok { from = intFrom.(int) } else { return dberr.New(dberr.ErrorExpectingInt, "int-from", from) } if intTo, ok := expr["int-to"]; ok { if floatTo, ok := intTo.(float64); ok { to = int(floatTo) } else if _, ok := intTo.(int); ok { to = intTo.(int) } else { return dberr.New(dberr.ErrorExpectingInt, "int-to", to) } } else if intTo, ok := expr["int to"]; ok { if floatTo, ok := intTo.(float64); ok { to = int(floatTo) } else if _, ok := intTo.(int); ok { to = intTo.(int) } else { return dberr.New(dberr.ErrorExpectingInt, "int to", to) } } else { return dberr.New(dberr.ErrorMissing, "int-to") } if to > from && to-from > 1000 || from > to && from-to > 1000 { tdlog.CritNoRepeat("Query %v involves index lookup on more than 1000 values, which can be very inefficient", expr) } counter := int(0) // Number of results already collected htPath := strings.Join(vecPath, ",") if _, indexScan := src.indexPaths[htPath]; !indexScan { return dberr.New(dberr.ErrorNeedIndex, vecPath, expr) } if from < to { // Forward scan - from low value to high value for lookupValue := from; lookupValue <= to; lookupValue++ { lookupStrValue := fmt.Sprint(lookupValue) hashValue := StrHash(lookupStrValue) vals := src.hashScan(htPath, hashValue, int(intLimit)) for _, docID := range vals { if intLimit > 0 && counter == intLimit { break } counter += 1 (*result)[docID] = struct{}{} } } } else { // Backward scan - from high value to low value for lookupValue := from; lookupValue >= to; lookupValue-- { lookupStrValue := fmt.Sprint(lookupValue) hashValue := StrHash(lookupStrValue) vals := src.hashScan(htPath, hashValue, int(intLimit)) for _, docID := range vals { if intLimit > 0 && counter == intLimit { break } counter += 1 (*result)[docID] = struct{}{} } } } return }