func TestTransactionString(t *testing.T) { txnID, err := uuid.FromBytes([]byte("ת\x0f^\xe4-Fؽ\xf7\x16\xe4\xf9\xbe^\xbe")) if err != nil { t.Fatal(err) } ts1 := makeTS(10, 11) txn := Transaction{ TxnMeta: TxnMeta{ Isolation: SERIALIZABLE, Key: Key("foo"), ID: txnID, Epoch: 2, Timestamp: makeTS(20, 21), }, Name: "name", Priority: 957356782, Status: COMMITTED, LastHeartbeat: &ts1, OrigTimestamp: makeTS(30, 31), MaxTimestamp: makeTS(40, 41), } expStr := `"name" id=d7aa0f5e key="foo" rw=false pri=44.58039917 iso=SERIALIZABLE stat=COMMITTED ` + `epo=2 ts=0.000000020,21 orig=0.000000030,31 max=0.000000040,41` if str := txn.String(); str != expStr { t.Errorf("expected txn %s; got %s", expStr, str) } var txnEmpty Transaction _ = txnEmpty.String() // prevent regression of NPE }
func localRangeKeyPrint(key roachpb.Key) string { var buf bytes.Buffer for _, s := range rangeSuffixDict { if s.atEnd { if bytes.HasSuffix(key, s.suffix) { key = key[:len(key)-len(s.suffix)] fmt.Fprintf(&buf, "%s/%s", decodeKeyPrint(key), s.name) return buf.String() } } else { begin := bytes.Index(key, s.suffix) if begin > 0 { addrKey := key[:begin] txnID, err := uuid.FromBytes(key[(begin + len(s.suffix)):]) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } fmt.Fprintf(&buf, "%s/%s/addrKey:/id:%q", decodeKeyPrint(addrKey), s.name, txnID) return buf.String() } } } fmt.Fprintf(&buf, "%s", decodeKeyPrint(key)) return buf.String() }
func sequenceCacheKeyPrint(key roachpb.Key) string { b, id, err := encoding.DecodeBytesAscending([]byte(key), nil) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } txnID, err := uuid.FromBytes(id) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } if len(b) == 0 { return fmt.Sprintf("/%q", txnID) } b, epoch, err := encoding.DecodeUint32Descending(b) if err != nil { return fmt.Sprintf("/%q/err:%v", txnID, err) } _, seq, err := encoding.DecodeUint32Descending(b) if err != nil { return fmt.Sprintf("/%q/epoch:%d/err:%v", txnID, epoch, err) } return fmt.Sprintf("/%q/epoch:%d/seq:%d", txnID, epoch, seq) }
// DecodeAbortCacheKey decodes the provided abort cache entry, // returning the transaction ID. func DecodeAbortCacheKey(key roachpb.Key, dest []byte) (*uuid.UUID, error) { // TODO(tschottdorf): redundant check. if !bytes.HasPrefix(key, LocalRangeIDPrefix) { return nil, util.Errorf("key %s does not have %s prefix", key, LocalRangeIDPrefix) } // Cut the prefix, the Range ID, and the infix specifier. b := key[len(LocalRangeIDPrefix):] b, _, err := encoding.DecodeUvarintAscending(b) if err != nil { return nil, err } b = b[1:] if !bytes.HasPrefix(b, LocalAbortCacheSuffix) { return nil, util.Errorf("key %s does not contain the abort cache suffix %s", key, LocalAbortCacheSuffix) } // Cut the abort cache suffix. b = b[len(LocalAbortCacheSuffix):] // Decode the id. b, idBytes, err := encoding.DecodeBytesAscending(b, dest) if err != nil { return nil, err } if len(b) > 0 { return nil, util.Errorf("key %q has leftover bytes after decode: %s; indicates corrupt key", key, b) } txnID, err := uuid.FromBytes(idBytes) return txnID, err }
func abortCacheKeyPrint(key roachpb.Key) string { _, id, err := encoding.DecodeBytesAscending([]byte(key), nil) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } txnID, err := uuid.FromBytes(id) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } return fmt.Sprintf("/%q", txnID) }
// DecodeAbortCacheKey decodes the provided abort cache entry, // returning the transaction ID. func DecodeAbortCacheKey(key roachpb.Key, dest []byte) (*uuid.UUID, error) { _, _, suffix, detail, err := DecodeRangeIDKey(key) if err != nil { return nil, err } if !bytes.Equal(suffix, LocalAbortCacheSuffix) { return nil, errors.Errorf("key %s does not contain the abort cache suffix %s", key, LocalAbortCacheSuffix) } // Decode the id. detail, idBytes, err := encoding.DecodeBytesAscending(detail, dest) if err != nil { return nil, err } if len(detail) > 0 { return nil, errors.Errorf("key %q has leftover bytes after decode: %s; indicates corrupt key", key, detail) } txnID, err := uuid.FromBytes(idBytes) return txnID, err }
func decodeSequenceCacheKey(key roachpb.Key, dest []byte) (*uuid.UUID, uint32, uint32, error) { // TODO(tschottdorf): redundant check. if !bytes.HasPrefix(key, keys.LocalRangeIDPrefix) { return nil, 0, 0, util.Errorf("key %s does not have %s prefix", key, keys.LocalRangeIDPrefix) } // Cut the prefix and the Range ID. b := key[len(keys.LocalRangeIDPrefix):] b, _, err := encoding.DecodeUvarintAscending(b) if err != nil { return nil, 0, 0, err } if !bytes.HasPrefix(b, keys.LocalSequenceCacheSuffix) { return nil, 0, 0, util.Errorf("key %s does not contain the sequence cache suffix %s", key, keys.LocalSequenceCacheSuffix) } // Cut the sequence cache suffix. b = b[len(keys.LocalSequenceCacheSuffix):] // Decode the id. b, idBytes, err := encoding.DecodeBytesAscending(b, dest) if err != nil { return nil, 0, 0, err } // Decode the epoch. b, epoch, err := encoding.DecodeUint32Descending(b) if err != nil { return nil, 0, 0, err } // Decode the sequence number. b, seq, err := encoding.DecodeUint32Descending(b) if err != nil { return nil, 0, 0, err } if len(b) > 0 { return nil, 0, 0, util.Errorf("key %q has leftover bytes after decode: %s; indicates corrupt key", key, b) } txnID, err := uuid.FromBytes(idBytes) return txnID, epoch, seq, err }
func TestTransactionString(t *testing.T) { txnID, err := uuid.FromBytes([]byte("ת\x0f^\xe4-Fؽ\xf7\x16\xe4\xf9\xbe^\xbe")) if err != nil { t.Fatal(err) } ts1 := makeTS(10, 11) txn := Transaction{ TxnMeta: enginepb.TxnMeta{ Isolation: enginepb.SERIALIZABLE, Key: Key("foo"), ID: txnID, Epoch: 2, Timestamp: makeTS(20, 21), Priority: 957356782, }, Name: "name", Status: COMMITTED, LastHeartbeat: &ts1, OrigTimestamp: makeTS(30, 31), MaxTimestamp: makeTS(40, 41), } expStr := `"name" id=d7aa0f5e key="foo" rw=false pri=44.58039917 iso=SERIALIZABLE stat=COMMITTED ` + `epo=2 ts=0.000000020,21 orig=0.000000030,31 max=0.000000040,41 wto=false rop=false` if str := txn.String(); str != expStr { t.Errorf("expected txn %s; got %s", expStr, str) } var txnEmpty Transaction _ = txnEmpty.String() // prevent regression of NPE var cmd RaftCommand cmd.Cmd.Txn = &txn if actStr, idStr := fmt.Sprintf("%s", &cmd), txn.ID.String(); !strings.Contains(actStr, idStr) { t.Fatalf("expected to find '%s' in '%s'", idStr, actStr) } }
// connectGossip connects to gossip network and reads cluster ID. If // this node is already part of a cluster, the cluster ID is verified // for a match. If not part of a cluster, the cluster ID is set. The // node's address is gossiped with node ID as the gossip key. func (n *Node) connectGossip() { log.Infof("connecting to gossip network to verify cluster ID...") // No timeout or stop condition is needed here. Log statements should be // sufficient for diagnosing this type of condition. <-n.ctx.Gossip.Connected uuidBytes, err := n.ctx.Gossip.GetInfo(gossip.KeyClusterID) if err != nil { log.Fatalf("unable to ascertain cluster ID from gossip network: %s", err) } gossipClusterIDPtr, err := uuid.FromBytes(uuidBytes) if err != nil { log.Fatalf("unable to ascertain cluster ID from gossip network: %s", err) } gossipClusterID := *gossipClusterIDPtr if n.ClusterID == *uuid.EmptyUUID { n.ClusterID = gossipClusterID } else if n.ClusterID != gossipClusterID { log.Fatalf("node %d belongs to cluster %q but is attempting to connect to a gossip network for cluster %q", n.Descriptor.NodeID, n.ClusterID, gossipClusterID) } log.Infof("node connected via gossip and verified as part of cluster %q", gossipClusterID) }