func openStreams(bucket *couchbase.Bucket, nodes map[string]*goupr.Client) map[string][]*goupr.Stream { servers, vbmaps := bucket.VBSMJson.ServerList, bucket.VBSMJson.VBucketMap streams := make(map[string][]*goupr.Stream) vbs_highseq_no := bucket.GetStats("vbucket-seqno") for vbucket, maps := range vbmaps { key := fmt.Sprintf("vb_%v_high_seqno", vbucket) server := servers[maps[0]] client := nodes[server] req := goupr.NewRequest(0, 0, opaqCount, uint16(vbucket)) flags := uint32(0) vuuid, high, start := uint64(0), uint64(0), uint64(0) strconv.Atoi(vbs_highseq_no[server][key]) end := uint64(0xFFFFFFFFFFFFFFFF) if stream, _, err := client.UprStream( req, flags, start, uint64(end), vuuid, high, onCommand); err != nil { log.Println("Error opening stream for vbucket", vbucket, err) } else { log.Println("Opened a stream for vbucket", vbucket) ls := streams[servers[maps[0]]] if ls == nil { ls = make([]*goupr.Stream, 0) } streams[servers[maps[0]]] = append(ls, stream) } opaqCount += 1 } return streams }
// Start a new stream for vuuid and seqNo func runStream(client *goupr.Client, vbucket int, ivuuid, iseqNo uint64) { req := goupr.NewRequest(0, 0, 0, uint16(vbucket)) flogs, err := client.UprFailOverLog(req) if err != nil { log.Panicln(err) } // We do not handle the scenario of re-building the index. req = goupr.NewRequest(0, 0, 0, uint16(vbucket)) vuuid, highVUUID, highSeqNo := uint64(0), ivuuid, iseqNo for _, flog := range flogs { if flog[0] == ivuuid { // Pick matching vuuid from failover-logs vuuid = ivuuid break } if flog[1] > highSeqNo { // Or the highest sequence number highVUUID, highSeqNo = flog[0], flog[1] } } var stream *goupr.Stream var rollb, seqNo uint64 if vuuid == 0 { vuuid, seqNo = highVUUID, highSeqNo } else { seqNo = iseqNo } // In either case, try to get a stream for (vuuid,seqNo) for { stream, rollb, err = client.UprStream(req, 0, seqNo, 0, vuuid, seqNo) if stream == nil && err == nil && rollb > 0 { seqNo = rollb continue } else if err != nil { log.Panicln(err) } else if stream != nil { break } } // Notify indexer about the sequence number that we will start receiving. for { _ = <-stream.Consumer // Start receiving stream commands. // Handle UPR commands. } }