func (this *PrimaryScan) scanPrimary(context *Context, parent value.Value) { conn := this.newIndexConnection(context) defer notifyConn(conn.StopChannel()) // Notify index that I have stopped var duration time.Duration timer := time.Now() defer context.AddPhaseTime("scan", time.Since(timer)-duration) go this.scanEntries(context, conn) var entry, lastEntry *datastore.IndexEntry ok := true nitems := 0 for ok { select { case <-this.stopChannel: return default: } select { case entry, ok = <-conn.EntryChannel(): t := time.Now() if ok { cv := value.NewScopeValue(make(map[string]interface{}), parent) av := value.NewAnnotatedValue(cv) av.SetAttachment("meta", map[string]interface{}{"id": entry.PrimaryKey}) ok = this.sendItem(av) lastEntry = entry nitems++ } duration += time.Since(t) case <-this.stopChannel: return } } if conn.Timeout() { logging.Errorp("Primary index scan timeout - resorting to chunked scan", logging.Pair{"chunkSize", nitems}, logging.Pair{"startingEntry", lastEntry}) if lastEntry == nil { // no key for chunked scans (primary scan returned 0 items) context.Error(errors.NewCbIndexScanTimeoutError(nil)) } // do chunked scans; nitems gives the chunk size, and lastEntry the starting point for lastEntry != nil { lastEntry = this.scanPrimaryChunk(context, parent, nitems, lastEntry) } } }
func n1qlError(client *qclient.GsiClient, err error) errors.Error { if err.Error() == c.ErrScanTimedOut.Error() { return errors.NewCbIndexScanTimeoutError(err) } return errors.NewError(err, client.DescribeError(err)) }