func applyTransaction(kv mvcc.KV, lessor lease.Lessor, req *etcdserverpb.TxnRequest) (*etcdserverpb.TxnResponse, error) { var revision int64 ok := true for _, c := range req.Compare { if revision, ok = applyCompare(kv, c); !ok { break } } var reqs []*etcdserverpb.RequestUnion if ok { reqs = req.Success } else { reqs = req.Failure } if err := checkRequestLeases(lessor, reqs); err != nil { return nil, err } if err := checkRequestRange(kv, reqs); err != nil { return nil, err } // When executing the operations of txn, we need to hold the txn lock. // So the reader will not see any intermediate results. txnID := kv.TxnBegin() defer func() { err := kv.TxnEnd(txnID) if err != nil { panic(fmt.Sprint("unexpected error when closing txn", txnID)) } }() resps := make([]*etcdserverpb.ResponseUnion, len(reqs)) for i := range reqs { resps[i] = applyUnion(txnID, kv, reqs[i]) } if len(resps) != 0 { revision++ } txnResp := &etcdserverpb.TxnResponse{} txnResp.Header = &etcdserverpb.ResponseHeader{} txnResp.Header.Revision = revision txnResp.Responses = resps txnResp.Succeeded = ok return txnResp, nil }