// checkResource determines whether a specific resource needs to be over-written. func checkResource(threshold int64, actual, expected api.ResourceList, res api.ResourceName) bool { val, ok := actual[res] expVal, expOk := expected[res] if ok != expOk { return true } if !ok && !expOk { return false } q := new(inf.Dec).QuoRound(val.AsDec(), expVal.AsDec(), 2, inf.RoundDown) lower := inf.NewDec(100-threshold, 2) upper := inf.NewDec(100+threshold, 2) if q.Cmp(lower) == -1 || q.Cmp(upper) == 1 { return true } return false }
func TestSemantic(t *testing.T) { table := []struct { a, b interface{} shouldEqual bool }{ {resource.MustParse("0"), resource.Quantity{}, true}, {resource.Quantity{}, resource.MustParse("0"), true}, {resource.Quantity{}, resource.MustParse("1m"), false}, { resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.BinarySI}, resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.DecimalSI}, true, }, {resource.MustParse("2m"), resource.MustParse("1m"), false}, } for index, item := range table { if e, a := item.shouldEqual, Semantic.DeepEqual(item.a, item.b); e != a { t.Errorf("case[%d], expected %v, got %v.", index, e, a) } } }
func dec(i int64, exponent int) *inf.Dec { // See the below test-- scale is the negative of an exponent. return inf.NewDec(i, inf.Scale(-exponent)) }
func dec(i int64, exponent int) *inf.Dec { return inf.NewDec(i, inf.Scale(-exponent)) }
const ( // maxInt64Factors is the highest value that will be checked when removing factors of 10 from an int64. // It is also the maximum decimal digits that can be represented with an int64. maxInt64Factors = 18 ) var ( // Commonly needed big.Int values-- treat as read only! bigTen = big.NewInt(10) bigZero = big.NewInt(0) bigOne = big.NewInt(1) bigThousand = big.NewInt(1000) big1024 = big.NewInt(1024) // Commonly needed inf.Dec values-- treat as read only! decZero = inf.NewDec(0, 0) decOne = inf.NewDec(1, 0) decMinusOne = inf.NewDec(-1, 0) decThousand = inf.NewDec(1000, 0) dec1024 = inf.NewDec(1024, 0) decMinus1024 = inf.NewDec(-1024, 0) // Largest (in magnitude) number allowed. maxAllowed = infDecAmount{inf.NewDec((1<<63)-1, 0)} // == max int64 // The maximum value we can represent milli-units for. // Compare with the return value of Quantity.Value() to // see if it's safe to use Quantity.MilliValue(). MaxMilliValue = int64(((1 << 63) - 1) / 1000) )
func amount(i int64, exponent int) infDecAmount { // See the below test-- scale is the negative of an exponent. return infDecAmount{inf.NewDec(i, inf.Scale(-exponent))} }
// Test that a TransactionRetryError will retry the read until it succeeds. The // test is designed so that if the proto timestamps are bumped during retry // a failure will occur. func TestAsOfRetry(t *testing.T) { defer leaktest.AfterTest(t)() params, cmdFilters := createTestServerParams() // Disable one phase commits because they cannot be restarted. params.Knobs.Store.(*storage.StoreTestingKnobs).DisableOnePhaseCommits = true s, sqlDB, _ := serverutils.StartServer(t, params) defer s.Stopper().Stop() const val1 = 1 const val2 = 2 const name = "boulanger" if _, err := sqlDB.Exec(` CREATE DATABASE d; CREATE TABLE d.t (s STRING PRIMARY KEY, a INT); `); err != nil { t.Fatal(err) } var tsStart string if err := sqlDB.QueryRow(` INSERT INTO d.t (s, a) VALUES ($1, $2) RETURNING cluster_logical_timestamp(); `, name, val1).Scan(&tsStart); err != nil { t.Fatal(err) } var tsVal2 string if err := sqlDB.QueryRow("UPDATE d.t SET a = $1 RETURNING cluster_logical_timestamp()", val2).Scan(&tsVal2); err != nil { t.Fatal(err) } walltime := new(inf.Dec) if _, ok := walltime.SetString(tsVal2); !ok { t.Fatalf("couldn't set decimal: %s", tsVal2) } oneTick := inf.NewDec(1, 0) // Set tsVal1 to 1ns before tsVal2. tsVal1 := walltime.Sub(walltime, oneTick).String() // Set up error injection that causes retries. magicVals := createFilterVals(nil, nil) magicVals.restartCounts = map[string]int{ name: 5, } cleanupFilter := cmdFilters.AppendFilter( func(args storagebase.FilterArgs) *roachpb.Error { magicVals.Lock() defer magicVals.Unlock() switch req := args.Req.(type) { case *roachpb.ScanRequest: for key, count := range magicVals.restartCounts { if err := checkCorrectTxn(string(req.Key), magicVals, args.Hdr.Txn); err != nil { return roachpb.NewError(err) } if count > 0 && bytes.Contains(req.Key, []byte(key)) { magicVals.restartCounts[key]-- err := roachpb.NewTransactionRetryError() magicVals.failedValues[string(req.Key)] = failureRecord{err, args.Hdr.Txn} txn := args.Hdr.Txn.Clone() txn.Timestamp = txn.Timestamp.Add(0, 1) return roachpb.NewErrorWithTxn(err, &txn) } } } return nil }, false) var i int // Query with tsVal1 which should return the first value. Since tsVal1 is just // one nanosecond before tsVal2, any proto timestamp bumping will return val2 // and error. // Must specify the WHERE here to trigger the injection errors. if err := sqlDB.QueryRow(fmt.Sprintf("SELECT a FROM d.t AS OF SYSTEM TIME %s WHERE s = '%s'", tsVal1, name)).Scan(&i); err != nil { t.Fatal(err) } else if i != val1 { t.Fatalf("unexpected val: %v", i) } cleanupFilter() // Verify that the retry errors were injected. checkRestarts(t, magicVals) // Query with tsVal2 to ensure val2 is indeed present. if err := sqlDB.QueryRow(fmt.Sprintf("SELECT a FROM d.t AS OF SYSTEM TIME %s", tsVal2)).Scan(&i); err != nil { t.Fatal(err) } else if i != val2 { t.Fatalf("unexpected val: %v", i) } }
// CmpInt64 returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the // quantity is greater than y. func (q *Quantity) CmpInt64(y int64) int { if q.d.Dec != nil { return q.d.Dec.Cmp(inf.NewDec(y, inf.Scale(0))) } return q.i.Cmp(int64Amount{value: y}) }
// NewScaledQuantity returns a new Quantity representing the given // value * 10^scale in DecimalSI format. func NewScaledQuantity(value int64, scale Scale) *Quantity { return &Quantity{ Amount: inf.NewDec(value, scale.infScale()), Format: DecimalSI, } }
// NewMilliQuantity returns a new Quantity representing the given // value * 1/1000 in the given format. Note that BinarySI formatting // will round fractional values, and will be changed to DecimalSI for // values x where (-1 < x < 1) && (x != 0). func NewMilliQuantity(value int64, format Format) *Quantity { return &Quantity{ Amount: inf.NewDec(value, 3), Format: format, } }