本文整理汇总了Golang中github.com/cockroachdb/cockroach/roachpb.Error类的典型用法代码示例。如果您正苦于以下问题:Golang Error类的具体用法?Golang Error怎么用?Golang Error使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Error类的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: executeCmd
// executeCmd interprets the given message as a *roachpb.BatchRequest and sends it
// via the local sender.
func (n *Node) executeCmd(argsI proto.Message) (proto.Message, error) {
ba := argsI.(*roachpb.BatchRequest)
var br *roachpb.BatchResponse
f := func() {
// TODO(tschottdorf) get a hold of the client's ID, add it to the
// context before dispatching, and create an ID for tracing the request.
sp := n.ctx.Tracer.StartSpan("node")
defer sp.Finish()
ctx, _ := opentracing.ContextWithSpan((*Node)(n).context(), sp)
tStart := time.Now()
var pErr *roachpb.Error
br, pErr = n.stores.Send(ctx, *ba)
if pErr != nil {
br = &roachpb.BatchResponse{}
sp.LogEvent(fmt.Sprintf("error: %T", pErr.GetDetail()))
}
if br.Error != nil {
panic(roachpb.ErrorUnexpectedlySet(n.stores, br))
}
n.feed.CallComplete(*ba, time.Now().Sub(tStart), pErr)
br.Error = pErr
}
if !n.stopper.RunTask(f) {
return nil, util.Errorf("node %d stopped", n.Descriptor.NodeID)
}
return br, nil
}
开发者ID:guanqun,项目名称:cockroach,代码行数:32,代码来源:node.go
示例2: convertBatchError
func convertBatchError(tableDesc *TableDescriptor, b client.Batch, origPErr *roachpb.Error) *roachpb.Error {
if origPErr.Index == nil {
return origPErr
}
index := origPErr.Index.Index
if index >= int32(len(b.Results)) {
panic(fmt.Sprintf("index %d outside of results: %+v", index, b.Results))
}
result := b.Results[index]
if _, ok := origPErr.GoError().(*roachpb.ConditionFailedError); ok {
for _, row := range result.Rows {
indexID, key, pErr := decodeIndexKeyPrefix(tableDesc, row.Key)
if pErr != nil {
return pErr
}
index, pErr := tableDesc.FindIndexByID(indexID)
if pErr != nil {
return pErr
}
valTypes, pErr := makeKeyVals(tableDesc, index.ColumnIDs)
if pErr != nil {
return pErr
}
vals := make([]parser.Datum, len(valTypes))
if _, pErr := decodeKeyVals(valTypes, vals, key); pErr != nil {
return pErr
}
return roachpb.NewError(errUniquenessConstraintViolation{index: index, vals: vals})
}
}
return origPErr
}
开发者ID:xnyan,项目名称:cockroach,代码行数:33,代码来源:errors.go
示例3: makeResultFromError
// If we hit an error and there is a pending transaction, rollback
// the transaction before returning. The client does not have to
// deal with cleaning up transaction state.
func makeResultFromError(planMaker *planner, pErr *roachpb.Error) Result {
if planMaker.txn != nil {
if _, ok := pErr.GoError().(*roachpb.SqlTransactionAbortedError); !ok {
planMaker.txn.Cleanup(pErr)
}
}
return Result{Err: pErr.GoError()}
}
开发者ID:harryge00,项目名称:cockroach,代码行数:11,代码来源:executor.go
示例4: TestTxnCoordSenderEndTxn
// TestTxnCoordSenderEndTxn verifies that ending a transaction
// sends resolve write intent requests and removes the transaction
// from the txns map.
func TestTxnCoordSenderEndTxn(t *testing.T) {
defer leaktest.AfterTest(t)
s := createTestDB(t)
defer s.Stop()
// 4 cases: no deadline, past deadline, equal deadline, future deadline.
for i := 0; i < 4; i++ {
key := roachpb.Key("key: " + strconv.Itoa(i))
txn := client.NewTxn(*s.DB)
// Initialize the transaction
if pErr := txn.Put(key, []byte("value")); pErr != nil {
t.Fatal(pErr)
}
{
var pErr *roachpb.Error
switch i {
case 0:
// No deadline.
pErr = txn.Commit()
case 1:
// Past deadline.
pErr = txn.CommitBy(txn.Proto.Timestamp.Prev())
case 2:
// Equal deadline.
pErr = txn.CommitBy(txn.Proto.Timestamp)
case 3:
// Future deadline.
pErr = txn.CommitBy(txn.Proto.Timestamp.Next())
}
switch i {
case 0:
// No deadline.
if pErr != nil {
t.Error(pErr)
}
case 1:
// Past deadline.
if _, ok := pErr.GoError().(*roachpb.TransactionAbortedError); !ok {
t.Errorf("expected TransactionAbortedError but got %T: %s", pErr, pErr)
}
case 2:
// Equal deadline.
if pErr != nil {
t.Error(pErr)
}
case 3:
// Future deadline.
if pErr != nil {
t.Error(pErr)
}
}
}
verifyCleanup(key, s.Sender, s.Eng, t)
}
}
开发者ID:kimh,项目名称:cockroach,代码行数:60,代码来源:txn_coord_sender_test.go
示例5: sendPError
func (c *v3Conn) sendPError(pErr *roachpb.Error) error {
var errCode string
if sqlErr, ok := pErr.GetDetail().(*roachpb.ErrorWithPGCode); ok {
errCode = sqlErr.ErrorCode
} else {
errCode = sql.CodeInternalError
}
return c.sendError(errCode, pErr.String())
}
开发者ID:petermattis,项目名称:cockroach,代码行数:9,代码来源:v3.go
示例6: processWriteIntentError
// processWriteIntentError tries to push the conflicting
// transaction(s) responsible for the given WriteIntentError, and to
// resolve those intents if possible. Returns a new error to be used
// in place of the original.
//
// The returned error may be a copy of the original WriteIntentError,
// with or without the Resolved flag set, which governs the client's
// retry behavior (if the transaction is pushed, the Resolved flag is
// set to tell the client to retry immediately; otherwise it is false
// to cause the client to back off).
func (ir *intentResolver) processWriteIntentError(ctx context.Context,
wiPErr *roachpb.Error, args roachpb.Request, h roachpb.Header,
pushType roachpb.PushTxnType) *roachpb.Error {
wiErr, ok := wiPErr.GetDetail().(*roachpb.WriteIntentError)
if !ok {
return roachpb.NewErrorf("not a WriteIntentError: %v", wiPErr)
}
if log.V(6) {
log.Infof(ctx, "resolving write intent %s", wiErr)
}
method := args.Method()
readOnly := roachpb.IsReadOnly(args) // TODO(tschottdorf): pass as param
resolveIntents, pushErr := ir.maybePushTransactions(ctx, wiErr.Intents, h, pushType, false)
if resErr := ir.resolveIntents(ctx, resolveIntents,
false /* !wait */, pushType == roachpb.PUSH_ABORT /* poison */); resErr != nil {
// When resolving without waiting, errors should not
// usually be returned here, although there are some cases
// when they may be (especially when a test cluster is in
// the process of shutting down).
log.Warningf(ctx, "asynchronous resolveIntents failed: %s", resErr)
}
if pushErr != nil {
if log.V(1) {
log.Infof(ctx, "on %s: %s", method, pushErr)
}
if _, isExpected := pushErr.GetDetail().(*roachpb.TransactionPushError); !isExpected {
// If an unexpected error occurred, make sure it bubbles up to the
// client. Examples are timeouts and logic errors.
return pushErr
}
// For write/write conflicts within a transaction, propagate the
// push failure, not the original write intent error. The push
// failure will instruct the client to restart the transaction
// with a backoff.
if h.Txn != nil && h.Txn.ID != nil && !readOnly {
return pushErr
}
// For read/write conflicts, and non-transactional write/write
// conflicts, return the write intent error which engages
// backoff/retry (with !Resolved). We don't need to restart the
// txn, only resend the read with a backoff.
return wiPErr
}
// We pushed all transactions, so tell the client everything's
// resolved and it can retry immediately.
wiErr.Resolved = true
return wiPErr // references wiErr
}
开发者ID:yangxuanjia,项目名称:cockroach,代码行数:67,代码来源:intent_resolver.go
示例7: makeResultFromError
// If we hit an error and there is a pending transaction, rollback
// the transaction before returning. The client does not have to
// deal with cleaning up transaction state.
func makeResultFromError(planMaker *planner, pErr *roachpb.Error) driver.Response_Result {
if planMaker.txn != nil {
if _, ok := pErr.GoError().(*roachpb.SqlTransactionAbortedError); !ok {
planMaker.txn.Cleanup(pErr)
}
}
errString := pErr.GoError().Error()
return driver.Response_Result{Error: &errString}
}
开发者ID:billhongs,项目名称:cockroach,代码行数:12,代码来源:executor.go
示例8: Exec
// Exec executes fn in the context of a distributed transaction.
// Execution is controlled by opt (see comments in TxnExecOptions).
//
// opt is passed to fn, and it's valid for fn to modify opt as it sees
// fit during each execution attempt.
//
// It's valid for txn to be nil (meaning the txn has already aborted) if fn
// can handle that. This is useful for continuing transactions that have been
// aborted because of an error in a previous batch of statements in the hope
// that a ROLLBACK will reset the state. Neither opt.AutoRetry not opt.AutoCommit
// can be set in this case.
//
// If an error is returned, the txn has been aborted.
func (txn *Txn) Exec(
opt TxnExecOptions,
fn func(txn *Txn, opt *TxnExecOptions) *roachpb.Error) *roachpb.Error {
// Run fn in a retry loop until we encounter a success or
// error condition this loop isn't capable of handling.
var pErr *roachpb.Error
var retryOptions retry.Options
if txn == nil && (opt.AutoRetry || opt.AutoCommit) {
panic("asked to retry or commit a txn that is already aborted")
}
if opt.AutoRetry {
retryOptions = txn.db.txnRetryOptions
}
RetryLoop:
for r := retry.Start(retryOptions); r.Next(); {
pErr = fn(txn, &opt)
if (pErr == nil) && opt.AutoCommit && (txn.Proto.Status == roachpb.PENDING) {
// fn succeeded, but didn't commit.
pErr = txn.commit(nil)
}
if pErr == nil {
break
}
// Make sure the txn record that pErr carries is for this txn.
// We check only when txn.Proto.ID has been initialized after an initial successful send.
if pErr.GetTxn() != nil && txn.Proto.ID != nil {
if errTxn := pErr.GetTxn(); !errTxn.Equal(&txn.Proto) {
return roachpb.NewErrorf("mismatching transaction record in the error:\n%s\nv.s.\n%s",
errTxn, txn.Proto)
}
}
if !opt.AutoRetry {
break RetryLoop
}
switch pErr.TransactionRestart {
case roachpb.TransactionRestart_IMMEDIATE:
r.Reset()
case roachpb.TransactionRestart_BACKOFF:
default:
break RetryLoop
}
if log.V(2) {
log.Infof("automatically retrying transaction: %s because of error: %s",
txn.DebugName(), pErr)
}
}
if txn != nil {
// TODO(andrei): don't do Cleanup() on retriable errors here.
// Let the sql executor do it.
txn.Cleanup(pErr)
}
return pErr
}
开发者ID:mrtracy,项目名称:cockroach,代码行数:69,代码来源:txn.go
示例9: encodeDTuple
func encodeDTuple(b []byte, d parser.DTuple) ([]byte, error) {
for _, val := range d {
var pErr *roachpb.Error
b, pErr = encodeDatum(b, val)
if pErr != nil {
return nil, pErr.GoError()
}
}
return b, nil
}
开发者ID:l2x,项目名称:cockroach,代码行数:10,代码来源:group.go
示例10: executeCmd
// executeCmd interprets the given message as a *roachpb.BatchRequest and sends it
// via the local sender.
func (n *Node) executeCmd(argsI proto.Message) (proto.Message, error) {
ba := argsI.(*roachpb.BatchRequest)
var br *roachpb.BatchResponse
opName := "node " + strconv.Itoa(int(n.Descriptor.NodeID)) // could save allocs here
fail := func(err error) {
br = &roachpb.BatchResponse{}
br.Error = roachpb.NewError(err)
}
f := func() {
sp, err := tracing.JoinOrNew(n.ctx.Tracer, ba.Trace, opName)
if err != nil {
fail(err)
return
}
// If this is a snowball span, it gets special treatment: It skips the
// regular tracing machinery, and we instead send the collected spans
// back with the response. This is more expensive, but then again,
// those are individual requests traced by users, so they can be.
if sp.BaggageItem(tracing.Snowball) != "" {
if sp, err = tracing.JoinOrNewSnowball(opName, ba.Trace, func(rawSpan basictracer.RawSpan) {
encSp, err := tracing.EncodeRawSpan(&rawSpan, nil)
if err != nil {
log.Warning(err)
}
br.CollectedSpans = append(br.CollectedSpans, encSp)
}); err != nil {
fail(err)
return
}
}
defer sp.Finish()
ctx := opentracing.ContextWithSpan((*Node)(n).context(), sp)
tStart := time.Now()
var pErr *roachpb.Error
br, pErr = n.stores.Send(ctx, *ba)
if pErr != nil {
br = &roachpb.BatchResponse{}
sp.LogEvent(fmt.Sprintf("error: %T", pErr.GetDetail()))
}
if br.Error != nil {
panic(roachpb.ErrorUnexpectedlySet(n.stores, br))
}
n.metrics.callComplete(time.Now().Sub(tStart), pErr)
br.Error = pErr
}
if !n.stopper.RunTask(f) {
return nil, util.Errorf("node %d stopped", n.Descriptor.NodeID)
}
return br, nil
}
开发者ID:liugangnhm,项目名称:cockroach,代码行数:56,代码来源:node.go
示例11: shouldCacheError
// Responses with write-too-old, write-intent and not leader errors
// are retried on the server, and so are not recorded in the sequence
// cache in the hopes of retrying to a successful outcome.
func (sc *SequenceCache) shouldCacheError(pErr *roachpb.Error) bool {
switch pErr.GoError().(type) {
case *roachpb.WriteTooOldError, *roachpb.WriteIntentError, *roachpb.NotLeaderError, *roachpb.RangeKeyMismatchError:
return false
}
return true
}
开发者ID:billhongs,项目名称:cockroach,代码行数:10,代码来源:sequence_cache.go
示例12: exec
func (txn *Txn) exec(retryable func(txn *Txn) *roachpb.Error) *roachpb.Error {
// Run retryable in a retry loop until we encounter a success or
// error condition this loop isn't capable of handling.
var pErr *roachpb.Error
for r := retry.Start(txn.db.txnRetryOptions); r.Next(); {
pErr = retryable(txn)
if pErr == nil && txn.Proto.Status == roachpb.PENDING {
// retryable succeeded, but didn't commit.
pErr = txn.commit(nil)
}
if pErr != nil {
// Make sure the txn record that pErr carries is for this txn.
// We check only when txn.Proto.ID has been initialized after an initial successful send.
if pErr.GetTxn() != nil && txn.Proto.ID != nil {
if errTxn := pErr.GetTxn(); !errTxn.Equal(&txn.Proto) {
return roachpb.NewErrorf("mismatching transaction record in the error:\n%s\nv.s.\n%s",
errTxn, txn.Proto)
}
}
switch pErr.TransactionRestart {
case roachpb.TransactionRestart_IMMEDIATE:
if log.V(2) {
log.Warning(pErr)
}
r.Reset()
continue
case roachpb.TransactionRestart_BACKOFF:
if log.V(2) {
log.Warning(pErr)
}
continue
}
// By default, fall through and break.
}
break
}
txn.Cleanup(pErr)
return pErr
}
开发者ID:binlijin,项目名称:cockroach,代码行数:41,代码来源:txn.go
示例13: convertBatchError
func convertBatchError(tableDesc *TableDescriptor, b client.Batch, origPErr *roachpb.Error) *roachpb.Error {
if origPErr.Index == nil {
return origPErr
}
index := origPErr.Index.Index
if index >= int32(len(b.Results)) {
panic(fmt.Sprintf("index %d outside of results: %+v", index, b.Results))
}
result := b.Results[index]
if _, ok := origPErr.GetDetail().(*roachpb.ConditionFailedError); ok {
for _, row := range result.Rows {
indexID, key, err := decodeIndexKeyPrefix(tableDesc, row.Key)
if err != nil {
return roachpb.NewError(err)
}
index, err := tableDesc.FindIndexByID(indexID)
if err != nil {
return roachpb.NewError(err)
}
valTypes, err := makeKeyVals(tableDesc, index.ColumnIDs)
if err != nil {
return roachpb.NewError(err)
}
dirs := make([]encoding.Direction, 0, len(index.ColumnIDs))
for _, dir := range index.ColumnDirections {
convertedDir, err := dir.toEncodingDirection()
if err != nil {
return roachpb.NewError(err)
}
dirs = append(dirs, convertedDir)
}
vals := make([]parser.Datum, len(valTypes))
if _, err := decodeKeyVals(valTypes, vals, dirs, key); err != nil {
return roachpb.NewError(err)
}
return sqlErrToPErr(&errUniquenessConstraintViolation{index: index, vals: vals})
}
}
return origPErr
}
开发者ID:petermattis,项目名称:cockroach,代码行数:41,代码来源:errors.go
示例14: CallComplete
// CallComplete is called by a node whenever it completes a request. This will
// publish appropriate events to the feed:
// - For a successful request, a corresponding event for each request in the batch,
// - on error without index information, a failure of the Batch, and
// - on an indexed error a failure of the individual request.
func (nef NodeEventFeed) CallComplete(ba roachpb.BatchRequest, pErr *roachpb.Error) {
if pErr != nil && pErr.TransactionRestart == roachpb.TransactionRestart_ABORT {
method := roachpb.Batch
if iErr, ok := pErr.GoError().(roachpb.IndexedError); ok {
if index, ok := iErr.ErrorIndex(); ok {
method = ba.Requests[index].GetInner().Method()
}
}
nef.f.Publish(&CallErrorEvent{
NodeID: nef.id,
Method: method,
})
return
}
for _, union := range ba.Requests {
nef.f.Publish(&CallSuccessEvent{
NodeID: nef.id,
Method: union.GetInner().Method(),
})
}
}
开发者ID:mbertschler,项目名称:cockroach,代码行数:26,代码来源:feed.go
示例15: handlePerReplicaError
// handlePerReplicaError returns true if the given error is likely to
// be unique to the replica that reported it, and retrying on other
// replicas is likely to produce different results. This method should
// be called only once for each error as it may have side effects such
// as updating caches.
func (ds *DistSender) handlePerReplicaError(rangeID roachpb.RangeID, pErr *roachpb.Error) bool {
switch tErr := pErr.GetDetail().(type) {
case *roachpb.RangeNotFoundError:
return true
case *roachpb.NodeUnavailableError:
return true
case *roachpb.NotLeaseHolderError:
if tErr.LeaseHolder != nil {
// If the replica we contacted knows the new lease holder, update the cache.
ds.updateLeaseHolderCache(rangeID, *tErr.LeaseHolder)
// TODO(bdarnell): Move the new lease holder to the head of the queue
// for the next retry.
}
return true
}
return false
}
开发者ID:yaojingguo,项目名称:cockroach,代码行数:23,代码来源:dist_sender.go
示例16: Query
// Query returns datapoints for the named time series during the supplied time
// span. Data is returned as a series of consecutive data points.
//
// Data is queried only at the Resolution supplied: if data for the named time
// series is not stored at the given resolution, an empty result will be
// returned.
//
// All data stored on the server is downsampled to some degree; the data points
// returned represent the average value within a sample period. Each datapoint's
// timestamp falls in the middle of the sample period it represents.
//
// If data for the named time series was collected from multiple sources, each
// returned datapoint will represent the sum of datapoints from all sources at
// the same time. The returned string slices contains a list of all sources for
// the metric which were aggregated to produce the result.
func (db *DB) Query(query Query, r Resolution, startNanos, endNanos int64) ([]TimeSeriesDatapoint, []string, error) {
// Normalize startNanos and endNanos the nearest SampleDuration boundary.
startNanos -= startNanos % r.SampleDuration()
var rows []client.KeyValue
if len(query.Sources) == 0 {
// Based on the supplied timestamps and resolution, construct start and end
// keys for a scan that will return every key with data relevant to the
// query.
startKey := MakeDataKey(query.Name, "" /* source */, r, startNanos)
endKey := MakeDataKey(query.Name, "" /* source */, r, endNanos).PrefixEnd()
var pErr *roachpb.Error
rows, pErr = db.db.ScanInconsistent(startKey, endKey, 0)
if pErr != nil {
return nil, nil, pErr.GoError()
}
} else {
b := db.db.NewBatch()
b.ReadConsistency = roachpb.INCONSISTENT
// Iterate over all key timestamps which may contain data for the given
// sources, based on the given start/end time and the resolution.
kd := r.KeyDuration()
startKeyNanos := startNanos - (startNanos % kd)
endKeyNanos := endNanos - (endNanos % kd)
for currentTimestamp := startKeyNanos; currentTimestamp <= endKeyNanos; currentTimestamp += kd {
for _, source := range query.Sources {
key := MakeDataKey(query.Name, source, r, currentTimestamp)
b.Get(key)
}
}
pErr := db.db.Run(b)
if pErr != nil {
return nil, nil, pErr.GoError()
}
for _, result := range b.Results {
row := result.Rows[0]
if row.Value == nil {
continue
}
rows = append(rows, row)
}
}
// Convert the queried source data into a set of data spans, one for each
// source.
sourceSpans, err := makeDataSpans(rows, startNanos)
if err != nil {
return nil, nil, err
}
// Compute a downsample function which will be used to return values from
// each source for each sample period.
downsampler, err := getDownsampleFunction(query.GetDownsampler())
if err != nil {
return nil, nil, err
}
// If we are returning a derivative, iteration needs to start at offset -1
// (in order to correctly compute the rate of change at offset 0).
var startOffset int32
isDerivative := query.GetDerivative() != TimeSeriesQueryDerivative_NONE
if isDerivative {
startOffset = -1
}
// Create an interpolatingIterator for each dataSpan, adding each iterator
// into a unionIterator collection. This is also where we compute a list of
// all sources with data present in the query.
sources := make([]string, 0, len(sourceSpans))
iters := make(unionIterator, 0, len(sourceSpans))
for name, span := range sourceSpans {
sources = append(sources, name)
iters = append(iters, span.newIterator(startOffset, downsampler))
}
// Choose an aggregation function to use when taking values from the
// unionIterator.
var valueFn func() float64
switch query.GetSourceAggregator() {
case TimeSeriesQueryAggregator_SUM:
valueFn = iters.sum
case TimeSeriesQueryAggregator_AVG:
valueFn = iters.avg
case TimeSeriesQueryAggregator_MAX:
valueFn = iters.max
//.........这里部分代码省略.........
开发者ID:petermattis,项目名称:cockroach,代码行数:101,代码来源:query.go
示例17: updateState
// updateState updates the transaction state in both the success and
// error cases, applying those updates to the corresponding txnMeta
// object when adequate. It also updates certain errors with the
// updated transaction for use by client restarts.
func (tc *TxnCoordSender) updateState(ctx context.Context, ba roachpb.BatchRequest, br *roachpb.BatchResponse, pErr *roachpb.Error) *roachpb.Error {
trace := tracer.FromCtx(ctx)
newTxn := &roachpb.Transaction{}
newTxn.Update(ba.GetTxn())
// TODO(tamird): remove this clone. It's currently needed to avoid race conditions.
pErr = proto.Clone(pErr).(*roachpb.Error)
err := pErr.GoError()
// TODO(bdarnell): We're writing to errors here (and where using ErrorWithIndex);
// since there's no concept of ownership copy-on-write is always preferable.
switch t := err.(type) {
case nil:
newTxn.Update(br.Txn)
// Move txn timestamp forward to response timestamp if applicable.
// TODO(tschottdorf): see (*Replica).executeBatch and comments within.
// Looks like this isn't necessary any more, nor did it prevent a bug
// referenced in a TODO there.
newTxn.Timestamp.Forward(br.Timestamp)
case *roachpb.TransactionStatusError:
// Likely already committed or more obscure errors such as epoch or
// timestamp regressions; consider txn dead.
defer tc.cleanupTxn(trace, t.Txn)
case *roachpb.OpRequiresTxnError:
panic("OpRequiresTxnError must not happen at this level")
case *roachpb.ReadWithinUncertaintyIntervalError:
// Mark the host as certain. See the protobuf comment for
// Transaction.CertainNodes for details.
if t.NodeID == 0 {
panic("no replica set in header on uncertainty restart")
}
newTxn.Update(&t.Txn)
newTxn.CertainNodes.Add(t.NodeID)
// If the reader encountered a newer write within the uncertainty
// interval, move the timestamp forward, just past that write or
// up to MaxTimestamp, whichever comes first.
candidateTS := newTxn.MaxTimestamp
candidateTS.Backward(t.ExistingTimestamp.Add(0, 1))
newTxn.Timestamp.Forward(candidateTS)
newTxn.Restart(ba.GetUserPriority(), newTxn.Priority, newTxn.Timestamp)
t.Txn = *newTxn
case *roachpb.TransactionAbortedError:
trace.SetError()
newTxn.Update(&t.Txn)
// Increase timestamp if applicable.
newTxn.Timestamp.Forward(t.Txn.Timestamp)
newTxn.Priority = t.Txn.Priority
t.Txn = *newTxn
// Clean up the freshly aborted transaction in defer(), avoiding a
// race with the state update below.
defer tc.cleanupTxn(trace, t.Txn)
case *roachpb.TransactionPushError:
newTxn.Update(t.Txn)
// Increase timestamp if applicable, ensuring that we're
// just ahead of the pushee.
newTxn.Timestamp.Forward(t.PusheeTxn.Timestamp.Add(0, 1))
newTxn.Restart(ba.GetUserPriority(), t.PusheeTxn.Priority-1, newTxn.Timestamp)
t.Txn = newTxn
case *roachpb.TransactionRetryError:
newTxn.Update(&t.Txn)
newTxn.Restart(ba.GetUserPriority(), t.Txn.Priority, newTxn.Timestamp)
t.Txn = *newTxn
case roachpb.TransactionRestartError:
// Assertion: The above cases should exhaust all ErrorDetails which
// carry a Transaction.
if pErr.Detail != nil {
panic(fmt.Sprintf("unhandled TransactionRestartError %T", err))
}
default:
trace.SetError()
}
return func() *roachpb.Error {
if len(newTxn.ID) <= 0 {
return pErr
}
id := string(newTxn.ID)
tc.Lock()
defer tc.Unlock()
txnMeta := tc.txns[id]
// For successful transactional requests, keep the written intents and
// the updated transaction record to be sent along with the reply.
// The transaction metadata is created with the first writing operation.
// A tricky edge case is that of a transaction which "fails" on the
// first writing request, but actually manages to write some intents
// (for example, due to being multi-range). In this case, there will
// be an error, but the transaction will be marked as Writing and the
// coordinator must track the state, for the client's retry will be
// performed with a Writing transaction which the coordinator rejects
// unless it is tracking it (on top of it making sense to track it;
// after all, it **has** laid down intents and only the coordinator
// can augment a potential EndTransaction call).
// consider re-using those.
if intents := ba.GetIntents(); len(intents) > 0 && (err == nil || newTxn.Writing) {
if txnMeta == nil {
if !newTxn.Writing {
panic("txn with intents marked as non-writing")
}
//.........这里部分代码省略.........
开发者ID:rissoa,项目名称:cockroach,代码行数:101,代码来源:txn_coord_sender.go
示例18: Send
// Send implements the batch.Sender interface. If the request is part of a
// transaction, the TxnCoordSender adds the transaction to a map of active
// transactions and begins heartbeating it. Every subsequent request for the
// same transaction updates the lastUpdate timestamp to prevent live
// transactions from being considered abandoned and garbage collected.
// Read/write mutating requests have their key or key range added to the
// transaction's interval tree of key ranges for eventual cleanup via resolved
// write intents; they're tagged to an outgoing EndTransaction request, with
// the receiving replica in charge of resolving them.
func (tc *TxnCoordSender) Send(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) {
if err := tc.maybeBeginTxn(&ba); err != nil {
return nil, roachpb.NewError(err)
}
ba.CmdID = ba.GetOrCreateCmdID(tc.clock.PhysicalNow())
var startNS int64
// This is the earliest point at which the request has a ClientCmdID and/or
// TxnID (if applicable). Begin a Trace which follows this request.
trace := tc.tracer.NewTrace(tracer.Coord, &ba)
defer trace.Finalize()
defer trace.Epoch("sending batch")()
ctx = tracer.ToCtx(ctx, trace)
var id string // optional transaction ID
if ba.Txn != nil {
// If this request is part of a transaction...
id = string(ba.Txn.ID)
// Verify that if this Transaction is not read-only, we have it on
// file. If not, refuse writes - the client must have issued a write on
// another coordinator previously.
if ba.Txn.Writing && ba.IsTransactionWrite() {
tc.Lock()
_, ok := tc.txns[id]
tc.Unlock()
if !ok {
return nil, roachpb.NewError(util.Errorf("transaction must not write on multiple coordinators"))
}
}
// Set the timestamp to the original timestamp for read-only
// commands and to the transaction timestamp for read/write
// commands.
if ba.IsReadOnly() {
ba.Timestamp = ba.Txn.OrigTimestamp
} else {
ba.Timestamp = ba.Txn.Timestamp
}
if rArgs, ok := ba.GetArg(roachpb.EndTransaction); ok {
et := rArgs.(*roachpb.EndTransactionRequest)
if len(et.Key) != 0 {
return nil, roachpb.NewError(util.Errorf("EndTransaction must not have a Key set"))
}
et.Key = ba.Txn.Key
// Remember when EndTransaction started in case we want to
// be linearizable.
startNS = tc.clock.PhysicalNow()
if len(et.Intents) > 0 {
// TODO(tschottdorf): it may be useful to allow this later.
// That would be part of a possible plan to allow txns which
// write on multiple coordinators.
return nil, roachpb.NewError(util.Errorf("client must not pass intents to EndTransaction"))
}
tc.Lock()
txnMeta, metaOK := tc.txns[id]
if id != "" && metaOK {
et.Intents = txnMeta.intents()
}
tc.Unlock()
if intents := ba.GetIntents(); len(intents) > 0 {
// Writes in Batch, so EndTransaction is fine. Should add
// outstanding intents to EndTransaction, though.
// TODO(tschottdorf): possible issues when the batch fails,
// but the intents have been added anyways.
// TODO(tschottdorf): some of these intents may be covered
// by others, for example {[a,b), a}). This can lead to
// some extra requests when those are non-local to the txn
// record. But it doesn't seem worth optimizing now.
et.Intents = append(et.Intents, intents...)
} else if !metaOK {
// If we don't have the transaction, then this must be a retry
// by the client. We can no longer reconstruct a correct
// request so we must fail.
//
// TODO(bdarnell): if we had a GetTransactionStatus API then
// we could lookup the transaction and return either nil or
// TransactionAbortedError instead of this ambivalent error.
return nil, roachpb.NewError(util.Errorf("transaction is already committed or aborted"))
}
if len(et.Intents) == 0 {
// If there aren't any intents, then there's factually no
// transaction to end. Read-only txns have all of their state in
// the client.
return nil, roachpb.NewError(util.Errorf("cannot commit a read-only transaction"))
}
if log.V(1) {
for _, intent := range et.Intents {
trace.Event(fmt.Sprintf("intent: [%s,%s)", intent.Key, intent.EndKey))
}
//.........这里部分代码省略.........
开发者ID:rissoa,项目名称:cockroach,代码行数:101,代码来源:txn_coord_sender.go
示例19: sendChunk
// sendChunk is in charge of sending an "admissible" piece of batch, i.e. one
// which doesn't need to be subdivided further before going to a range (so no
// mixing of forward and reverse scans, etc). The parameters and return values
// correspond to client.Sender with the exception of the returned boolean,
// which is true when indicating that the caller should retry but needs to send
// EndTransaction in a separate request.
func (ds *DistSender) sendChunk(ctx context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error, bool) {
isReverse := ba.IsReverse()
// TODO(radu): when contexts are properly plumbed, we should be able to get
// the tracer from ctx, not from the DistSender.
ctx, cleanup := tracing.EnsureContext(ctx, tracing.TracerFromCtx(ds.Ctx))
defer cleanup()
// The minimal key range encompassing all requests contained within.
// Local addressing has already been resolved.
// TODO(tschottdorf): consider rudimentary validation of the batch here
// (for example, non-range requests with EndKey, or empty key ranges).
rs, err := keys.Range(ba)
if err != nil {
return nil, roachpb.NewError(err), false
}
var br *roachpb.BatchResponse
// Send the request to one range per iteration.
for {
// Increase the sequence counter only once before sending RPCs to
// the ranges involved in this chunk of the batch (as opposed to for
// each RPC individually). On RPC errors, there's no guarantee that
// the request hasn't made its way to the target regardless of the
// error; we'd like the second execution to be caught by the sequence
// cache if that happens. There is a small chance that that we address
// a range twice in this chunk (stale/suboptimal descriptors due to
// splits/merges) which leads to a transaction retry.
// TODO(tschottdorf): it's possible that if we don't evict from the
// cache we could be in for a busy loop.
ba.SetNewRequest()
var curReply *roachpb.BatchResponse
var desc *roachpb.RangeDescriptor
var evictToken *evictionToken
var needAnother bool
var pErr *roachpb.Error
var finished bool
var numAttempts int
for r := retry.StartWithCtx(ctx, ds.rpcRetryOptions); r.Next(); {
numAttempts++
{
const magicLogCurAttempt = 20
var seq int32
if ba.Txn != nil {
seq = ba.Txn.Sequence
}
if numAttempts%magicLogCurAttempt == 0 || seq%magicLogCurAttempt == 0 {
// Log a message if a request appears to get stuck for a long
// time or, potentially, forever. See #8975.
// The local counter captures this loop here; the Sequence number
// should capture anything higher up (as it needs to be
// incremented every time this method is called).
log.Warningf(
ctx,
"%d retries for an RPC at sequence %d, last error was: %s, remaining key ranges %s: %s",
numAttempts, seq, pErr, rs, ba,
)
}
}
// Get range descriptor (or, when spanning range, descriptors). Our
// error handling below may clear them on certain errors, so we
// refresh (likely from the cache) on every retry.
log.Trace(ctx, "meta descriptor lookup")
var err error
desc, needAnother, evictToken, err = ds.getDescriptors(ctx, rs, evictToken, isReverse)
// getDescriptors may fail retryably if, for example, the first
// range isn't available via Gossip. Assume that all errors at
// this level are retryable. Non-retryable errors would be for
// things like malformed requests which we should have checked
// for before reaching this point.
if err != nil {
log.Trace(ctx, "range descriptor lookup failed: "+err.Error())
if log.V(1) {
log.Warning(ctx, err)
}
pErr = roachpb.NewError(err)
continue
}
if needAnother && br == nil {
// TODO(tschottdorf): we should have a mechanism for discovering
// range merges (descriptor staleness will mostly go unnoticed),
// or we'll be turning single-range queries into multi-range
// queries for no good reason.
// If there's no transaction and op spans ranges, possibly
// re-run as part of a transaction for consistency. The
// case where we don't need to re-run is if the read
// consistency is not required.
if ba.Txn == nil && ba.IsPossibleTransaction() &&
//.........这里部分代码省略.........
开发者ID:yaojingguo,项目名称:cockroach,代码行数:101,代码来源:dist_sender.go
示例20: Exec
// Exec executes fn in the context of a distributed transaction.
// Execution is controlled by opt (see comments in TxnExecOptions).
//
// opt is passed to fn, and it's valid for fn to modify opt as it sees
// fit during each execution attempt.
//
// It's valid for txn to be nil (meaning the txn has already aborted) if fn
// can handle that. This is useful for continuing transactions that have been
// aborted because of an error in a previous batch of statements in the hope
// that a ROLLBACK will reset the state. Neither opt.AutoRetry not opt.AutoCommit
// can be set in this case.
//
// When this method returns, txn might be in any state; Exec does not attempt
// to clean up the transaction before returning an error. In case of
// TransactionAbortedError, txn is reset to a fresh transaction, ready to be
// used.
//
// TODO(andrei): Make Exec() return error; make fn return an error + a retriable
// bit. There's no reason to propagate roachpb.Error (protos) above this point.
func (txn *Txn) Exec(
opt TxnExecOptions,
fn func(txn *Txn, opt *TxnExecOptions) *roachpb.Error) *roachpb.Error {
// Run fn in a retry loop until we encounter a success or
// error condition this loop isn't capable of handling.
var pErr *roachpb.Error
var retryOptions retry.Options
if txn == nil && (opt.AutoRetry || opt.AutoCommit) {
panic("asked to retry or commit a txn that is already aborted")
}
if opt.AutoRetry {
retryOptions = txn.db.txnRetryOptions
}
RetryLoop:
for r := retry.Start(retryOptions); r.Next(); {
if txn != nil {
// If we're looking at a brand new transaction, then communicate
// what should be used as initial timestamp for the KV txn created
// by TxnCoordSender.
if txn.Proto.OrigTimestamp == roachpb.ZeroTimestamp {
txn.Proto.OrigTimestamp = opt.MinInitialTimestamp
}
}
pErr = fn(txn, &opt)
if txn != nil {
txn.retrying = true
defer func() {
txn.retrying = false
}()
}
if (pErr == nil) && opt.AutoCommit && (txn.Proto.Status == roachpb.PENDING) {
// fn succeeded, but didn't commit.
pErr = txn.Commit()
}
if pErr == nil {
break
}
// Make sure the txn record that pErr carries is for this txn.
// We check only when txn.Proto.ID has been initialized after an initial successful send.
if pErr.GetTxn() != nil && txn.Proto.ID != nil {
if errTxn := pErr.GetTxn(); !errTxn.Equal(&txn.Proto) {
return roachpb.NewErrorf("mismatching transaction record in the error:\n%s\nv.s.\n%s",
errTxn, txn.Proto)
}
}
if !opt.AutoRetry {
break RetryLoop
}
switch pErr.TransactionRestart {
case roachpb.TransactionRestart_IMMEDIATE:
r.Reset()
case roachpb.TransactionRestart_BACKOFF:
default:
break RetryLoop
}
if log.V(2) {
log.Infof("automatically retrying transaction: %s because of error: %s",
txn.DebugName(), pErr)
}
}
if pErr != nil {
pErr.StripErrorTransaction()
}
return pErr
}
开发者ID |
请发表评论