// Indirectly this tests that the transaction remembers the NodeID of the node // being read from correctly, at least in this simple case. Not remembering the // node would lead to thousands of transaction restarts and almost certainly a // test timeout. func TestUncertaintyRestarts(t *testing.T) { defer leaktest.AfterTest(t) s := createTestDB(t) disableOwnNodeCertain(s) defer s.Stop() // Set a large offset so that a busy restart-loop // really shows. Also makes sure that the values // we write in the future below don't actually // wind up in the past. offset := 4000 * time.Millisecond s.Clock.SetMaxOffset(offset) key := roachpb.Key("key") value := roachpb.Value{} // With the correct restart behaviour, we see only one restart // and the value read is the very first one (as nothing else // has been written) wantedBytes := []byte("value-0") i := -1 tErr := s.DB.Txn(func(txn *client.Txn) *roachpb.Error { i++ s.Manual.Increment(1) futureTS := s.Clock.Now() futureTS.WallTime++ value.SetBytes([]byte(fmt.Sprintf("value-%d", i))) if err := engine.MVCCPut(s.Eng, nil, key, futureTS, value, nil); err != nil { t.Fatal(err) } gr, pErr := txn.Get(key) if pErr != nil { return pErr } if !gr.Exists() || !bytes.Equal(gr.ValueBytes(), wantedBytes) { t.Fatalf("%d: read wrong value: %v, wanted %q", i, gr.Value, wantedBytes) } return nil }) if i != 1 { t.Errorf("txn restarted %d times, expected only one restart", i) } if tErr != nil { t.Fatal(tErr) } }
// marshalValue returns a roachpb.Value initialized from the source // interface{}, returning an error if the types are not compatible. func marshalValue(v interface{}) (roachpb.Value, error) { var r roachpb.Value // Handle a few common types via a type switch. switch t := v.(type) { case *roachpb.Value: return *t, nil case nil: return r, nil case bool: i := int64(0) if t { i = 1 } r.SetInt(i) return r, nil case string: r.SetBytes([]byte(t)) return r, nil case []byte: r.SetBytes(t) return r, nil case inf.Dec: err := r.SetDecimal(&t) return r, err case roachpb.Key: r.SetBytes([]byte(t)) return r, nil case time.Time: r.SetTime(t) return r, nil case duration.Duration: err := r.SetDuration(t) return r, err case proto.Message: err := r.SetProto(t) return r, err } // Handle all of the Go primitive types besides struct and pointers. This // switch also handles types based on a primitive type (e.g. "type MyInt // int"). switch v := reflect.ValueOf(v); v.Kind() { case reflect.Bool: i := int64(0) if v.Bool() { i = 1 } r.SetInt(i) return r, nil case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: r.SetInt(v.Int()) return r, nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: r.SetInt(int64(v.Uint())) return r, nil case reflect.Float32, reflect.Float64: r.SetFloat(v.Float()) return r, nil case reflect.String: r.SetBytes([]byte(v.String())) return r, nil } return r, fmt.Errorf("unable to marshal %T: %v", v, v) }