int64 support for counters


#1

I’d like to implement an atomic counter. Ideally I can use Client.Add(), but the method does not return the new value of the bin. So I resort to a UDF that increases a number typed bin and return it. However the interface{} returned from Client.Execute() is of type int. How can I make the returned type become int64? Or are there any better way to get int64 counters?

Here is my UDF in case it’s useful:

function add(topRec, intBin, intVal)
        if type(intVal) ~= "number" then
                error("input value is not a number")
        end
        if not aerospike:exists(topRec) then
                aerospike:create(topRec)
        end
        local v = topRec[intBin]
        if v == nil then
                v = intVal
        else
                if type(v) ~= "number" then
                        error("value in the bin is not a number")
                end
                v = v + intVal
        end
        topRec[intBin] = v
        aerospike:update(topRec)
        return v
end

#2

There’s a much better way. You can use Operate command:

  bin := NewBin('atomicCounter', 1) // value can be any integer
  ops := []*Operation{
    GetOp(),
    AddOp(bin),
  }

  rec, err := client.Operate(nil, key, ops...)

Operate command is atomic, and all ops are done in a single transaction.

GetOp() always happens after other operations regardless of the order.

As to your other question:

counter := int64(rec.Bins['atomicCounter].(int))

int is an alias for int64 on 64bit platforms.


#3

That’s neat. Thanks!


#4

Out of curious, how to get int64 from db on 32 bit platform?


#5

The client is not supported on 32bit platforms.


#6

It seems better to use int64 as strconv.ParseInt() does.

Also looks right now the db (or Go client) does not support storing/fetching uint64? I actually faced this problem and have to encode uint64 into a customized base 64 string. Or I can actually use uint64 as LDT item’s key directly?

Thanks.


#7

You can cast your uint64 into an int64. Values bigger than MaxInt64 will become negative. On retrieval, you can cast them back to uint64.

  u64 := uint64(math.MaxUint64)
  i64 := int64(u64)

  key, err := NewKey(namespace, set, i64)
  client.PutBins(nil, key, NewBin("bin", i64))

  rec, err := client.Get(nil, key)
  fmt.Println(uint64(rec.Bins["bin"].(int)))

#8

I see. That’s a workaround for storage purpose. But it does not work for llist item key which is used for ordering, right?


#9

Haven’t checked, but I’d assume not.