本文整理汇总了Golang中github.com/cockroachdb/cockroach/pkg/util/log.Eventf函数的典型用法代码示例。如果您正苦于以下问题:Golang Eventf函数的具体用法?Golang Eventf怎么用?Golang Eventf使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了Eventf函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: maybeSignalStatusChangeLocked
// maybeSignalStatusChangeLocked checks whether gossip should transition its
// internal state from connected to stalled or vice versa.
func (g *Gossip) maybeSignalStatusChangeLocked() {
ctx := g.AnnotateCtx(context.TODO())
orphaned := g.outgoing.len()+g.mu.incoming.len() == 0
stalled := orphaned || g.mu.is.getInfo(KeySentinel) == nil
if stalled {
// We employ the stalled boolean to avoid filling logs with warnings.
if !g.stalled {
log.Eventf(ctx, "now stalled")
if orphaned {
if len(g.resolvers) == 0 {
log.Warningf(ctx, "no resolvers found; use --join to specify a connected node")
} else {
log.Warningf(ctx, "no incoming or outgoing connections")
}
} else if len(g.resolversTried) == len(g.resolvers) {
log.Warningf(ctx, "first range unavailable; resolvers exhausted")
} else {
log.Warningf(ctx, "first range unavailable; trying remaining resolvers")
}
}
if len(g.resolvers) > 0 {
g.signalStalledLocked()
}
} else {
if g.stalled {
log.Eventf(ctx, "connected")
log.Infof(ctx, "node has connected to cluster via gossip")
g.signalConnectedLocked()
}
g.maybeCleanupBootstrapAddressesLocked()
}
g.stalled = stalled
}
开发者ID:knz,项目名称:cockroach,代码行数:35,代码来源:gossip.go
示例2: addInternal
// addInternal adds the replica the queue with specified priority. If
// the replica is already queued, updates the existing
// priority. Expects the queue lock to be held by caller.
func (bq *baseQueue) addInternal(
ctx context.Context, desc *roachpb.RangeDescriptor, should bool, priority float64,
) (bool, error) {
if bq.mu.stopped {
return false, errQueueStopped
}
if bq.mu.disabled {
log.Event(ctx, "queue disabled")
return false, errQueueDisabled
}
if !desc.IsInitialized() {
// We checked this above in MaybeAdd(), but we need to check it
// again for Add().
return false, errors.New("replica not initialized")
}
// If the replica is currently in purgatory, don't re-add it.
if _, ok := bq.mu.purgatory[desc.RangeID]; ok {
return false, nil
}
item, ok := bq.mu.replicas[desc.RangeID]
if !should {
if ok {
log.Eventf(ctx, "%s: removing from queue", item.value)
bq.remove(item)
}
return false, errReplicaNotAddable
} else if ok {
if item.priority != priority {
log.Eventf(ctx, "%s: updating priority: %0.3f -> %0.3f",
desc, item.priority, priority)
}
// Replica has already been added; update priority.
bq.mu.priorityQ.update(item, priority)
return false, nil
}
log.VEventf(ctx, 3, "%s: adding: priority=%0.3f", desc, priority)
item = &replicaItem{value: desc.RangeID, priority: priority}
bq.add(item)
// If adding this replica has pushed the queue past its maximum size,
// remove the lowest priority element.
if pqLen := bq.mu.priorityQ.Len(); pqLen > bq.maxSize {
bq.remove(bq.mu.priorityQ[pqLen-1])
}
// Signal the processLoop that a replica has been added.
select {
case bq.incoming <- struct{}{}:
default:
// No need to signal again.
}
return true, nil
}
开发者ID:knz,项目名称:cockroach,代码行数:60,代码来源:queue.go
示例3: bootstrap
// bootstrap connects the node to the gossip network. Bootstrapping
// commences in the event there are no connected clients or the
// sentinel gossip info is not available. After a successful bootstrap
// connection, this method will block on the stalled condvar, which
// receives notifications that gossip network connectivity has been
// lost and requires re-bootstrapping.
func (g *Gossip) bootstrap() {
g.server.stopper.RunWorker(func() {
ctx := g.AnnotateCtx(context.Background())
ctx = log.WithLogTag(ctx, "bootstrap", nil)
var bootstrapTimer timeutil.Timer
defer bootstrapTimer.Stop()
for {
if g.server.stopper.RunTask(func() {
g.mu.Lock()
defer g.mu.Unlock()
haveClients := g.outgoing.len() > 0
haveSentinel := g.mu.is.getInfo(KeySentinel) != nil
log.Eventf(ctx, "have clients: %t, have sentinel: %t", haveClients, haveSentinel)
if !haveClients || !haveSentinel {
// Try to get another bootstrap address from the resolvers.
if addr := g.getNextBootstrapAddress(); addr != nil {
g.startClient(addr, g.NodeID.Get())
} else {
bootstrapAddrs := make([]string, 0, len(g.bootstrapping))
for addr := range g.bootstrapping {
bootstrapAddrs = append(bootstrapAddrs, addr)
}
log.Eventf(ctx, "no next bootstrap address; currently bootstrapping: %v", bootstrapAddrs)
// We couldn't start a client, signal that we're stalled so that
// we'll retry.
g.maybeSignalStatusChangeLocked()
}
}
}) != nil {
return
}
// Pause an interval before next possible bootstrap.
bootstrapTimer.Reset(g.bootstrapInterval)
log.Eventf(ctx, "sleeping %s until bootstrap", g.bootstrapInterval)
select {
case <-bootstrapTimer.C:
bootstrapTimer.Read = true
// break
case <-g.server.stopper.ShouldStop():
return
}
log.Eventf(ctx, "idling until bootstrap required")
// Block until we need bootstrapping again.
select {
case <-g.stalledCh:
log.Eventf(ctx, "detected stall; commencing bootstrap")
// break
case <-g.server.stopper.ShouldStop():
return
}
}
})
}
开发者ID:knz,项目名称:cockroach,代码行数:60,代码来源:gossip.go
示例4: Seek
// Seek positions the iterator at the specified key.
func (ri *RangeIterator) Seek(ctx context.Context, key roachpb.RKey, scanDir ScanDirection) {
log.Eventf(ctx, "querying next range at %s", key)
ri.scanDir = scanDir
ri.init = true // the iterator is now initialized
ri.pErr = nil // clear any prior error
ri.key = key // set the key
// Retry loop for looking up next range in the span. The retry loop
// deals with retryable range descriptor lookups.
for r := retry.StartWithCtx(ctx, ri.ds.rpcRetryOptions); r.Next(); {
log.Event(ctx, "meta descriptor lookup")
var err error
ri.desc, ri.token, err = ri.ds.getDescriptor(
ctx, ri.key, ri.token, ri.scanDir == Descending)
// getDescriptor 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.VEventf(ctx, 1, "range descriptor lookup failed: %s", err)
continue
}
// It's possible that the returned descriptor misses parts of the
// keys it's supposed to include after it's truncated to match the
// descriptor. Example revscan [a,g), first desc lookup for "g"
// returns descriptor [c,d) -> [d,g) is never scanned.
// We evict and retry in such a case.
// TODO: this code is subject to removal. See
// https://groups.google.com/d/msg/cockroach-db/DebjQEgU9r4/_OhMe7atFQAJ
reverse := ri.scanDir == Descending
if (reverse && !ri.desc.ContainsExclusiveEndKey(ri.key)) ||
(!reverse && !ri.desc.ContainsKey(ri.key)) {
log.Eventf(ctx, "addressing error: %s does not include key %s", ri.desc, ri.key)
if err := ri.token.Evict(ctx); err != nil {
ri.pErr = roachpb.NewError(err)
return
}
// On addressing errors, don't backoff; retry immediately.
r.Reset()
continue
}
return
}
// Check for an early exit from the retry loop.
if pErr := ri.ds.deduceRetryEarlyExitError(ctx); pErr != nil {
ri.pErr = pErr
} else {
ri.pErr = roachpb.NewErrorf("RangeIterator failed to seek to %s", key)
}
}
开发者ID:veteranlu,项目名称:cockroach,代码行数:55,代码来源:range_iter.go
示例5: processReplica
// processReplica processes a single replica. This should not be
// called externally to the queue. bq.mu.Lock must not be held
// while calling this method.
func (bq *baseQueue) processReplica(
queueCtx context.Context, repl *Replica, clock *hlc.Clock,
) error {
bq.processMu.Lock()
defer bq.processMu.Unlock()
// Load the system config.
cfg, ok := bq.gossip.GetSystemConfig()
if !ok {
log.VEventf(queueCtx, 1, "no system config available, skipping")
return nil
}
if bq.requiresSplit(cfg, repl) {
// Range needs to be split due to zone configs, but queue does
// not accept unsplit ranges.
log.VEventf(queueCtx, 3, "split needed; skipping")
return nil
}
// Putting a span in a context means that events will no longer go to the
// event log. Use queueCtx for events that are intended for the event log.
ctx, span := bq.AnnotateCtxWithSpan(queueCtx, bq.name)
defer span.Finish()
// Also add the Replica annotations to ctx.
ctx = repl.AnnotateCtx(ctx)
ctx, cancel := context.WithTimeout(ctx, bq.processTimeout)
defer cancel()
log.Eventf(ctx, "processing replica")
if err := repl.IsDestroyed(); err != nil {
log.VEventf(queueCtx, 3, "replica destroyed (%s); skipping", err)
return nil
}
// If the queue requires a replica to have the range lease in
// order to be processed, check whether this replica has range lease
// and renew or acquire if necessary.
if bq.needsLease {
// Create a "fake" get request in order to invoke redirectOnOrAcquireLease.
if err := repl.redirectOnOrAcquireLease(ctx); err != nil {
switch v := err.GetDetail().(type) {
case *roachpb.NotLeaseHolderError, *roachpb.RangeNotFoundError:
log.VEventf(queueCtx, 3, "%s; skipping", v)
return nil
default:
return errors.Wrapf(err.GoError(), "%s: could not obtain lease", repl)
}
}
log.Event(ctx, "got range lease")
}
log.VEventf(queueCtx, 3, "processing")
if err := bq.impl.process(ctx, clock.Now(), repl, cfg); err != nil {
return err
}
log.Event(ctx, "done")
bq.successes.Inc(1)
return nil
}
开发者ID:jmptrader,项目名称:cockroach,代码行数:63,代码来源:queue.go
示例6: GetSnapshot
// GetSnapshot wraps Snapshot() but does not require the replica lock
// to be held and it will block instead of returning
// ErrSnapshotTemporaryUnavailable. The caller is directly responsible for
// calling r.CloseOutSnap.
func (r *Replica) GetSnapshot(ctx context.Context, snapType string) (*OutgoingSnapshot, error) {
// Use shorter-than-usual backoffs because this rarely succeeds on
// the first attempt and this method is used a lot in tests.
// Unsuccessful attempts are cheap, so we can have a low MaxBackoff.
retryOpts := retry.Options{
InitialBackoff: 1 * time.Millisecond,
MaxBackoff: 100 * time.Millisecond,
Multiplier: 2,
}
for retryObj := retry.StartWithCtx(ctx, retryOpts); retryObj.Next(); {
log.Eventf(ctx, "snapshot retry loop pass %d", retryObj.CurrentAttempt())
r.mu.Lock()
doneChan := r.mu.outSnapDone
r.mu.Unlock()
<-doneChan
r.mu.Lock()
snap, err := r.snapshotWithContext(ctx, snapType)
if err == nil {
r.mu.outSnap.claimed = true
}
r.mu.Unlock()
if err == raft.ErrSnapshotTemporarilyUnavailable {
continue
} else {
return snap, err
}
}
return nil, ctx.Err() // the only loop exit condition
}
开发者ID:jmptrader,项目名称:cockroach,代码行数:36,代码来源:replica_raftstorage.go
示例7: maybeAddBootstrapAddress
// maybeAddBootstrapAddress adds the specified address to the list of
// bootstrap addresses if not already present. Returns whether a new
// bootstrap address was added. The caller must hold the gossip mutex.
func (g *Gossip) maybeAddBootstrapAddress(addr util.UnresolvedAddr) bool {
if _, ok := g.bootstrapAddrs[addr]; ok {
return false
}
g.bootstrapInfo.Addresses = append(g.bootstrapInfo.Addresses, addr)
g.bootstrapAddrs[addr] = struct{}{}
ctx := g.AnnotateCtx(context.TODO())
log.Eventf(ctx, "add bootstrap %s", addr)
return true
}
开发者ID:knz,项目名称:cockroach,代码行数:13,代码来源:gossip.go
示例8: manage
// manage manages outgoing clients. Periodically, the infostore is
// scanned for infos with hop count exceeding the MaxHops
// threshold. If the number of outgoing clients doesn't exceed
// maxPeers(), a new gossip client is connected to a randomly selected
// peer beyond MaxHops threshold. Otherwise, the least useful peer
// node is cut off to make room for a replacement. Disconnected
// clients are processed via the disconnected channel and taken out of
// the outgoing address set. If there are no longer any outgoing
// connections or the sentinel gossip is unavailable, the bootstrapper
// is notified via the stalled conditional variable.
func (g *Gossip) manage() {
g.server.stopper.RunWorker(func() {
ctx := g.AnnotateCtx(context.Background())
cullTicker := time.NewTicker(g.jitteredInterval(g.cullInterval))
stallTicker := time.NewTicker(g.jitteredInterval(g.stallInterval))
defer cullTicker.Stop()
defer stallTicker.Stop()
for {
select {
case <-g.server.stopper.ShouldStop():
return
case c := <-g.disconnected:
g.doDisconnected(c)
case nodeID := <-g.tighten:
g.tightenNetwork(nodeID)
case <-cullTicker.C:
func() {
g.mu.Lock()
if !g.outgoing.hasSpace() {
leastUsefulID := g.mu.is.leastUseful(g.outgoing)
if c := g.findClient(func(c *client) bool {
return c.peerID == leastUsefulID
}); c != nil {
if log.V(1) {
log.Infof(ctx, "closing least useful client %+v to tighten network graph", c)
}
log.Eventf(ctx, "culling %s", c.addr)
c.close()
// After releasing the lock, block until the client disconnects.
defer func() {
g.doDisconnected(<-g.disconnected)
}()
} else {
if log.V(1) {
g.clientsMu.Lock()
log.Infof(ctx, "couldn't find least useful client among %+v", g.clientsMu.clients)
g.clientsMu.Unlock()
}
}
}
g.mu.Unlock()
}()
case <-stallTicker.C:
g.mu.Lock()
g.maybeSignalStatusChangeLocked()
g.mu.Unlock()
}
}
})
}
开发者ID:knz,项目名称:cockroach,代码行数:62,代码来源:gossip.go
示例9: maybeAddBootstrapAddress
// maybeAddBootstrapAddress adds the specified address to the list of
// bootstrap addresses if not already present. Returns whether a new
// bootstrap address was added. The caller must hold the gossip mutex.
func (g *Gossip) maybeAddBootstrapAddress(addr util.UnresolvedAddr, nodeID roachpb.NodeID) bool {
if existingNodeID, ok := g.bootstrapAddrs[addr]; ok {
if existingNodeID == unknownNodeID || existingNodeID != nodeID {
g.bootstrapAddrs[addr] = nodeID
}
return false
}
g.bootstrapInfo.Addresses = append(g.bootstrapInfo.Addresses, addr)
g.bootstrapAddrs[addr] = nodeID
ctx := g.AnnotateCtx(context.TODO())
log.Eventf(ctx, "add bootstrap %s", addr)
return true
}
开发者ID:bdarnell,项目名称:cockroach,代码行数:16,代码来源:gossip.go
示例10: removeClient
// removeClient removes the specified client. Called when a client
// disconnects.
func (g *Gossip) removeClient(target *client) {
g.clientsMu.Lock()
defer g.clientsMu.Unlock()
for i, candidate := range g.clientsMu.clients {
if candidate == target {
ctx := g.AnnotateCtx(context.TODO())
log.Eventf(ctx, "client %s disconnected", candidate.addr)
g.clientsMu.clients = append(g.clientsMu.clients[:i], g.clientsMu.clients[i+1:]...)
delete(g.bootstrapping, candidate.addr.String())
g.outgoing.removeNode(candidate.peerID)
break
}
}
}
开发者ID:knz,项目名称:cockroach,代码行数:16,代码来源:gossip.go
示例11: startClient
// startClient launches a new client connected to remote address.
// The client is added to the outgoing address set and launched in
// a goroutine.
func (g *Gossip) startClient(addr net.Addr, nodeID roachpb.NodeID) {
g.clientsMu.Lock()
defer g.clientsMu.Unlock()
breaker, ok := g.clientsMu.breakers[addr.String()]
if !ok {
breaker = g.rpcContext.NewBreaker()
g.clientsMu.breakers[addr.String()] = breaker
}
ctx := g.AnnotateCtx(context.TODO())
log.Eventf(ctx, "starting new client to %s", addr)
c := newClient(g.server.AmbientContext, addr, g.serverMetrics)
g.clientsMu.clients = append(g.clientsMu.clients, c)
c.start(g, g.disconnected, g.rpcContext, g.server.stopper, nodeID, breaker)
}
开发者ID:knz,项目名称:cockroach,代码行数:17,代码来源:gossip.go
示例12: tightenNetwork
// tightenNetwork "tightens" the network by starting a new gossip
// client to the most distant node as measured in required gossip hops
// to propagate info from the distant node to this node.
func (g *Gossip) tightenNetwork(distantNodeID roachpb.NodeID) {
g.mu.Lock()
defer g.mu.Unlock()
if g.outgoing.hasSpace() {
ctx := g.AnnotateCtx(context.TODO())
if nodeAddr, err := g.getNodeIDAddressLocked(distantNodeID); err != nil {
log.Errorf(ctx, "unable to get address for node %d: %s", distantNodeID, err)
} else {
log.Infof(ctx, "starting client to distant node %d to tighten network graph", distantNodeID)
log.Eventf(ctx, "tightening network with new client to %s", nodeAddr)
g.startClient(nodeAddr, g.NodeID.Get())
}
}
}
开发者ID:knz,项目名称:cockroach,代码行数:17,代码来源:gossip.go
示例13: maybeAddResolver
// maybeAddResolver creates and adds a resolver for the specified
// address if one does not already exist. Returns whether a new
// resolver was added. The caller must hold the gossip mutex.
func (g *Gossip) maybeAddResolver(addr util.UnresolvedAddr) bool {
if _, ok := g.resolverAddrs[addr]; ok {
return false
}
ctx := g.AnnotateCtx(context.TODO())
r, err := resolver.NewResolverFromUnresolvedAddr(addr)
if err != nil {
log.Warningf(ctx, "bad address %s: %s", addr, err)
return false
}
g.resolvers = append(g.resolvers, r)
g.resolverAddrs[addr] = r
log.Eventf(ctx, "add resolver %s", r)
return true
}
开发者ID:knz,项目名称:cockroach,代码行数:18,代码来源:gossip.go
示例14: snapshotWithContext
// snapshotWithContext is the main implementation for Snapshot() but it takes
// a context to allow tracing. If this method returns without error, callers
// must eventually call CloseOutSnap to ready this replica for more snapshots.
// r.mu must be held.
func (r *Replica) snapshotWithContext(
ctx context.Context, snapType string,
) (*OutgoingSnapshot, error) {
r.mu.AssertHeld()
rangeID := r.RangeID
if r.exceedsDoubleSplitSizeLocked() {
maxBytes := r.mu.maxBytes
size := r.mu.state.Stats.Total()
log.Infof(ctx,
"not generating %s snapshot because replica is too large: %d > 2 * %d",
snapType, size, maxBytes)
return &OutgoingSnapshot{}, raft.ErrSnapshotTemporarilyUnavailable
}
// See if there is already a snapshot running for this store.
select {
case <-r.mu.outSnapDone:
default:
log.Event(ctx, "snapshot already running")
return nil, raft.ErrSnapshotTemporarilyUnavailable
}
if !r.store.AcquireRaftSnapshot() {
log.Event(ctx, "snapshot already running")
return nil, raft.ErrSnapshotTemporarilyUnavailable
}
startKey := r.mu.state.Desc.StartKey
ctx, sp := r.AnnotateCtxWithSpan(ctx, "snapshot")
defer sp.Finish()
snap := r.store.NewSnapshot()
log.Eventf(ctx, "new engine snapshot for replica %s", r)
// Delegate to a static function to make sure that we do not depend
// on any indirect calls to r.store.Engine() (or other in-memory
// state of the Replica). Everything must come from the snapshot.
snapData, err := snapshot(ctx, snapType, snap, rangeID, r.store.raftEntryCache, startKey)
if err != nil {
log.Errorf(ctx, "error generating snapshot: %s", err)
return nil, err
}
log.Event(ctx, "snapshot generated")
r.store.metrics.RangeSnapshotsGenerated.Inc(1)
r.mu.outSnap = snapData
r.mu.outSnapDone = make(chan struct{})
return &r.mu.outSnap, nil
}
开发者ID:jmptrader,项目名称:cockroach,代码行数:51,代码来源:replica_raftstorage.go
示例15: EvictAndReplace
// EvictAndReplace instructs the EvictionToken to evict the RangeDescriptor it was
// created with from the rangeDescriptorCache. It also allows the user to provide
// new RangeDescriptors to insert into the cache, all atomically. When called without
// arguments, EvictAndReplace will behave the same as Evict.
func (et *EvictionToken) EvictAndReplace(
ctx context.Context, newDescs ...roachpb.RangeDescriptor,
) error {
var err error
et.doOnce.Do(func() {
et.doLocker.Lock()
defer et.doLocker.Unlock()
err = et.do()
if err == nil {
if len(newDescs) > 0 {
err = et.doReplace(newDescs...)
log.Eventf(ctx, "evicting cached range descriptor with %d replacements", len(newDescs))
} else {
log.Event(ctx, "evicting cached range descriptor")
}
}
})
return err
}
开发者ID:knz,项目名称:cockroach,代码行数:23,代码来源:range_cache.go
示例16: GetSnapshot
// GetSnapshot wraps Snapshot() but does not require the replica lock
// to be held and it will block instead of returning
// ErrSnapshotTemporaryUnavailable. The caller is directly responsible for
// calling r.CloseOutSnap.
func (r *Replica) GetSnapshot(ctx context.Context) (*OutgoingSnapshot, error) {
for i := 0; ; i++ {
log.Eventf(ctx, "snapshot retry loop pass %d", i)
r.mu.Lock()
doneChan := r.mu.outSnapDone
r.mu.Unlock()
<-doneChan
r.mu.Lock()
snap, err := r.SnapshotWithContext(ctx)
if err == nil {
r.mu.outSnap.claimed = true
}
r.mu.Unlock()
if err == raft.ErrSnapshotTemporarilyUnavailable {
continue
} else {
return snap, err
}
}
}
开发者ID:bdarnell,项目名称:cockroach,代码行数:27,代码来源:replica_raftstorage.go
示例17: 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.
func (txn *Txn) Exec(opt TxnExecOptions, fn func(txn *Txn, opt *TxnExecOptions) error) (err error) {
// Run fn in a retry loop until we encounter a success or
// error condition this loop isn't capable of handling.
var retryOptions retry.Options
if txn == nil && (opt.AutoRetry || opt.AutoCommit) {
panic("asked to retry or commit a txn that is already aborted")
}
// Ensure that a RetryableTxnError escaping this function is not used by
// another (higher-level) Exec() invocation to restart its unrelated
// transaction. Technically, setting TxnID to nil here is best-effort and
// doesn't ensure that (the error will be wrongly used if the outer txn also
// has a nil TxnID).
// TODO(andrei): set TxnID to a bogus non-nil value once we get rid of the
// retErr.Transaction field.
defer func() {
if retErr, ok := err.(*roachpb.RetryableTxnError); ok {
retErr.TxnID = nil
retErr.Transaction = nil
}
}()
if opt.AutoRetry {
retryOptions = txn.db.ctx.TxnRetryOptions
}
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 opt.Clock != nil && !txn.Proto.IsInitialized() {
// Control the KV timestamp, such that the value returned by
// `cluster_logical_timestamp()` is consistent with the commit
// (serializable) ordering.
txn.Proto.OrigTimestamp = opt.Clock.Now()
}
}
err = fn(txn, &opt)
// TODO(andrei): Until 7881 is fixed.
if err == nil && opt.AutoCommit && txn.Proto.Status == roachpb.ABORTED {
log.Errorf(txn.Context, "#7881: no err but aborted txn proto. opt: %+v, txn: %+v",
opt, txn)
}
if err == nil && opt.AutoCommit && txn.Proto.Status == roachpb.PENDING {
// fn succeeded, but didn't commit.
err = txn.Commit()
log.Eventf(txn.Context, "client.Txn did AutoCommit. err: %v\ntxn: %+v", err, txn.Proto)
if err != nil {
if _, retryable := err.(*roachpb.RetryableTxnError); !retryable {
// We can't retry, so let the caller know we tried to
// autocommit.
err = &AutoCommitError{cause: err}
}
}
}
if !opt.AutoRetry {
break
}
if retErr, retryable := err.(*roachpb.RetryableTxnError); !retryable {
break
} else {
// Make sure the txn record that err carries is for this txn.
// If it's not, we terminate the "retryable" character of the error.
if txn.Proto.ID != nil && (retErr.TxnID == nil || *retErr.TxnID != *txn.Proto.ID) {
return errors.New(retErr.Error())
}
if !retErr.Backoff {
r.Reset()
}
}
txn.commitTriggers = nil
log.VEventf(txn.Context, 2, "automatically retrying transaction: %s because of error: %s",
txn.DebugName(), err)
}
return err
//.........这里部分代码省略.........
开发者ID:veteranlu,项目名称:cockroach,代码行数:101,代码来源:txn.go
示例18: execStmtInOpenTxn
// execStmtInOpenTxn executes one statement in the context
// of the planner's transaction (which is assumed to exist).
// It handles statements that affect the transaction state (BEGIN, COMMIT)
// and delegates everything else to `execStmt`.
// It binds placeholders.
//
// The current transaction might be committed/rolled back when this returns.
// It might also have transitioned to the aborted or RestartWait state.
//
// Args:
// implicitTxn: set if the current transaction was implicitly
// created by the system (i.e. the client sent the statement outside of
// a transaction).
// COMMIT/ROLLBACK statements are rejected if set. Also, the transaction
// might be auto-committed in this function.
// firstInTxn: set for the first statement in a transaction. Used
// so that nested BEGIN statements are caught.
// stmtTimestamp: Used as the statement_timestamp().
//
// Returns:
// - a Result
// - an error, if any. In case of error, the result returned also reflects this error.
func (e *Executor) execStmtInOpenTxn(
stmt parser.Statement, planMaker *planner, implicitTxn bool, firstInTxn bool, txnState *txnState,
) (Result, error) {
if txnState.State != Open {
panic("execStmtInOpenTxn called outside of an open txn")
}
if planMaker.txn == nil {
panic("execStmtInOpenTxn called with a txn not set on the planner")
}
planMaker.evalCtx.SetTxnTimestamp(txnState.sqlTimestamp)
planMaker.evalCtx.SetStmtTimestamp(e.cfg.Clock.PhysicalTime())
session := planMaker.session
log.Eventf(session.context, "%s", stmt)
// TODO(cdo): Figure out how to not double count on retries.
e.updateStmtCounts(stmt)
switch s := stmt.(type) {
case *parser.BeginTransaction:
if !firstInTxn {
txnState.updateStateAndCleanupOnErr(errTransactionInProgress, e)
return Result{Err: errTransactionInProgress}, errTransactionInProgress
}
case *parser.CommitTransaction:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
// CommitTransaction is executed fully here; there's no planNode for it
// and the planner is not involved at all.
res, err := commitSQLTransaction(txnState, planMaker, commit, e)
return res, err
case *parser.ReleaseSavepoint:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
if err := parser.ValidateRestartCheckpoint(s.Savepoint); err != nil {
return Result{Err: err}, err
}
// ReleaseSavepoint is executed fully here; there's no planNode for it
// and the planner is not involved at all.
res, err := commitSQLTransaction(txnState, planMaker, release, e)
return res, err
case *parser.RollbackTransaction:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
// RollbackTransaction is executed fully here; there's no planNode for it
// and the planner is not involved at all.
// Notice that we don't return any errors on rollback.
return rollbackSQLTransaction(txnState, planMaker), nil
case *parser.SetTransaction:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
case *parser.Savepoint:
if implicitTxn {
return e.noTransactionHelper(txnState)
}
if err := parser.ValidateRestartCheckpoint(s.Name); err != nil {
return Result{Err: err}, err
}
// We want to disallow SAVEPOINTs to be issued after a transaction has
// started running, but such enforcement is problematic in the
// presence of transaction retries (since the transaction proto is
// necessarily reused). To work around this, we keep track of the
// transaction's retrying state and special-case SAVEPOINT when it is
// set.
//
// TODO(andrei): the check for retrying is a hack - we erroneously
// allow SAVEPOINT to be issued at any time during a retry, not just
// in the beginning. We should figure out how to track whether we
// started using the transaction during a retry.
if txnState.txn.Proto.IsInitialized() && !txnState.retrying {
err := fmt.Errorf("SAVEPOINT %s needs to be the first statement in a transaction",
parser.RestartSavepointName)
txnState.updateStateAndCleanupOnErr(err, e)
return Result{Err: err}, err
//.........这里部分代码省略.........
开发者ID:hvaara,项目名称:cockroach,代码行数:101,代码来源:executor.go
示例19: execRequest
// execRequest executes the request using the provided planner.
// It parses the sql into statements, iterates through the statements, creates
// KV transactions and automatically retries them when possible, and executes
// the (synchronous attempt of) schema changes.
// It will accumulate a result in Response for each statement.
// It will resume a SQL transaction, if one was previously open for this client.
//
// execRequest handles the mismatch between the SQL interface that the Executor
// provides, based on statements being streamed from the client in the context
// of a session, and the KV client.Txn interface, based on (possibly-retriable)
// callbacks passed to be executed in the context of a transaction. Actual
// execution of statements in the context of a KV txn is delegated to
// runTxnAttempt().
//
// Args:
// txnState: State about about ongoing transaction (if any). The state will be
// updated.
func (e *Executor) execRequest(session *Session, sql string, copymsg copyMsg) StatementResults {
var res StatementResults
txnState := &session.TxnState
planMaker := &session.planner
var stmts parser.StatementList
var err error
log.VEventf(session.Ctx(), 2, "execRequest: %s", sql)
if session.planner.copyFrom != nil {
stmts, err = session.planner.ProcessCopyData(sql, copymsg)
} else if copymsg != copyMsgNone {
err = fmt.Errorf("unexpected copy command")
} else {
stmts, err = planMaker.parser.Parse(sql, parser.Syntax(session.Syntax))
}
if err != nil {
// A parse error occurred: we can't determine if there were multiple
// statements or only one, so just pretend there was one.
if txnState.txn != nil {
// Rollback the txn.
txnState.updateStateAndCleanupOnErr(err, e)
}
res.ResultList = append(res.ResultList, Result{Err: err})
return res
}
if len(stmts) == 0 {
res.Empty = true
return res
}
// If the planMaker wants config updates to be blocked, then block them.
defer planMaker.blockConfigUpdatesMaybe(e)()
for len(stmts) > 0 {
// Each iteration consumes a transaction's worth of statements.
inTxn := txnState.State != NoTxn
execOpt := client.TxnExecOptions{
Clock: e.cfg.Clock,
}
// Figure out the statements out of which we're going to try to consume
// this iteration. If we need to create an implicit txn, only one statement
// can be consumed.
stmtsToExec := stmts
// If protoTS is set, the transaction proto sets its Orig and Max timestamps
// to it each retry.
var protoTS *hlc.Timestamp
// We can AutoRetry the next batch of statements if we're in a clean state
// (i.e. the next statements we're going to see are the first statements in
// a transaction).
if !inTxn {
// Detect implicit transactions.
if _, isBegin := stmts[0].(*parser.BeginTransaction); !isBegin {
execOpt.AutoCommit = true
stmtsToExec = stmtsToExec[:1]
// Check for AS OF SYSTEM TIME. If it is present but not detected here,
// it will raise an error later on.
protoTS, err = isAsOf(planMaker, stmtsToExec[0], e.cfg.Clock.Now())
if err != nil {
res.ResultList = append(res.ResultList, Result{Err: err})
return res
}
if protoTS != nil {
planMaker.avoidCachedDescriptors = true
defer func() {
planMaker.avoidCachedDescriptors = false
}()
}
}
txnState.resetForNewSQLTxn(e, session)
txnState.autoRetry = true
txnState.sqlTimestamp = e.cfg.Clock.PhysicalTime()
if execOpt.AutoCommit {
txnState.txn.SetDebugName(sqlImplicitTxnName, 0)
} else {
txnState.txn.SetDebugName(sqlTxnName, 0)
}
} else {
txnState.autoRetry = false
}
execOpt.AutoRetry = txnState.autoRetry
if txnState.State == NoTxn {
//.........这里部分代码省略.........
开发者ID:hvaara,项目名称:cockroach,代码行数:101,代码来源:executor.go
示例20: resolveIntents
// resolveIntents resolves the given intents. `wait` is currently a
// no-op; all intents are resolved synchronously.
//
// TODO(bdarnell): Restore the wait=false optimization when/if #8360
// is fixed. `wait=false` requests a semi-synchronous operation,
// returning when all local commands have been *proposed* but not yet
// committed or executed. This ensures that if a waiting client
// retries immediately after calling this function, it will not hit
// the same intents again (in the absence of #8360, we provide this
// guarantee by resolving the intents synchronously regardless of the
// `wait` argument).
func (ir *intentResolver) resolveIntents(
ctx context.Context, intents []roachpb.Intent, wait bool, poison bool,
) error {
// Force synchronous operation; see above TODO.
wait = true
if len(intents) == 0 {
return nil
}
// We're doing async stuff below; those need new traces.
ctx, cleanup := tracing.EnsureContext(ctx, ir.store.Tracer())
defer cleanup()
log.Eventf(ctx, "resolving intents [wait=%t]", wait)
var reqs []roachpb.Request
for i := range intents {
intent := intents[i] // avoids a race in `i, intent := range ...`
var resolveArgs roachpb.Request
{
if len(intent.EndKey) == 0 {
resolveArgs = &roachpb.ResolveIntentRequest{
Span: intent.Span,
IntentTxn: intent.Txn,
Status: intent.Status,
Poison: poison,
}
} else {
resolveArgs = &roachpb.ResolveIntentRangeRequest{
Span: intent.Span,
IntentTxn: intent.Txn,
Status: intent.Status,
Poison: poison,
}
}
}
reqs = append(reqs, resolveArgs)
}
// Resolve all of the intents.
if len(reqs) > 0 {
b := &client.Batch{}
b.AddRawRequest(reqs...)
action := func() error {
// TODO(tschottdorf): no tracing here yet.
return ir.store.DB().Run(ctx, b)
}
if wait || ir.store.Stopper().RunLimitedAsyncTask(
ctx, ir.sem, true /* wait */, func(ctx context.Context) {
if err := action(); err != nil {
log.Warningf(ctx, "unable to resolve external intents: %s", err)
}
}) != nil {
// Try async to not keep the caller waiting, but when draining
// just go ahead and do it synchronously. See #1684.
// TODO(tschottdorf): This is ripe for removal.
if err := action(); err != nil {
return err
}
}
}
return nil
}
开发者ID:veteranlu,项目名称:cockroach,代码行数:74,代码来源:intent_resolver.go
注:本文中的github.com/cockroachdb/cockroach/pkg/util/log.Eventf函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论