/* message KeyVersions { required uint64 seqno = 1; // sequence number corresponding to this mutation optional bytes docid = 2; // primary document id repeated uint64 uuids = 3; // uuids, hosting key-version repeated uint32 commands = 4; // list of command for each uuid repeated bytes keys = 5; // key-versions for each uuids listed above repeated bytes oldkeys = 6; // key-versions from old copy of the document repeated bytes partnkeys = 7; // partition key for each key-version } */ func (s *Stream) handleSingleKeyVersion(bucket string, vbucket uint32, vbuuid uint64, kv *data.KeyVersions) { for i, cmd := range kv.GetCommands() { logging.Debugf("Stream.handleSingleKeyVersion(): recieve command %v", cmd) switch byte(cmd) { case common.Upsert: s.handler.HandleUpsert(s.id, bucket, vbucket, vbuuid, kv, i) case common.Deletion: s.handler.HandleDeletion(s.id, bucket, vbucket, vbuuid, kv, i) case common.UpsertDeletion: s.handler.HandleUpsertDeletion(s.id, bucket, vbucket, vbuuid, kv, i) case common.Sync: s.handler.HandleSync(s.id, bucket, vbucket, vbuuid, kv, i) case common.DropData: s.handler.HandleDropData(s.id, bucket, vbucket, vbuuid, kv, i) case common.StreamBegin: s.handler.HandleStreamBegin(s.id, bucket, vbucket, vbuuid, kv, i) case common.StreamEnd: s.handler.HandleStreamEnd(s.id, bucket, vbucket, vbuuid, kv, i) case common.Snapshot: s.handler.HandleSnapshot(s.id, bucket, vbucket, vbuuid, kv, i) } } }
//handleSingleKeyVersion processes a single mutation based on the command type //A mutation is put in a worker queue and control message is sent to supervisor func (r *mutationStreamReader) handleSingleKeyVersion(bucket string, vbucket Vbucket, vbuuid Vbuuid, kv *protobuf.KeyVersions) { meta := NewMutationMeta() meta.bucket = bucket meta.vbucket = vbucket meta.vbuuid = vbuuid meta.seqno = Seqno(kv.GetSeqno()) defer meta.Free() var mutk *MutationKeys r.skipMutation = false r.evalFilter = true logging.LazyTrace(func() string { return fmt.Sprintf("MutationStreamReader::handleSingleKeyVersion received KeyVersions %v", kv) }) for i, cmd := range kv.GetCommands() { //based on the type of command take appropriate action switch byte(cmd) { //case protobuf.Command_Upsert, protobuf.Command_Deletion, protobuf.Command_UpsertDeletion: case common.Upsert, common.Deletion, common.UpsertDeletion: //As there can multiple keys in a KeyVersion for a mutation, //filter needs to be evaluated and set only once. if r.evalFilter { r.evalFilter = false //check the bucket filter to see if this mutation can be processed //valid mutation will increment seqno of the filter if !r.checkAndSetBucketFilter(meta) { r.skipMutation = true } } if r.skipMutation { continue } r.logReaderStat() //allocate new mutation first time if mutk == nil { //TODO use free list here to reuse the struct and reduce garbage mutk = NewMutationKeys() mutk.meta = meta.Clone() mutk.docid = kv.GetDocid() mutk.mut = mutk.mut[:0] } mut := NewMutation() mut.uuid = common.IndexInstId(kv.GetUuids()[i]) mut.key = kv.GetKeys()[i] mut.command = byte(kv.GetCommands()[i]) mutk.mut = append(mutk.mut, mut) case common.DropData: //send message to supervisor to take decision msg := &MsgStream{mType: STREAM_READER_STREAM_DROP_DATA, streamId: r.streamId, meta: meta.Clone()} r.supvRespch <- msg case common.StreamBegin: r.updateVbuuidInFilter(meta) //send message to supervisor to take decision msg := &MsgStream{mType: STREAM_READER_STREAM_BEGIN, streamId: r.streamId, meta: meta.Clone()} r.supvRespch <- msg case common.StreamEnd: //send message to supervisor to take decision msg := &MsgStream{mType: STREAM_READER_STREAM_END, streamId: r.streamId, meta: meta.Clone()} r.supvRespch <- msg case common.Snapshot: //get snapshot information from message r.snapType, r.snapStart, r.snapEnd = kv.Snapshot() // Snapshot marker can be processed only if // they belong to ondisk type or inmemory type. if r.snapType&(0x1|0x2) != 0 { r.updateSnapInFilter(meta, r.snapStart, r.snapEnd) } } } //place secKey in the right worker's queue if mutk != nil { r.workerch[int(vbucket)%r.numWorkers] <- mutk } }