diff --git a/meta_flags.go b/meta_flags.go index f5c7b81..b071243 100644 --- a/meta_flags.go +++ b/meta_flags.go @@ -13,11 +13,6 @@ func buildMetaFlags(fs []metaFlag) string { } func obtainMetaFlagsResults(ss []string) (mr MetaResult, err error) { - // Always set the cas token as setted - // enforce the operation use this token always use the CasToken.value - // even if the token is not returned. - // To avoid unexpected non-cas opertion caused by the lack of "c" flag. - mr.CasToken.setted = true for _, f := range ss { k, v := f[0], f[1:] switch k { @@ -32,7 +27,9 @@ func obtainMetaFlagsResults(ss []string) (mr MetaResult, err error) { case 'O': mr.Opaque = v case 'c': - mr.CasToken.value, err = strconv.ParseInt(v, 10, 64) + var cv int64 + cv, err = strconv.ParseInt(v, 10, 64) + mr.CasToken = casToken(cv) case 'f': v, err := strconv.ParseUint(v, 10, 32) if err != nil { diff --git a/meta_options.go b/meta_options.go index ffc9c2d..6ff3a05 100644 --- a/meta_options.go +++ b/meta_options.go @@ -1,8 +1,13 @@ package memcache -type casToken struct { - value int64 - setted bool +type CasToken interface { + value() int64 +} + +type casToken int64 + +func (c casToken) value() int64 { + return int64(c) } type MetaGetOptions struct { @@ -79,7 +84,7 @@ type MetaSetOptions struct { Key string // the key of item BinaryKey []byte // interpret key as base64 encoded binary value (see metaget) Value []byte // the value of item - CasToken casToken // compare and swap token + CasToken CasToken // compare and swap token GetCasToken bool // return CAS value if successfully stored. @@ -109,8 +114,8 @@ func (o MetaSetOptions) marshal() (fs []metaFlag) { if o.SetTTL != 0 { fs = append(fs, withSetTTL(o.SetTTL)) } - if o.CasToken.setted { - fs = append(fs, withCompareCAS(o.CasToken.value)) + if o.CasToken != nil { + fs = append(fs, withCompareCAS(o.CasToken.value())) } return } @@ -118,7 +123,7 @@ func (o MetaSetOptions) marshal() (fs []metaFlag) { type MetaDeletOptions struct { Key string // the key of item BinaryKey []byte // interpret key as base64 encoded binary value (see metaget) - CasToken casToken // compare and swap token + CasToken CasToken // compare and swap token SetTTL uint64 // updates TTL, only when paired with the SetInvalidate option SetInvalidate bool // mark as stale, bumps CAS. @@ -134,8 +139,8 @@ func (o MetaDeletOptions) marshal() (fs []metaFlag) { if o.SetTTL != 0 { fs = append(fs, withSetTTL(o.SetTTL)) } - if o.CasToken.setted { - fs = append(fs, withCompareCAS(o.CasToken.value)) + if o.CasToken != nil { + fs = append(fs, withCompareCAS(o.CasToken.value())) } return } @@ -151,7 +156,7 @@ const ( type MetaArithmeticOptions struct { Key string // the key of item BinaryKey []byte // interpret key as base64 encoded binary value (see metaget) - CasToken casToken // compare and swap token + CasToken CasToken // compare and swap token GetCasToken bool // return current CAS value if successful. GetTTL bool // return current TTL @@ -193,8 +198,8 @@ func (o MetaArithmeticOptions) marshal() (fs []metaFlag) { if o.SetTTL != 0 { fs = append(fs, withSetTTL(o.SetTTL)) } - if o.CasToken.setted { - fs = append(fs, withCompareCAS(o.CasToken.value)) + if o.CasToken != nil { + fs = append(fs, withCompareCAS(o.CasToken.value())) } return } diff --git a/meta_test.go b/meta_test.go index ecd1557..f5c14fd 100644 --- a/meta_test.go +++ b/meta_test.go @@ -30,7 +30,7 @@ func TestMetaSetGet(t *testing.T) { if err != nil { t.Error(err) } - if sr.CasToken.value == 0 { + if int(sr.CasToken) == 0 { t.Error("CAS Incorrect") } @@ -127,7 +127,7 @@ func TestMetaSetCAS(t *testing.T) { _, err = c.MetaSet(ctx, MetaSetOptions{ Key: k, Value: v, - CasToken: casToken{0, true}, + CasToken: casToken(0), }) if err != ErrCASConflict { t.Error("CAS Invalid") @@ -279,3 +279,30 @@ func TestBinaryKey(t *testing.T) { t.Error("Binary Key Error.", err) } } + +func TestMetaCasMiss(t *testing.T) { + c, _ := New(os.Getenv("MC_ADDRESS"), 2, 100) + + ctx := context.Background() + k := "MEI" + var ttl uint64 = 20 + + item, err := c.MetaGet(ctx, MetaGetOptions{ + Key: k, + SetVivifyWithTTL: ttl, + GetValue: true, + }) + if err != nil { + t.Error(err) + } + + item, err = c.MetaSet(ctx, MetaSetOptions{ + Key: k, + CasToken: item.CasToken, + Value: []byte("t"), + }) + if err != ErrCASConflict { + t.Errorf("CAS Error") + } + +}