func RangeStatistics(indexName, bucketName, server string, low, high []interface{}, inclusion uint32) error { // ToDo: Create a client pool client, e := CreateClient(server, "2itest") if e != nil { return e } defer client.Close() defnID, _ := GetDefnID(client, bucketName, indexName) statistics, err := client.RangeStatistics(defnID, c.SecondaryKey(low), c.SecondaryKey(high), qc.Inclusion(inclusion)) if err != nil { return err } else { log.Print("Statistics: %v\n\n", statistics) return nil } }
func CountRange(indexName, bucketName, server string, low, high []interface{}, inclusion uint32, consistency c.Consistency, vector *qc.TsConsistency) (int64, error) { // ToDo: Create a client pool client, e := CreateClient(server, "2itest") if e != nil { return 0, e } defer client.Close() defnID, _ := GetDefnID(client, bucketName, indexName) count, err := client.CountRange(defnID, c.SecondaryKey(low), c.SecondaryKey(high), qc.Inclusion(inclusion), consistency, vector) if err != nil { return 0, err } else { return count, nil } }
func RangeWithClient(indexName, bucketName, server string, low, high []interface{}, inclusion uint32, distinct bool, limit int64, consistency c.Consistency, vector *qc.TsConsistency, client *qc.GsiClient) (tc.ScanResponse, error) { var scanErr error scanErr = nil defnID, _ := GetDefnID(client, bucketName, indexName) scanResults := make(tc.ScanResponse) start := time.Now() connErr := client.Range( defnID, c.SecondaryKey(low), c.SecondaryKey(high), qc.Inclusion(inclusion), distinct, limit, consistency, vector, func(response qc.ResponseReader) bool { if err := response.Error(); err != nil { scanErr = err return false } else if skeys, pkeys, err := response.GetEntries(); err != nil { scanErr = err return false } else { for i, skey := range skeys { primaryKey := string(pkeys[i]) if _, keyPresent := scanResults[primaryKey]; keyPresent { // Duplicate primary key found tc.HandleError(err, "Duplicate primary key found in the scan results: "+primaryKey) } else { scanResults[primaryKey] = skey } } return true } return false }) elapsed := time.Since(start) if connErr != nil { log.Printf("Connection error in Scan occured: %v", connErr) return scanResults, connErr } else if scanErr != nil { return scanResults, scanErr } tc.LogPerfStat("Range", elapsed) return scanResults, nil }
// ParseArgs into Command object, return the list of arguments, // flagset used for parseing and error if any. func ParseArgs(arguments []string) (*Command, []string, *flag.FlagSet, error) { var fields, bindexes string var inclusion uint var equal, low, high string var useSessionCons bool cmdOptions := &Command{Consistency: c.AnyConsistency} fset := flag.NewFlagSet("cmd", flag.ExitOnError) // basic options fset.StringVar(&cmdOptions.Server, "server", "", "Cluster server address") fset.StringVar(&cmdOptions.Auth, "auth", "", "Auth user and password") fset.StringVar(&cmdOptions.Bucket, "bucket", "", "Bucket name") fset.StringVar(&cmdOptions.OpType, "type", "", "Command: scan|stats|scanAll|count|nodes|create|build|drop|list|config") fset.StringVar(&cmdOptions.IndexName, "index", "", "Index name") // options for create-index fset.StringVar(&cmdOptions.WhereStr, "where", "", "where clause for create index") fset.StringVar(&fields, "fields", "", "Comma separated on-index fields") // secStrs fset.BoolVar(&cmdOptions.IsPrimary, "primary", false, "Is primary index") fset.StringVar(&cmdOptions.With, "with", "", "index specific properties") // options for build-indexes, drop-indexes fset.StringVar(&bindexes, "indexes", "", "csv list of bucket.index to build") // options for Range, Statistics, Count fset.StringVar(&low, "low", "[]", "Span.Range: [low]") fset.StringVar(&high, "high", "[]", "Span.Range: [high]") fset.StringVar(&equal, "equal", "", "Span.Lookup: [key]") fset.UintVar(&inclusion, "incl", 0, "Range: 0|1|2|3") fset.Int64Var(&cmdOptions.Limit, "limit", 10, "Row limit") fset.BoolVar(&cmdOptions.Help, "h", false, "print help") fset.BoolVar(&useSessionCons, "consistency", false, "Use session consistency") // options for setting configuration fset.StringVar(&cmdOptions.ConfigKey, "ckey", "", "Config key") fset.StringVar(&cmdOptions.ConfigVal, "cval", "", "Config value") fset.StringVar(&cmdOptions.Using, "using", c.ForestDB, "storate type to use") // not useful to expose in sherlock cmdOptions.ExprType = "N1QL" cmdOptions.PartnStr = "partn" if err := fset.Parse(arguments); err != nil { return nil, nil, fset, err } if useSessionCons { cmdOptions.Consistency = c.SessionConsistency } // if server is not specified, try guessing if cmdOptions.Server == "" { if guess := guessServer(); guess != "" { cmdOptions.Server = guess fset.Set("server", guess) } } // if server is not specified, try guessing if cmdOptions.Auth == "" { if guess := guessAuth(cmdOptions.Server); guess != "" { cmdOptions.Auth = guess fset.Set("auth", guess) } } // validate combinations err := validate(cmdOptions, fset) if err != nil { return nil, nil, fset, err } // bindexes if len(bindexes) > 0 { cmdOptions.Bindexes = strings.Split(bindexes, ",") } // inclusion, secStrs, equal, low, high cmdOptions.Inclusion = qclient.Inclusion(inclusion) cmdOptions.SecStrs = make([]string, 0) if fields != "" { for _, field := range strings.Split(fields, ",") { expr, err := n1ql.ParseExpression(field) if err != nil { msgf := "Error occured: Invalid field (%v) %v\n" return nil, nil, fset, fmt.Errorf(msgf, field, err) } secStr := expression.NewStringer().Visit(expr) cmdOptions.SecStrs = append(cmdOptions.SecStrs, secStr) } } if equal != "" { cmdOptions.Equal = c.SecondaryKey(Arg2Key([]byte(equal))) } cmdOptions.Low = c.SecondaryKey(Arg2Key([]byte(low))) cmdOptions.High = c.SecondaryKey(Arg2Key([]byte(high))) // with if len(cmdOptions.With) > 0 { err := json.Unmarshal([]byte(cmdOptions.With), &cmdOptions.WithPlan) if err != nil { logging.Fatalf("%v\n", err) os.Exit(1) } } // setup cbauth if cmdOptions.Auth != "" { up := strings.Split(cmdOptions.Auth, ":") _, err := cbauth.InternalRetryDefaultInit(cmdOptions.Server, up[0], up[1]) if err != nil { logging.Fatalf("Failed to initialize cbauth: %s\n", err) os.Exit(1) } } return cmdOptions, fset.Args(), fset, err }
func doConsistency( cluster string, maxvb int, client *qclient.GsiClient) (err error) { b, err := common.ConnectBucket(cluster, "default", "beer-sample") if err != nil { log.Fatal(err) } defer b.Close() vbnos := make([]uint16, maxvb) for i := range vbnos { vbnos[i] = uint16(i) } // Drop index args := []string{"-type", "drop", "-bucket", "beer-sample", "-index", "index-city"} cmd, _, _, _ := querycmd.ParseArgs(args) querycmd.HandleCommand(client, cmd, true, os.Stdout) // Create index args = []string{ "-type", "create", "-bucket", "beer-sample", "-index", "index-city", "-fields", "city", } cmd, _, _, err = querycmd.ParseArgs(args) if err != nil { log.Fatal(err) } querycmd.HandleCommand(client, cmd, true, os.Stdout) // Wait for index to come active. index, ok := querycmd.GetIndex(client, "beer-sample", "index-city") if !ok { log.Fatalf("cannot get definition ID") } defnID := uint64(index.Definition.DefnId) _, err = querycmd.WaitUntilIndexState( client, []uint64{defnID}, common.INDEX_STATE_ACTIVE, 100 /*period*/, 20000 /*timeout*/) synch := make(chan bool, 1) // Get the latest seqnos,vbuuid and vbucket that contains `docid`. seqnos, vbuuids, vbno, vbuuid, seqno := setValueConst(b, maxvb, constDocValue1) equal := common.SecondaryKey(querycmd.Arg2Key(constEqualLookup1)) equals := []common.SecondaryKey{equal} anyConsistency(client, defnID, equals) // query-consistency without any new mutations. ts := qclient.NewTsConsistency(vbnos, seqnos, vbuuids) queryConsistency(client, defnID, ts, equals, synch) <-synch // query-consistency with a new mutation. equal = common.SecondaryKey(querycmd.Arg2Key(constEqualLookup2)) equals = []common.SecondaryKey{equal} seqno++ ts = ts.Override(vbno, seqno, vbuuid) queryConsistency(client, defnID, ts, equals, synch) time.Sleep(2 * time.Second) setValueConst(b, maxvb, constDocValue2) <-synch // query-consistency with a new mutation. equal = common.SecondaryKey(querycmd.Arg2Key(constEqualLookup3)) equals = []common.SecondaryKey{equal} seqno++ ts = qclient.NewTsConsistency([]uint16{vbno}, []uint64{seqno}, []uint64{vbuuid}) queryConsistency(client, defnID, ts, equals, synch) time.Sleep(2 * time.Second) setValueConst(b, maxvb, constDocValue3) <-synch // session-consistency without any new mutations. sessionConsistency(client, defnID, equals, synch) <-synch // session-consistency with a new mutation. setValueConst(b, maxvb, constDocValue4) equal = common.SecondaryKey(querycmd.Arg2Key(constEqualLookup4)) equals = []common.SecondaryKey{equal} sessionConsistency(client, defnID, equals, synch) <-synch // session-consistency with a new mutation. equal = common.SecondaryKey(querycmd.Arg2Key(constEqualLookup5)) equals = []common.SecondaryKey{equal} setValueConst(b, maxvb, constDocValue5) sessionConsistency(client, defnID, equals, synch) <-synch return nil }
func Range(indexName, bucketName, server string, low, high []interface{}, inclusion uint32, distinct bool, limit int64, consistency c.Consistency, vector *qc.TsConsistency) (tc.ScanResponse, error) { var scanErr error scanErr = nil var previousSecKey value.Value // ToDo: Create a client pool client, e := CreateClient(server, "2itest") if e != nil { return nil, e } defer client.Close() defnID, _ := GetDefnID(client, bucketName, indexName) scanResults := make(tc.ScanResponse) start := time.Now() connErr := client.Range( defnID, c.SecondaryKey(low), c.SecondaryKey(high), qc.Inclusion(inclusion), distinct, limit, consistency, vector, func(response qc.ResponseReader) bool { if err := response.Error(); err != nil { scanErr = err return false } else if skeys, pkeys, err := response.GetEntries(); err != nil { scanErr = err return false } else { for i, skey := range skeys { primaryKey := string(pkeys[i]) if _, keyPresent := scanResults[primaryKey]; keyPresent { // Duplicate primary key found tc.HandleError(err, "Duplicate primary key found in the scan results: "+primaryKey) } else { // Test collation only if CheckCollation is true if CheckCollation == true && len(skey) > 0 { secVal := skey2Values(skey)[0] if previousSecKey == nil { previousSecKey = secVal } else { if secVal.Collate(previousSecKey) < 0 { errMsg := "Collation check failed. Previous Sec key > Current Sec key" scanErr = errors.New(errMsg) return false } } } scanResults[primaryKey] = skey } } return true } return false }) elapsed := time.Since(start) if connErr != nil { log.Printf("Connection error in Scan occured: %v", connErr) return scanResults, connErr } else if scanErr != nil { return scanResults, scanErr } tc.LogPerfStat("Range", elapsed) return scanResults, nil }