├── .build.yml
├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── .testcoverage.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── abort_status.go
├── admin_command.go
├── admin_policy.go
├── aerospike.go
├── aerospike_bench_reflect_test.go
├── aerospike_bench_test.go
├── aerospike_suite_test.go
├── anonymous_fields_test.go
├── auth_mode.go
├── base_read_command.go
├── base_write_command.go
├── batch_attr.go
├── batch_command.go
├── batch_command_delete.go
├── batch_command_exists.go
├── batch_command_get.go
├── batch_command_get_reflect.go
├── batch_command_operate.go
├── batch_command_reflect.go
├── batch_command_udf.go
├── batch_delete.go
├── batch_delete_policy.go
├── batch_executer.go
├── batch_index_command_get.go
├── batch_node.go
├── batch_node_list.go
├── batch_offsets.go
├── batch_policy.go
├── batch_read.go
├── batch_read_policy.go
├── batch_record.go
├── batch_test.go
├── batch_udf.go
├── batch_udf_policy.go
├── batch_write.go
├── batch_write_policy.go
├── bench_batchget_test.go
├── bench_cdt_list_test.go
├── bench_get_test.go
├── bench_interface_allocs_test.go
├── bench_key_test.go
├── bench_packing_test.go
├── bench_rand_gen_test.go
├── bench_read_command_test.go
├── bench_recordset_test.go
├── bench_values_test.go
├── bench_write_command_test.go
├── bin.go
├── bit_overflow_action.go
├── bit_policy.go
├── bit_resize_flags.go
├── bit_write_flags.go
├── buffered_connection.go
├── bytes_buffer.go
├── cdt.go
├── cdt_bitwise.go
├── cdt_bitwise_test.go
├── cdt_context.go
├── cdt_context_test.go
├── cdt_list.go
├── cdt_list_test.go
├── cdt_map.go
├── cdt_map_test.go
├── client.go
├── client_appengine_exclusions.go
├── client_object_test.go
├── client_policy.go
├── client_reflect.go
├── client_reflect_test.go
├── client_test.go
├── cluster.go
├── command.go
├── commit_error.go
├── commit_policy.go
├── commit_status.go
├── complex_index_test.go
├── complex_query_test.go
├── connection.go
├── connection_heap.go
├── connection_heap_test.go
├── connection_test.go
├── delete_command.go
├── docs
├── README.md
├── aerospike.md
├── client.md
├── datamodel.md
├── log.md
├── performance.md
└── policies.md
├── error.go
├── error_test.go
├── example_client_test.go
├── example_listiter_int_test.go
├── example_listiter_string_test.go
├── example_listiter_time_test.go
├── example_mapiter_test.go
├── example_pagination_cursor_test.go
├── examples
├── add
│ └── add.go
├── append
│ └── append.go
├── batch
│ └── batch.go
├── blob
│ └── blob.go
├── count_set_objects
│ └── count_set_objects_using_request_info.go
├── custom_list_iter
│ └── custom_list_iter.go
├── expire
│ └── expire.go
├── expressions
│ └── expressions.go
├── generation
│ └── generation.go
├── geojson_query
│ └── geojson_query.go
├── get
│ ├── .gitignore
│ └── get.go
├── info
│ └── info.go
├── list_map
│ └── list_map.go
├── operate
│ └── operate.go
├── prepend
│ └── prepend.go
├── put
│ ├── .gitignore
│ └── put.go
├── putget
│ └── putget.go
├── query-aggregate
│ ├── average
│ │ └── average.go
│ ├── single_bin_sum
│ │ └── single_bin_sum.go
│ └── udf
│ │ ├── average.lua
│ │ └── sum_single_bin.lua
├── replace
│ └── replace.go
├── scan_paginate
│ └── scan_paginate.go
├── scan_parallel
│ └── scan_parallel.go
├── scan_serial
│ └── scan_serial.go
├── shared
│ └── shared.go
├── simple
│ └── simple.go
├── tls_secure_connection
│ └── tls_secure_connection.go
├── touch
│ └── touch.go
└── udf
│ └── udf.go
├── execute_command.go
├── execute_task.go
├── exists_command.go
├── exp_bit.go
├── exp_bit_test.go
├── exp_hll.go
├── exp_hll_test.go
├── exp_list.go
├── exp_list_test.go
├── exp_map.go
├── exp_map_test.go
├── exp_operation.go
├── exp_ops_test.go
├── expression.go
├── expression_ops_test.go
├── expression_test.go
├── field_type.go
├── filter.go
├── generation_policy.go
├── generics.go
├── geo_test.go
├── go.mod
├── go.sum
├── helper_test.go
├── hll_operation.go
├── hll_operation_test.go
├── hll_policy.go
├── hll_write_flags.go
├── host.go
├── host_test.go
├── index_collection_type.go
├── index_test.go
├── index_type.go
├── info.go
├── info_policy.go
├── internal
├── atomic
│ ├── array.go
│ ├── atomic_test.go
│ ├── bool.go
│ ├── bool_test.go
│ ├── guard.go
│ ├── guard_test.go
│ ├── int.go
│ ├── int_test.go
│ ├── map
│ │ └── map.go
│ ├── queue.go
│ ├── queue_test.go
│ ├── sync_val.go
│ ├── typed_val.go
│ └── typed_val_test.go
├── lua
│ ├── instance.go
│ ├── lua.go
│ ├── lua_aerospike.go
│ ├── lua_aerospike_test.go
│ ├── lua_list.go
│ ├── lua_list_test.go
│ ├── lua_map.go
│ ├── lua_map_test.go
│ ├── lua_stream.go
│ ├── lua_suite_test.go
│ └── resources
│ │ ├── aerospike.go
│ │ └── stream_ops.go
└── seq
│ └── seq.go
├── key.go
├── key_bench_test.go
├── key_helper.go
├── key_reflect_test.go
├── key_test.go
├── language.go
├── load_test.go
├── logger
└── logger.go
├── login_command.go
├── marshal.go
├── metrics_policy.go
├── multi_command.go
├── multi_policy.go
├── node.go
├── node_stats.go
├── node_test.go
├── node_validator.go
├── operate_args.go
├── operate_command_read.go
├── operate_command_write.go
├── operation.go
├── packer.go
├── packer_reflect.go
├── packing_test.go
├── partition.go
├── partition_filter.go
├── partition_parser.go
├── partition_status.go
├── partition_tracker.go
├── partitions.go
├── peers.go
├── peers_parser.go
├── pkg
├── bcrypt
│ ├── .gitignore
│ ├── LICENSE
│ ├── README
│ ├── bcrypt.go
│ └── cipher.go
└── ripemd160
│ ├── ripemd160.go
│ ├── ripemd160_test.go
│ └── ripemd160block.go
├── policy.go
├── privilege.go
├── query_aggregate_command.go
├── query_aggregate_test.go
├── query_command.go
├── query_context_test.go
├── query_duration.go
├── query_executor.go
├── query_objects_executor.go
├── query_partition_command.go
├── query_partitiopn_objects_command.go
├── query_policy.go
├── query_test.go
├── random_operation_test.go
├── read_command.go
├── read_command_reflect.go
├── read_command_reflect_test.go
├── read_header_command.go
├── read_mode_ap.go
├── read_mode_sc.go
├── record.go
├── record_exists_action.go
├── record_parser.go
├── recordset.go
├── recordset_test.go
├── replica_policy.go
├── role.go
├── scan_executor.go
├── scan_objects_executor.go
├── scan_partition_command.go
├── scan_partition_objects_command.go
├── scan_policy.go
├── scan_test.go
├── security_test.go
├── server_command.go
├── single_command.go
├── statement.go
├── task.go
├── task_drop_index.go
├── task_index.go
├── task_register.go
├── task_remove.go
├── test
└── resources
│ ├── average.lua
│ └── sum_single_bin.lua
├── test_utils_test.go
├── tools.go
├── tools
├── asinfo
│ └── asinfo.go
├── benchmark
│ ├── README.md
│ ├── benchmark.go
│ └── tls.go
└── cli
│ └── cli.go
├── touch_command.go
├── truncate_test.go
├── txn.go
├── txn_add_keys_command.go
├── txn_close.go
├── txn_error.go
├── txn_mark_roll_forward.go
├── txn_monitor.go
├── txn_roll.go
├── txn_roll_batch.go
├── txn_roll_batch_single.go
├── txn_roll_policy.go
├── txn_test.go
├── txn_verify_batch.go
├── txn_verify_batch_single.go
├── txn_verify_policy.go
├── types
├── epoc.go
├── histogram
│ ├── bench_histogram_test.go
│ ├── histogram.go
│ ├── histogram_test.go
│ ├── log2hist.go
│ └── sync_histogram.go
├── message.go
├── particle_type
│ └── particle_type.go
├── pool.go
├── pool
│ ├── buffer_pool_test.go
│ └── tiered_buffer.go
├── rand
│ └── xor_shift128.go
├── result_code.go
├── types.go
└── types_test.go
├── udf.go
├── udf_test.go
├── unpacker.go
├── user_roles.go
├── utils
└── buffer
│ └── buffer.go
├── value.go
├── value_helpers.go
├── value_reflect.go
├── value_test.go
├── werrgroup.go
├── write_command.go
├── write_payload_command.go
└── write_policy.go
/.build.yml:
--------------------------------------------------------------------------------
1 | name: aerospike-client-go
2 | dir: src/github.com/aerospike/aerospike-client-go
3 |
4 | container:
5 | - base:
6 | - docker.qe.aerospike.com/build/golang:1.11
7 |
8 | build:
9 | - name: build
10 | script:
11 | - go get -v github.com/aerospike/aerospike-client-go
12 | - go build -v -x github.com/aerospike/aerospike-client-go
13 | - go install -v -x github.com/aerospike/aerospike-client-go/tools/cli
14 | - go install -v -x github.com/aerospike/aerospike-client-go/tools/benchmark
15 | - go install -v -x github.com/aerospike/aerospike-client-go/tools/asinfo
16 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Aerospike Go Client Tests
2 | "on":
3 | push:
4 | pull_request:
5 |
6 | env:
7 | AEROSPIKE_HOSTS: "127.0.0.1:3000"
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | strategy:
12 | matrix:
13 | go-version:
14 | - "1.23"
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: "Setup Go ${{ matrix.go-version }}"
18 | uses: actions/setup-go@v3
19 | with:
20 | go-version: "${{ matrix.go-version }}"
21 | cache: true
22 | - name: Display Go version
23 | run: go version
24 | - name: Set up Aerospike Database
25 | uses: reugn/github-action-aerospike@v1
26 | - name: Test Lua Code
27 | run: go run github.com/onsi/ginkgo/v2/ginkgo -cover -race -r -keep-going -succinct -randomize-suites internal/lua
28 | - name: Test types package
29 | run: go run github.com/onsi/ginkgo/v2/ginkgo -cover -race -r -keep-going -succinct -randomize-suites types
30 | - name: Test pkg tests
31 | run: go run github.com/onsi/ginkgo/v2/ginkgo -cover -race -r -keep-going -succinct -randomize-suites pkg
32 | - name: Build Benchmark tool
33 | run: cd tools/benchmark | go build -tags as_proxy -o benchmark .
34 | - name: Build asinfo tool
35 | run: cd tools/asinfo | go build -o asinfo .
36 | - name: Build cli tool
37 | run: cd tools/cli | go build -o cli .
38 | - name: Build example files
39 | run: find examples -name "*.go" -type f -print0 | xargs -0 -n1 go build
40 | - name: Build with Reflection code removed
41 | run: go run github.com/onsi/ginkgo/v2/ginkgo build -tags="as_performance" .
42 | - name: Build for Google App Engine (unsafe package removed)
43 | run: go run github.com/onsi/ginkgo/v2/ginkgo build -tags="app_engine" .
44 | - name: Run the tests
45 | run: go run github.com/onsi/ginkgo/v2/ginkgo -coverprofile=./cover_native.out -covermode=atomic -coverpkg=./... -race -keep-going -succinct -randomize-suites -skip="HyperLogLog"
46 | - name: Download gocovmerge
47 | run: go mod download github.com/wadey/gocovmerge
48 | - name: Combine Cover Profiles
49 | run: go run github.com/wadey/gocovmerge cover_*.out > cover_all.out
50 | - name: Check Code Coverage
51 | uses: vladopajic/go-test-coverage@v2
52 | with:
53 | # Configure action using config file (option 1)
54 | config: ./.testcoverage.yml
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.prof
2 | *.test
3 | *.coverprofile*
4 | tools/benchmark/benchmark
5 | tools/asinfo/asinfo
6 | debug/
7 | _debug/
8 | tmp/
9 | .DS_Store
10 | TODO
11 | PLAN.todo
12 | .go_metalinter
13 | .go_style
14 | .golangci.yml
15 | .travis/read-write-udf.ldif
16 | .travis/people.ldif
17 | .travis/modify.ldif
18 | .travis/badwan.ldif
19 | .travis/access.ldif
20 | tools/
21 | cmd/
22 | .revive.toml
23 | Makefile
24 | testdata/
25 | Dockerfile*
26 | .dockerignore
27 | docker-compose.yml
28 | golangci.yml
29 | cover*.out
30 | .vscode/settings.json
31 |
--------------------------------------------------------------------------------
/.testcoverage.yml:
--------------------------------------------------------------------------------
1 | # (mandatory)
2 | # Path to coverprofile file (output of `go test -coverprofile` command).
3 | #
4 | # For cases where there are many coverage profiles, such as when running
5 | # unit tests and integration tests separately, you can combine all those
6 | # profiles into one. In this case, the profile should have a comma-separated list
7 | # of profile files, e.g., 'cover_unit.out,cover_integration.out'.
8 | profile: cover_all.out
9 |
10 | # (optional; but recommended to set)
11 | # When specified reported file paths will not contain local prefix in the output
12 | local-prefix: "github.com/aerospike/aerospike-client-go/v8"
13 |
14 | # Holds coverage thresholds percentages, values should be in range [0-100]
15 | threshold:
16 | # (optional; default 0)
17 | # The minimum coverage that each file should have
18 | file: 0
19 |
20 | # (optional; default 0)
21 | # The minimum coverage that each package should have
22 | package: 0
23 |
24 | # (optional; default 0)
25 | # The minimum total coverage project should have
26 | total: 0
27 |
28 | # Holds regexp rules which will override thresholds for matched files or packages
29 | # using their paths.
30 | #
31 | # First rule from this list that matches file or package is going to apply
32 | # new threshold to it. If project has multiple rules that match same path,
33 | # override rules should be listed in order from specific to more general rules.
34 | override:
35 | # Increase coverage threshold to 100% for `foo` package
36 | # (default is 80, as configured above in this example)
37 | #- threshold: 100
38 | # path: ^pkg/lib/foo$
39 |
40 | # Holds regexp rules which will exclude matched files or packages
41 | # from coverage statistics
42 | exclude:
43 | # Exclude files or packages matching their paths
44 | paths:
45 | # - \.pb\.go$ # excludes all protobuf generated files
46 | - proto/*
47 | - ^pkg/* # exclude package `pkg/bar`
48 | - client_builder.go
49 | - info_policy.go
50 | - commit_policy.go
51 | - generation_policy.go
52 | - privilege.go
53 | - read_mode_ap.go
54 | - read_mode_sc.go
55 | - record_exists_action.go
56 | - replica_policy.go
57 | - generics.go
58 | - login_command.go
59 | - types/histogram/histogram.go
60 | - types/rand/xor_shift128.go
61 | - internal/atomic/array.go
62 | # NOTES:
63 | # - symbol `/` in all path regexps will be replaced by current OS file path separator
64 | # to properly work on Windows
65 |
--------------------------------------------------------------------------------
/abort_status.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2024 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // Transaction abort status code.
18 | type AbortStatus string
19 |
20 | const (
21 | AbortStatusOK AbortStatus = "Abort succeeded"
22 | AbortStatusAlreadyCommitted AbortStatus = "Already committed"
23 | AbortStatusAlreadyAborted AbortStatus = "Already aborted"
24 | AbortStatusRollBackAbandoned AbortStatus = "Transaction client roll back abandoned. Server will eventually abort the Transaction."
25 | AbortStatusCloseAbandoned AbortStatus = "Transaction has been rolled back, but Transaction client close was abandoned. Server will eventually close the Transaction."
26 | )
27 |
--------------------------------------------------------------------------------
/admin_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "time"
18 |
19 | // AdminPolicy contains attributes used for user administration commands.
20 | type AdminPolicy struct {
21 |
22 | // User administration command socket timeout.
23 | // Default is 2 seconds.
24 | Timeout time.Duration
25 | }
26 |
27 | // NewAdminPolicy generates a new AdminPolicy with default values.
28 | func NewAdminPolicy() *AdminPolicy {
29 | return &AdminPolicy{
30 | Timeout: _DEFAULT_TIMEOUT,
31 | }
32 | }
33 |
34 | func (ap *AdminPolicy) deadline() (deadline time.Time) {
35 | if ap != nil && ap.Timeout > 0 {
36 | deadline = time.Now().Add(ap.Timeout)
37 | }
38 |
39 | return deadline
40 | }
41 |
42 | func (ap *AdminPolicy) timeout() time.Duration {
43 | if ap != nil && ap.Timeout > 0 {
44 | return ap.Timeout
45 | }
46 |
47 | return _DEFAULT_TIMEOUT
48 | }
49 |
--------------------------------------------------------------------------------
/aerospike.go:
--------------------------------------------------------------------------------
1 | // Package aerospike provides a client to connect and interact with an Aerospike cluster.
2 | // This is the official Go implementation of the Aerospike Client.
3 | package aerospike
4 |
--------------------------------------------------------------------------------
/aerospike_bench_reflect_test.go:
--------------------------------------------------------------------------------
1 | //go:build !as_performance
2 |
3 | // Copyright 2014-2022 Aerospike, Inc.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package aerospike_test
18 |
19 | import (
20 | "runtime"
21 |
22 | as "github.com/aerospike/aerospike-client-go/v8"
23 |
24 | "testing"
25 | )
26 |
27 | func benchGetObj(times int, client *as.Client, key *as.Key, obj interface{}) {
28 | for i := 0; i < times; i++ {
29 | if err = client.GetObject(nil, key, obj); err != nil {
30 | panic(err)
31 | }
32 | }
33 | }
34 |
35 | func benchPutObj(times int, client *as.Client, key *as.Key, wp *as.WritePolicy, obj interface{}) {
36 | for i := 0; i < times; i++ {
37 | if err = client.PutObject(wp, key, obj); err != nil {
38 | panic(err)
39 | }
40 | }
41 | }
42 |
43 | func Benchmark_GetObject(b *testing.B) {
44 | client, err := as.NewClientWithPolicy(clientPolicy, *host, *port)
45 | if err != nil {
46 | b.Fail()
47 | }
48 |
49 | key, _ := as.NewKey(*namespace, "databases", "Aerospike")
50 |
51 | obj := &OBJECT{198, "Jack Shaftoe and Company", []int64{1, 2, 3, 4, 5, 6}}
52 | client.PutObject(nil, key, obj)
53 |
54 | b.N = 1
55 | runtime.GC()
56 | b.ResetTimer()
57 | benchGetObj(b.N, client, key, obj)
58 | }
59 |
60 | func Benchmark_PutObject(b *testing.B) {
61 | client, err := as.NewClient(*host, *port)
62 | if err != nil {
63 | b.Fail()
64 | }
65 |
66 | // obj := &OBJECT{198, "Jack Shaftoe and Company", []byte(bytes.Repeat([]byte{32}, 1000))}
67 | obj := &OBJECT{198, "Jack Shaftoe and Company", []int64{1, 2, 3, 4, 5, 6}}
68 | key, _ := as.NewKey(*namespace, "databases", "Aerospike")
69 | writepolicy := as.NewWritePolicy(0, 0)
70 |
71 | b.N = 100
72 | runtime.GC()
73 | b.ResetTimer()
74 | benchPutObj(b.N, client, key, writepolicy, obj)
75 | }
76 |
--------------------------------------------------------------------------------
/auth_mode.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // AuthMode determines authentication mode.
18 | type AuthMode int
19 |
20 | const (
21 | // AuthModeInternal uses internal authentication only when user/password defined. Hashed password is stored
22 | // on the server. Do not send clear password. This is the default.
23 | AuthModeInternal AuthMode = iota
24 |
25 | // AuthModeExternal uses external authentication (like LDAP) when user/password defined. Specific external authentication is
26 | // configured on server. If TLSConfig is defined, sends clear password on node login via TLS.
27 | // Will return an error if TLSConfig is not defined.
28 | AuthModeExternal
29 |
30 | // AuthModePKI allows authentication and authorization based on a certificate. No user name or
31 | // password needs to be configured. Requires TLS and a client certificate.
32 | // Requires server version 5.7.0+
33 | AuthModePKI
34 | )
35 |
--------------------------------------------------------------------------------
/batch_executer.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // batchExecute Uses werrGroup to run commands using multiple goroutines,
18 | // and waits for their return
19 | func (clnt *Client) batchExecute(policy *BatchPolicy, batchNodes []*batchNode, cmd batcher) (int, Error) {
20 | maxConcurrentNodes := policy.ConcurrentNodes
21 | if maxConcurrentNodes <= 0 {
22 | maxConcurrentNodes = len(batchNodes)
23 | }
24 |
25 | // we need this list to count the number of filtered out records
26 | list := make([]batcher, 0, len(batchNodes))
27 |
28 | weg := newWeightedErrGroup(maxConcurrentNodes)
29 | for _, batchNode := range batchNodes {
30 | newCmd := cmd.cloneBatchCommand(batchNode)
31 | list = append(list, newCmd)
32 | weg.execute(newCmd)
33 | }
34 |
35 | errs := weg.wait()
36 |
37 | // count the filtered out records
38 | filteredOut := 0
39 | for i := range list {
40 | filteredOut += list[i].filteredOut()
41 | }
42 |
43 | return filteredOut, errs
44 | }
45 |
46 | // batchExecuteSimple Uses werrGroup to run commands using multiple goroutines,
47 | // and waits for their return
48 | func (clnt *Client) batchExecuteSimple(policy *BatchPolicy, cmds []command) Error {
49 | maxConcurrentNodes := policy.ConcurrentNodes
50 | if maxConcurrentNodes <= 0 {
51 | maxConcurrentNodes = len(cmds)
52 | }
53 |
54 | // we need this list to count the number of filtered out records
55 | weg := newWeightedErrGroup(maxConcurrentNodes)
56 | for _, cmd := range cmds {
57 | weg.execute(cmd)
58 | }
59 |
60 | return weg.wait()
61 | }
62 |
--------------------------------------------------------------------------------
/batch_node.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "fmt"
18 |
19 | type batchNode struct {
20 | Node *Node
21 | offsets []int
22 | }
23 |
24 | func newBatchNode(node *Node, capacity int, offset int) *batchNode {
25 | res := &batchNode{
26 | Node: node,
27 | offsets: make([]int, 1, capacity),
28 | }
29 |
30 | res.offsets[0] = offset
31 | return res
32 | }
33 |
34 | func (bn *batchNode) AddKey(offset int) {
35 | bn.offsets = append(bn.offsets, offset)
36 | }
37 |
38 | func (bn *batchNode) String() string {
39 | return fmt.Sprintf("Node: %s, Offsets: %v", bn.Node.String(), bn.offsets)
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/batch_offsets.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2024 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | type BatchOffsets interface {
18 | size() int
19 | get(int) int
20 | }
21 |
22 | // enforce the interface
23 | var _ BatchOffsets = &batchOffsetsNative{}
24 |
25 | type batchOffsetsNative struct {
26 | offsets []int
27 | }
28 |
29 | func newBatchOffsetsNative(batch *batchNode) *batchOffsetsNative {
30 | return &batchOffsetsNative{
31 | offsets: batch.offsets,
32 | }
33 | }
34 |
35 | func (bon *batchOffsetsNative) size() int {
36 | return len(bon.offsets)
37 | }
38 |
39 | func (bon *batchOffsetsNative) get(i int) int {
40 | return bon.offsets[i]
41 | }
42 |
--------------------------------------------------------------------------------
/bench_key_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | "strings"
19 | "testing"
20 |
21 | as "github.com/aerospike/aerospike-client-go/v8"
22 | "github.com/aerospike/aerospike-client-go/v8/pkg/ripemd160"
23 | ParticleType "github.com/aerospike/aerospike-client-go/v8/types/particle_type"
24 | )
25 |
26 | var str = strings.Repeat("abcd", 128)
27 | var strVal = as.NewValue(str)
28 | var buffer = []byte(str)
29 | var key *as.Key
30 |
31 | var res []byte
32 |
33 | // func hash_key_baseline(str string) {
34 | // hash := ripemd160.New()
35 | // for i := 0; i < b.N; i++ {
36 | // hash.Reset()
37 | // hash.Write(buffer)
38 | // res = hash.Sum(nil)
39 | // }
40 | // }
41 |
42 | func Benchmark_Key_Hash_BaseLine(b *testing.B) {
43 | hash := ripemd160.New()
44 | for i := 0; i < b.N; i++ {
45 | hash.Reset()
46 | hash.Write(buffer)
47 | res = hash.Sum(nil)
48 | }
49 | }
50 |
51 | func Benchmark_Key_NewKey(b *testing.B) {
52 | for i := 0; i < b.N; i++ {
53 | key, _ = as.NewKey(str, str, str)
54 | res = key.Digest()
55 | }
56 | }
57 |
58 | func Benchmark_K_ComputeDigest_Raw(b *testing.B) {
59 | h := ripemd160.New()
60 | setName := []byte(str)
61 | keyType := []byte{byte(ParticleType.STRING)}
62 | keyVal := []byte(str)
63 | for i := 0; i < b.N; i++ {
64 | h.Reset()
65 |
66 | // write will not fail; no error checking necessary
67 | h.Write(setName)
68 | h.Write(keyType)
69 | h.Write(keyVal)
70 |
71 | res = h.Sum(nil)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/bench_rand_gen_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "math/rand"
19 | "testing"
20 | "time"
21 |
22 | xor "github.com/aerospike/aerospike-client-go/v8/types/rand"
23 | )
24 |
25 | func Benchmark_math_rand(b *testing.B) {
26 | r := rand.New(rand.NewSource(time.Now().UnixNano()))
27 | for i := 0; i < b.N; i++ {
28 | r.Int63()
29 | }
30 | }
31 |
32 | func Benchmark_xor_rand(b *testing.B) {
33 | r := xor.NewXorRand()
34 | for i := 0; i < b.N; i++ {
35 | r.Int64()
36 | }
37 | }
38 |
39 | func Benchmark_math_rand_with_new(b *testing.B) {
40 | for i := 0; i < b.N; i++ {
41 | r := rand.New(rand.NewSource(time.Now().UnixNano()))
42 | r.Int63()
43 | }
44 | }
45 |
46 | func Benchmark_xor_rand_with_new(b *testing.B) {
47 | for i := 0; i < b.N; i++ {
48 | r := xor.NewXorRand()
49 | r.Int64()
50 | }
51 | }
52 |
53 | func Benchmark_math_rand_synched(b *testing.B) {
54 | for i := 0; i < b.N; i++ {
55 | rand.Int63()
56 | }
57 | }
58 |
59 | func Benchmark_xor_rand_fast_pool(b *testing.B) {
60 | r := xor.NewXorRand()
61 | for i := 0; i < b.N; i++ {
62 | r.Int64()
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/bench_recordset_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | "runtime"
19 | "testing"
20 |
21 | // "time"
22 | _ "net/http/pprof"
23 |
24 | as "github.com/aerospike/aerospike-client-go/v8"
25 | // _ "github.com/influxdata/influxdb/client"
26 | )
27 |
28 | func doScan(b *testing.B) {
29 | runtime.GC()
30 | b.ResetTimer()
31 | b.SetBytes(0)
32 |
33 | policy := as.NewScanPolicy()
34 |
35 | n := 0
36 | for i := 0; i < 10; i++ {
37 | results, err := client.ScanAll(policy, *namespace, "test")
38 | if err != nil {
39 | b.Errorf("Scan error: %s", err)
40 | }
41 |
42 | for range results.Results() {
43 | n++
44 | }
45 | }
46 | b.N = n
47 | }
48 |
49 | func doQuery(b *testing.B) {
50 | var err error
51 |
52 | runtime.GC()
53 | b.ResetTimer()
54 | b.SetBytes(0)
55 |
56 | n := 0
57 | //queries to aerospike
58 | policy := as.NewQueryPolicy()
59 | stmt := as.NewStatement(*namespace, "test")
60 |
61 | b.ResetTimer()
62 | b.SetBytes(0)
63 | results, err := client.Query(policy, stmt)
64 | if err != nil {
65 | b.Errorf("Query error: %s", err)
66 | }
67 |
68 | for range results.Results() {
69 | n++
70 | }
71 |
72 | b.N = n
73 | }
74 |
75 | func Benchmark_Scan(b *testing.B) {
76 | initTestVars()
77 | go doScan(b)
78 | }
79 |
80 | func Benchmark_Query(b *testing.B) {
81 | initTestVars()
82 | doQuery(b)
83 | }
84 |
--------------------------------------------------------------------------------
/bin.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // BinMap is used to define a map of bin names to values.
18 | type BinMap map[string]interface{}
19 |
20 | // Bin encapsulates a field name/value pair.
21 | type Bin struct {
22 | // Bin name. Current limit is 14 characters.
23 | Name string
24 |
25 | // Bin value.
26 | Value Value
27 | }
28 |
29 | // NewBin generates a new Bin instance, specifying bin name and string value.
30 | // For servers configured as "single-bin", enter an empty name.
31 | func NewBin(name string, value interface{}) *Bin {
32 | return &Bin{
33 | Name: name,
34 | Value: NewValue(value),
35 | }
36 | }
37 |
38 | // String implements Stringer interface.
39 | func (bn *Bin) String() string {
40 | return bn.Name + ":" + bn.Value.String()
41 | }
42 |
--------------------------------------------------------------------------------
/bit_overflow_action.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // BitOverflowAction specifies the action to take when bitwise add/subtract results in overflow/underflow.
18 | type BitOverflowAction int
19 |
20 | const (
21 | // BitOverflowActionFail specifies to fail operation with error.
22 | BitOverflowActionFail BitOverflowAction = 0
23 |
24 | // BitOverflowActionSaturate specifies that in add/subtract overflows/underflows, set to max/min value.
25 | // Example: MAXINT + 1 = MAXINT
26 | BitOverflowActionSaturate BitOverflowAction = 2
27 |
28 | // BitOverflowActionWrap specifies that in add/subtract overflows/underflows, wrap the value.
29 | // Example: MAXINT + 1 = -1
30 | BitOverflowActionWrap BitOverflowAction = 4
31 | )
32 |
--------------------------------------------------------------------------------
/bit_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // BitPolicy determines the Bit operation policy.
18 | type BitPolicy struct {
19 | flags int
20 | }
21 |
22 | // DefaultBitPolicy will return the default BitPolicy
23 | func DefaultBitPolicy() *BitPolicy {
24 | return &BitPolicy{BitWriteFlagsDefault}
25 | }
26 |
27 | // NewBitPolicy will return a BitPolicy will provided flags.
28 | func NewBitPolicy(flags int) *BitPolicy {
29 | return &BitPolicy{flags}
30 | }
31 |
--------------------------------------------------------------------------------
/bit_resize_flags.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // BitResizeFlags specifies the bitwise operation flags for resize.
18 | type BitResizeFlags int
19 |
20 | const (
21 | // BitResizeFlagsDefault specifies the defalt flag.
22 | BitResizeFlagsDefault BitResizeFlags = 0
23 |
24 | // BitResizeFlagsFromFront Adds/removes bytes from the beginning instead of the end.
25 | BitResizeFlagsFromFront BitResizeFlags = 1
26 |
27 | // BitResizeFlagsGrowOnly will only allow the []byte size to increase.
28 | BitResizeFlagsGrowOnly BitResizeFlags = 2
29 |
30 | // BitResizeFlagsShrinkOnly will only allow the []byte size to decrease.
31 | BitResizeFlagsShrinkOnly BitResizeFlags = 4
32 | )
33 |
--------------------------------------------------------------------------------
/bit_write_flags.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // BitWriteFlags specify bitwise operation policy write flags.
18 |
19 | const (
20 | // BitWriteFlagsDefault allows create or update.
21 | BitWriteFlagsDefault = 0
22 |
23 | // BitWriteFlagsCreateOnly specifies that:
24 | // If the bin already exists, the operation will be denied.
25 | // If the bin does not exist, a new bin will be created.
26 | BitWriteFlagsCreateOnly = 1
27 |
28 | // BitWriteFlagsUpdateOnly specifies that:
29 | // If the bin already exists, the bin will be overwritten.
30 | // If the bin does not exist, the operation will be denied.
31 | BitWriteFlagsUpdateOnly = 2
32 |
33 | // BitWriteFlagsNoFail specifies not to raise error if operation is denied.
34 | BitWriteFlagsNoFail = 4
35 |
36 | // BitWriteFlagsPartial allows other valid operations to be committed if this operations is
37 | // denied due to flag constraints.
38 | BitWriteFlagsPartial = 8
39 | )
40 |
--------------------------------------------------------------------------------
/cdt_context_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | gg "github.com/onsi/ginkgo/v2"
19 | gm "github.com/onsi/gomega"
20 |
21 | as "github.com/aerospike/aerospike-client-go/v8"
22 | )
23 |
24 | var _ = gg.Describe("CDTContext Test", func() {
25 |
26 | gg.It("should convert to/from base64", func() {
27 | ctxl := []*as.CDTContext{
28 | as.CtxMapKey(as.StringValue("key2")),
29 | as.CtxListRank(0),
30 | }
31 |
32 | b, err := as.CDTContextToBase64(ctxl)
33 | gm.Expect(err).ToNot(gm.HaveOccurred())
34 | gm.Expect(b).ToNot(gm.BeNil())
35 |
36 | ctxl2, err := as.Base64ToCDTContext(b)
37 | gm.Expect(err).ToNot(gm.HaveOccurred())
38 |
39 | arraysEqual(ctxl2, ctxl)
40 | })
41 |
42 | }) // describe
43 |
--------------------------------------------------------------------------------
/commit_error.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2024 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // Transaction error status.
18 | type CommitError string
19 |
20 | const (
21 | CommitErrorVerifyFail CommitError = "Transaction verify failed. Transaction aborted."
22 | CommitErrorVerifyFailCloseAbandoned CommitError = "Transaction verify failed. Transaction aborted. Transaction client close abandoned. Server will eventually close the Transaction."
23 | CommitErrorVerifyFailAbortAbandoned CommitError = "Transaction verify failed. Transaction client abort abandoned. Server will eventually abort the Transaction."
24 | CommitErrorMarkRollForwardAbandoned CommitError = "Transaction client mark roll forward abandoned. Server will eventually abort the Transaction."
25 | )
26 |
--------------------------------------------------------------------------------
/commit_policy.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package aerospike
19 |
20 | // CommitLevel indicates the desired consistency guarantee when committing a command on the server.
21 | type CommitLevel int
22 |
23 | const (
24 | // COMMIT_ALL indicates the server should wait until successfully committing master and all replicas.
25 | COMMIT_ALL CommitLevel = iota
26 |
27 | // COMMIT_MASTER indicates the server should wait until successfully committing master only.
28 | COMMIT_MASTER
29 | )
30 |
--------------------------------------------------------------------------------
/commit_status.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2024 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // Transaction commit status code.
18 | type CommitStatus string
19 |
20 | const (
21 | CommitStatusOK CommitStatus = "Commit succeeded"
22 | CommitStatusUnverified CommitStatus = "Commit process was disrupted on client side and unverified"
23 | CommitStatusAlreadyCommitted CommitStatus = "Already committed"
24 | CommitStatusAlreadyAborted CommitStatus = "Already aborted"
25 | CommitStatusRollForwardAbandoned CommitStatus = "Transaction client roll forward abandoned. Server will eventually commit the Transaction."
26 | CommitStatusCloseAbandoned CommitStatus = "Transaction has been rolled forward, but Transaction client close was abandoned. Server will eventually close the Transaction."
27 | )
28 |
--------------------------------------------------------------------------------
/delete_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | // guarantee deleteCommand implements command interface
22 | var _ command = &deleteCommand{}
23 |
24 | type deleteCommand struct {
25 | baseWriteCommand
26 |
27 | existed bool
28 | }
29 |
30 | func newDeleteCommand(
31 | cluster *Cluster,
32 | policy *WritePolicy,
33 | key *Key,
34 | ) (*deleteCommand, Error) {
35 | bwc, err := newBaseWriteCommand(cluster, policy, key)
36 | if err != nil {
37 | return nil, err
38 | }
39 |
40 | newDeleteCmd := &deleteCommand{
41 | baseWriteCommand: bwc,
42 | }
43 |
44 | return newDeleteCmd, nil
45 | }
46 |
47 | func (cmd *deleteCommand) writeBuffer(ifc command) Error {
48 | return cmd.setDelete(cmd.policy, cmd.key)
49 | }
50 |
51 | func (cmd *deleteCommand) parseResult(ifc command, conn *Connection) Error {
52 | resultCode, err := cmd.parseHeader()
53 | if err != nil {
54 | return newCustomNodeError(cmd.node, err.resultCode())
55 | }
56 |
57 | switch types.ResultCode(resultCode) {
58 | case 0:
59 | cmd.existed = true
60 | case types.KEY_NOT_FOUND_ERROR:
61 | cmd.existed = false
62 | case types.FILTERED_OUT:
63 | cmd.existed = true
64 | return ErrFilteredOut.err()
65 | default:
66 | return newError(types.ResultCode(resultCode))
67 | }
68 |
69 | return nil
70 | }
71 |
72 | func (cmd *deleteCommand) Existed() bool {
73 | return cmd.existed
74 | }
75 |
76 | func (cmd *deleteCommand) Execute() Error {
77 | return cmd.execute(cmd)
78 | }
79 |
80 | func (cmd *deleteCommand) commandType() commandType {
81 | return ttDelete
82 | }
83 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | This package describes the Aerospike Go Client API in detail.
4 |
5 |
6 | ## Usage
7 |
8 | The aerospike Go client package is the main entry point to the client API.
9 |
10 | ```go
11 | import as "github.com/aerospike/aerospike-client-go/v8"
12 | ```
13 |
14 | Before connecting to a cluster, you must import the package.
15 |
16 | You can then generate a client object for connecting to and operating against as cluster.
17 |
18 | ```go
19 | client, err := as.NewClient("127.0.0.1", 3000)
20 | ```
21 |
22 | The application will use the client object to connect to a cluster, then perform operations such as writing and reading records.
23 | Client object is goroutine frinedly, so you can use it in goroutines without synchronization.
24 | It caches its connections and internal state automatically for optimal performance. These settings can also be changed.
25 |
26 | For more details on client operations, see [Client Class](client.md).
27 |
28 | ## API Reference
29 |
30 | - [Aerospike Go Client Library Overview](aerospike.md)
31 | - [Client Class](client.md)
32 | - [Object Model](datamodel.md)
33 | - [Policy Objects](policies.md)
34 | - [Logger Object](log.md)
35 |
--------------------------------------------------------------------------------
/docs/log.md:
--------------------------------------------------------------------------------
1 | #log
2 |
3 | Various log levels available to log from the Aerospike API.
4 | Default is set to OFF.
5 |
6 | ```go
7 | import asl "github.com/aerospike/aerospike-client-go/v8/logger"
8 |
9 | asl.Logger.SetLevel(asl.OFF)
10 | ```
11 |
12 | You can set the Logger to any object that supports log.Logger interface.
13 |
14 | ## Log levels:
15 |
16 | ##### ERROR
17 |
18 | ##### WARN
19 |
20 | ##### INFO
21 |
22 | ##### DEBUG
23 |
24 | ##### OFF
25 |
--------------------------------------------------------------------------------
/example_listiter_int_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | "fmt"
19 | "log"
20 |
21 | as "github.com/aerospike/aerospike-client-go/v8"
22 | )
23 |
24 | /*
25 | myListInt
26 | */
27 | var _ as.ListIter = myListInt([]int{})
28 |
29 | // your custom list
30 | type myListInt []int
31 |
32 | func (ml myListInt) PackList(buf as.BufferEx) (int, error) {
33 | size := 0
34 | for _, elem := range ml {
35 | n, err := as.PackInt64(buf, int64(elem))
36 | size += n
37 | if err != nil {
38 | return size, err
39 | }
40 | }
41 |
42 | return size, nil
43 | }
44 |
45 | func (ml myListInt) Len() int {
46 | return len(ml)
47 | }
48 |
49 | func ExampleListIter_int() {
50 | // Setup the client here
51 | // client, err := as.NewClient("127.0.0.1", 3000)
52 | // if err != nil {
53 | // log.Fatal(err)
54 | // }
55 |
56 | var v as.Value = as.NewValue(myListInt([]int{1, 2, 3}))
57 | key, err := as.NewKey(*namespace, "test", 1)
58 | if err != nil {
59 | log.Fatal(err)
60 | }
61 |
62 | err = client.Put(nil, key, as.BinMap{"myBin": v})
63 | if err != nil {
64 | log.Fatal(err)
65 | }
66 |
67 | rec, err := client.Get(nil, key)
68 | if err != nil {
69 | log.Fatal(err)
70 | }
71 |
72 | fmt.Println(rec.Bins["myBin"])
73 | // Output:
74 | // [1 2 3]
75 | }
76 |
--------------------------------------------------------------------------------
/example_listiter_string_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | "fmt"
19 | "log"
20 |
21 | as "github.com/aerospike/aerospike-client-go/v8"
22 | )
23 |
24 | /*
25 | myListString
26 | */
27 | var _ as.ListIter = myListString([]string{})
28 |
29 | // your custom list
30 | type myListString []string
31 |
32 | func (ml myListString) PackList(buf as.BufferEx) (int, error) {
33 | size := 0
34 | for _, elem := range ml {
35 | n, err := as.PackString(buf, elem)
36 | size += n
37 | if err != nil {
38 | return size, err
39 | }
40 | }
41 | return size, nil
42 | }
43 |
44 | func (ml myListString) Len() int {
45 | return len(ml)
46 | }
47 |
48 | func ExampleListIter_string() {
49 | // Setup the client here
50 | // client, err := as.NewClient("127.0.0.1", 3000)
51 | // if err != nil {
52 | // log.Fatal(err)
53 | // }
54 |
55 | var v as.Value = as.NewValue(myListString([]string{"a", "b", "c"}))
56 | key, err := as.NewKey(*namespace, "test", 1)
57 | if err != nil {
58 | log.Fatal(err)
59 | }
60 |
61 | err = client.Put(nil, key, as.BinMap{"myBin": v})
62 | if err != nil {
63 | log.Fatal(err)
64 | }
65 |
66 | rec, err := client.Get(nil, key)
67 | if err != nil {
68 | log.Fatal(err)
69 | }
70 |
71 | fmt.Println(rec.Bins["myBin"])
72 | // Output:
73 | // [a b c]
74 | }
75 |
--------------------------------------------------------------------------------
/example_listiter_time_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | "fmt"
19 | "log"
20 | "time"
21 |
22 | as "github.com/aerospike/aerospike-client-go/v8"
23 | )
24 |
25 | /*
26 | myListTime
27 | */
28 | var _ as.ListIter = myListTime([]time.Time{})
29 |
30 | // your custom list
31 | type myListTime []time.Time
32 |
33 | func (ml myListTime) PackList(buf as.BufferEx) (int, error) {
34 | size := 0
35 | for _, elem := range ml {
36 | n, err := as.PackInt64(buf, elem.UnixNano())
37 | size += n
38 | if err != nil {
39 | return size, err
40 | }
41 | }
42 | return size, nil
43 | }
44 |
45 | func (ml myListTime) Len() int {
46 | return len(ml)
47 | }
48 |
49 | func ExampleListIter_time() {
50 | // Setup the client here
51 | // client, err := as.NewClient("127.0.0.1", 3000)
52 | // if err != nil {
53 | // log.Fatal(err)
54 | // }
55 |
56 | now1 := time.Unix(123123123, 0)
57 | now2 := time.Unix(123123124, 0)
58 | now3 := time.Unix(123123125, 0)
59 | var v as.Value = as.NewValue(myListTime([]time.Time{now1, now2, now3}))
60 | key, err := as.NewKey(*namespace, "test", 1)
61 | if err != nil {
62 | log.Fatal(err)
63 | }
64 |
65 | err = client.Put(nil, key, as.BinMap{"myBin": v})
66 | if err != nil {
67 | log.Fatal(err)
68 | }
69 |
70 | rec, err := client.Get(nil, key)
71 | if err != nil {
72 | log.Fatal(err)
73 | }
74 |
75 | fmt.Println(rec.Bins["myBin"])
76 | // Output:
77 | // [123123123000000000 123123124000000000 123123125000000000]
78 | }
79 |
--------------------------------------------------------------------------------
/example_mapiter_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | "fmt"
19 | "log"
20 | "time"
21 |
22 | as "github.com/aerospike/aerospike-client-go/v8"
23 | )
24 |
25 | /*
26 | myMapStringTime
27 | */
28 | var _ as.MapIter = myMapStringTime(map[string]time.Time{})
29 |
30 | // your custom list
31 | type myMapStringTime map[string]time.Time
32 |
33 | func (mm myMapStringTime) PackMap(buf as.BufferEx) (int, error) {
34 | size := 0
35 | for key, val := range mm {
36 | n, err := as.PackString(buf, key)
37 | size += n
38 | if err != nil {
39 | return size, err
40 | }
41 |
42 | n, err = as.PackInt64(buf, val.UnixNano())
43 | size += n
44 | if err != nil {
45 | return size, err
46 | }
47 | }
48 | return size, nil
49 | }
50 |
51 | func (mm myMapStringTime) Len() int {
52 | return len(mm)
53 | }
54 |
55 | func ExampleMapIter() {
56 | // Setup the client here
57 | // client, err := as.NewClient("127.0.0.1", 3000)
58 | // if err != nil {
59 | // log.Fatal(err)
60 | // }
61 |
62 | now := time.Unix(123123123, 0)
63 | var v as.Value = as.NewValue(myMapStringTime(map[string]time.Time{"now": now}))
64 | key, err := as.NewKey(*namespace, "test", 1)
65 | if err != nil {
66 | log.Fatal(err)
67 | }
68 |
69 | err = client.Put(nil, key, as.BinMap{"myBin": v})
70 | if err != nil {
71 | log.Fatal(err)
72 | }
73 |
74 | rec, err := client.Get(nil, key)
75 | if err != nil {
76 | log.Fatal(err)
77 | }
78 |
79 | fmt.Println(rec.Bins["myBin"])
80 | // Output:
81 | // map[now:123123123000000000]
82 | }
83 |
--------------------------------------------------------------------------------
/example_pagination_cursor_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | "fmt"
19 | "log"
20 |
21 | as "github.com/aerospike/aerospike-client-go/v8"
22 | )
23 |
24 | func ExamplePartitionFilter_EncodeCursor() {
25 | // Setup the client here
26 | // client, err := as.NewClient("127.0.0.1", 3000)
27 | // if err != nil {
28 | // log.Fatal(err)
29 | // }
30 |
31 | var ns = *namespace
32 | var set = randString(50)
33 |
34 | // initialize the records
35 | keyCount := 1000
36 | for i := 0; i < keyCount; i++ {
37 | key, err := as.NewKey(ns, set, i)
38 | if err != nil {
39 | log.Fatal(err)
40 | }
41 |
42 | err = client.Put(nil, key, as.BinMap{"bin": i})
43 | if err != nil {
44 | log.Fatal(err)
45 | }
46 | }
47 |
48 | // Set up the scan policy
49 | spolicy := as.NewScanPolicy()
50 | spolicy.MaxRecords = 30
51 |
52 | received := 0
53 | var buf []byte
54 | for received < keyCount {
55 | pf := as.NewPartitionFilterAll()
56 |
57 | if len(buf) > 0 {
58 | err = pf.DecodeCursor(buf)
59 | if err != nil {
60 | log.Fatal(err)
61 | }
62 | }
63 |
64 | recordset, err := client.ScanPartitions(spolicy, pf, ns, set)
65 | if err != nil {
66 | log.Fatal(err)
67 | }
68 |
69 | counter := 0
70 | for range recordset.Results() {
71 | counter++
72 | received++
73 | }
74 |
75 | if counter > 30 {
76 | log.Fatal("More records received than requested.")
77 | }
78 |
79 | buf, err = pf.EncodeCursor()
80 | if err != nil {
81 | log.Fatal(err)
82 | }
83 | }
84 |
85 | fmt.Println(received)
86 | // Output:
87 | // 1000
88 | }
89 |
--------------------------------------------------------------------------------
/examples/append/append.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "log"
22 |
23 | as "github.com/aerospike/aerospike-client-go/v8"
24 | shared "github.com/aerospike/aerospike-client-go/v8/examples/shared"
25 | )
26 |
27 | func main() {
28 | runExample(shared.Client)
29 | log.Println("Example finished successfully.")
30 | }
31 |
32 | func runExample(client *as.Client) {
33 | key, err := as.NewKey(*shared.Namespace, *shared.Set, "appendkey")
34 | shared.PanicOnError(err)
35 |
36 | binName := "appendbin"
37 |
38 | // Delete record if it already exists.
39 | client.Delete(shared.WritePolicy, key)
40 |
41 | bin := as.NewBin(binName, "Hello")
42 | log.Println("Initial append will create record. Initial value is ", bin.Value, ".")
43 | client.AppendBins(shared.WritePolicy, key, bin)
44 |
45 | bin = as.NewBin(binName, " World")
46 | log.Println("Append \"", bin.Value, "\" to existing record.")
47 | client.AppendBins(shared.WritePolicy, key, bin)
48 |
49 | record, err := client.Get(shared.Policy, key, bin.Name)
50 | shared.PanicOnError(err)
51 |
52 | if record == nil {
53 | log.Fatalf(
54 | "Failed to get: namespace=%s set=%s key=%s",
55 | key.Namespace(), key.SetName(), key.Value())
56 | }
57 |
58 | received := record.Bins[bin.Name]
59 | expected := "Hello World"
60 |
61 | if received == expected {
62 | log.Printf("Append successful: ns=%s set=%s key=%s bin=%s value=%s",
63 | key.Namespace(), key.SetName(), key.Value(), bin.Name, received)
64 | } else {
65 | log.Fatalf("Append mismatch: Expected %s. Received %s.", expected, received)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/examples/blob/blob.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package main
16 |
17 | import (
18 | as "github.com/aerospike/aerospike-client-go/v8"
19 | )
20 |
21 | // Person is a custom data type to be converted to a blob
22 | type Person struct {
23 | name string
24 | }
25 |
26 | // EncodeBlob defines The AerospikeBlob interface
27 | func (p Person) EncodeBlob() ([]byte, error) {
28 | return []byte(p.name), nil
29 | }
30 |
31 | // DecodeBlob is optional, and should be used manually
32 | func (p *Person) DecodeBlob(buf []byte) error {
33 | p.name = string(buf)
34 | return nil
35 | }
36 |
37 | func main() {
38 | // define a client to connect to
39 | client, err := as.NewClient("127.0.0.1", 3000)
40 | panicOnError(err)
41 |
42 | namespace := "test"
43 | setName := "people"
44 | key, err := as.NewKey(namespace, setName, "key") // user key can be of any supported type
45 | panicOnError(err)
46 |
47 | // define some bins
48 | bins := as.BinMap{
49 | "bin1": Person{name: "Albert Einstein"},
50 | "bin2": &Person{name: "Richard Feynman"},
51 | }
52 |
53 | // write the bins
54 | writePolicy := as.NewWritePolicy(0, 0)
55 | err = client.Put(writePolicy, key, bins)
56 | panicOnError(err)
57 |
58 | // read it back!
59 | readPolicy := as.NewPolicy()
60 | rec, err := client.Get(readPolicy, key)
61 | panicOnError(err)
62 |
63 | result := &Person{}
64 |
65 | // decode first object
66 | result.DecodeBlob(rec.Bins["bin1"].([]byte))
67 |
68 | // decode second object
69 | result.DecodeBlob(rec.Bins["bin2"].([]byte))
70 | }
71 |
72 | func panicOnError(err error) {
73 | if err != nil {
74 | panic(err)
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/examples/get/.gitignore:
--------------------------------------------------------------------------------
1 | get
--------------------------------------------------------------------------------
/examples/get/get.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package main
16 |
17 | import (
18 | "flag"
19 | "fmt"
20 | "os"
21 | "strconv"
22 |
23 | as "github.com/aerospike/aerospike-client-go/v8"
24 | )
25 |
26 | var (
27 | host = "127.0.0.1"
28 | port = 3000
29 | namespace = "test"
30 | set = "demo"
31 | )
32 |
33 | func main() {
34 |
35 | var err error
36 |
37 | // arguments
38 | flag.StringVar(&host, "host", host, "Remote host")
39 | flag.IntVar(&port, "port", port, "Remote port")
40 | flag.StringVar(&namespace, "namespace", namespace, "Namespace")
41 | flag.StringVar(&set, "set", set, "Set name")
42 |
43 | // parse flags
44 | flag.Parse()
45 |
46 | // args
47 | args := flag.Args()
48 |
49 | if len(args) < 1 {
50 | printError("Missing argument")
51 | }
52 |
53 | client, err := as.NewClient(host, port)
54 | panicOnError(err)
55 |
56 | var key *as.Key
57 |
58 | skey := flag.Arg(0)
59 | ikey, err := strconv.ParseInt(skey, 10, 64)
60 | if err == nil {
61 | key, err = as.NewKey(namespace, set, ikey)
62 | panicOnError(err)
63 | } else {
64 | key, err = as.NewKey(namespace, set, skey)
65 | panicOnError(err)
66 | }
67 |
68 | policy := as.NewPolicy()
69 | rec, err := client.Get(policy, key)
70 | panicOnError(err)
71 | if rec != nil {
72 | printOK("%v", rec.Bins)
73 | } else {
74 | printError("record not found: namespace=%s set=%s key=%v", key.Namespace(), key.SetName(), key.Value())
75 | }
76 | }
77 |
78 | func panicOnError(err error) {
79 | if err != nil {
80 | panic(err)
81 | }
82 | }
83 |
84 | func printOK(format string, a ...interface{}) {
85 | fmt.Printf("ok: "+format+"\n", a...)
86 | os.Exit(0)
87 | }
88 |
89 | func printError(format string, a ...interface{}) {
90 | fmt.Printf("error: "+format+"\n", a...)
91 | os.Exit(1)
92 | }
93 |
--------------------------------------------------------------------------------
/examples/info/info.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package main
16 |
17 | import (
18 | "log"
19 | "time"
20 |
21 | as "github.com/aerospike/aerospike-client-go/v8"
22 | )
23 |
24 | func main() {
25 | // remove timestamps from log messages
26 | log.SetFlags(0)
27 |
28 | // connect to the host
29 | cp := as.NewClientPolicy()
30 | cp.Timeout = 10 * time.Second
31 |
32 | // cp.User = "admin"
33 | // cp.Password = "admin"
34 |
35 | conn, err := as.NewConnection(cp, as.NewHost("localhost", 3000))
36 | if err != nil {
37 | log.Fatalln(err.Error())
38 | }
39 |
40 | // Login if needed
41 | // if err := conn.Login(cp); err != nil {
42 | // log.Fatalln(err.Error())
43 | // }
44 |
45 | infoMap, err := conn.RequestInfo("")
46 | if err != nil {
47 | log.Fatalln(err.Error())
48 | }
49 |
50 | cnt := 1
51 | for k, v := range infoMap {
52 | log.Printf("%d : %s\n %s\n", cnt, k, v)
53 | cnt++
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/examples/operate/operate.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "log"
22 |
23 | as "github.com/aerospike/aerospike-client-go/v8"
24 | shared "github.com/aerospike/aerospike-client-go/v8/examples/shared"
25 | )
26 |
27 | func main() {
28 | runExample(shared.Client)
29 |
30 | log.Println("Example finished successfully.")
31 | }
32 |
33 | func runExample(client *as.Client) {
34 | // Write initial record.
35 | key, _ := as.NewKey(*shared.Namespace, *shared.Set, "opkey")
36 | bin1 := as.NewBin("optintbin", 7)
37 | bin2 := as.NewBin("optstringbin", "string value")
38 | log.Printf("Put: namespace=%s set=%s key=%s bin1=%s value1=%s bin2=%s value2=%s",
39 | key.Namespace(), key.SetName(), key.Value(), bin1.Name, bin1.Value, bin2.Name, bin2.Value)
40 | client.PutBins(shared.WritePolicy, key, bin1, bin2)
41 |
42 | // Add integer, write new string and read record.
43 | bin3 := as.NewBin(bin1.Name, 4)
44 | bin4 := as.NewBin(bin2.Name, "new string")
45 | log.Println("Add: ", bin3.Value)
46 | log.Println("Write: ", bin4.Value)
47 | log.Println("Read:")
48 |
49 | record, err := client.Operate(shared.WritePolicy, key, as.AddOp(bin3), as.PutOp(bin4), as.GetOp())
50 | shared.PanicOnError(err)
51 |
52 | if record == nil {
53 | log.Fatalf(
54 | "Failed to get: namespace=%s set=%s key=%s",
55 | key.Namespace(), key.SetName(), key.Value())
56 | }
57 |
58 | binExpected := as.NewBin(bin3.Name, 11)
59 | shared.ValidateBin(key, binExpected, record)
60 | shared.ValidateBin(key, bin4, record)
61 | }
62 |
--------------------------------------------------------------------------------
/examples/prepend/prepend.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "log"
22 |
23 | as "github.com/aerospike/aerospike-client-go/v8"
24 | shared "github.com/aerospike/aerospike-client-go/v8/examples/shared"
25 | )
26 |
27 | func main() {
28 | runExample(shared.Client)
29 | log.Println("Example finished successfully.")
30 | }
31 |
32 | func runExample(client *as.Client) {
33 | key, err := as.NewKey(*shared.Namespace, *shared.Set, "prependkey")
34 | shared.PanicOnError(err)
35 |
36 | binName := "prependbin"
37 |
38 | // Delete record if it already exists.
39 | client.Delete(shared.WritePolicy, key)
40 |
41 | bin := as.NewBin(binName, "World")
42 | log.Println("Initial prepend will create record. Initial value is ", bin.Value, ".")
43 | client.PrependBins(shared.WritePolicy, key, bin)
44 |
45 | bin = as.NewBin(binName, "Hello ")
46 | log.Println("Prepend \"", bin.Value, "\" to existing record.")
47 | client.PrependBins(shared.WritePolicy, key, bin)
48 |
49 | record, err := client.Get(shared.Policy, key, bin.Name)
50 | shared.PanicOnError(err)
51 |
52 | if record == nil {
53 | log.Fatalf(
54 | "Failed to get: namespace=%s set=%s key=%s",
55 | key.Namespace(), key.SetName(), key.Value())
56 | }
57 |
58 | // The value received from the server is an unsigned byte stream.
59 | // Convert to an integer before comparing with expected.
60 | received := record.Bins[bin.Name]
61 | expected := "Hello World"
62 |
63 | if received == expected {
64 | log.Printf("Prepend successful: ns=%s set=%s key=%s bin=%s value=%s",
65 | key.Namespace(), key.SetName(), key.Value(), bin.Name, received)
66 | } else {
67 | log.Fatalf("Prepend mismatch: Expected %s. Received %s.", expected, received)
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/examples/put/.gitignore:
--------------------------------------------------------------------------------
1 | put
--------------------------------------------------------------------------------
/examples/query-aggregate/average/average.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "log"
22 | "os"
23 | "time"
24 |
25 | as "github.com/aerospike/aerospike-client-go/v8"
26 | shared "github.com/aerospike/aerospike-client-go/v8/examples/shared"
27 | )
28 |
29 | const keyCount = 1000
30 |
31 | func main() {
32 | runExample(shared.Client)
33 | log.Println("Example finished successfully.")
34 | }
35 |
36 | func runExample(client *as.Client) {
37 | // Set LuaPath
38 | luaPath, _ := os.Getwd()
39 | luaPath += "/udf/"
40 | as.SetLuaPath(luaPath)
41 |
42 | filename := "average"
43 | regTask, err := client.RegisterUDFFromFile(nil, luaPath+filename+".lua", filename+".lua", as.LUA)
44 | shared.PanicOnError(err)
45 |
46 | // wait until UDF is created
47 | shared.PanicOnError(<-regTask.OnComplete())
48 |
49 | sum := 0
50 | for i := 1; i <= keyCount; i++ {
51 | sum += i
52 | key, err := as.NewKey(*shared.Namespace, *shared.Set, i)
53 | shared.PanicOnError(err)
54 |
55 | bin1 := as.NewBin("bin1", i)
56 | client.PutBins(nil, key, bin1)
57 | }
58 |
59 | average := float64(sum) / float64(keyCount)
60 |
61 | t := time.Now()
62 | stm := as.NewStatement(*shared.Namespace, *shared.Set)
63 | res, err := client.QueryAggregate(nil, stm, filename, filename, as.StringValue("bin1"))
64 | shared.PanicOnError(err)
65 |
66 | for rec := range res.Results() {
67 | res := rec.Record.Bins["SUCCESS"].(map[interface{}]interface{})
68 | log.Printf("Result from Map/Reduce: %v\n", res)
69 | log.Printf("Result %f should equal %f\n", res["sum"].(float64)/res["count"].(float64), average)
70 | }
71 | log.Println("Map/Reduce took", time.Now().Sub(t))
72 | }
73 |
--------------------------------------------------------------------------------
/examples/query-aggregate/single_bin_sum/single_bin_sum.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "log"
22 | "os"
23 | "time"
24 |
25 | as "github.com/aerospike/aerospike-client-go/v8"
26 | shared "github.com/aerospike/aerospike-client-go/v8/examples/shared"
27 | )
28 |
29 | const keyCount = 1000
30 |
31 | func main() {
32 | runExample(shared.Client)
33 | log.Println("Example finished successfully.")
34 | }
35 |
36 | func runExample(client *as.Client) {
37 | // Set LuaPath
38 | luaPath, _ := os.Getwd()
39 | luaPath += "/udf/"
40 | as.SetLuaPath(luaPath)
41 |
42 | filename := "sum_single_bin"
43 | regTask, err := client.RegisterUDFFromFile(nil, luaPath+filename+".lua", filename+".lua", as.LUA)
44 | shared.PanicOnError(err)
45 |
46 | // wait until UDF is created
47 | shared.PanicOnError(<-regTask.OnComplete())
48 |
49 | sum := 0
50 | for i := 1; i <= keyCount; i++ {
51 | sum += i
52 | key, err := as.NewKey(*shared.Namespace, *shared.Set, i)
53 | shared.PanicOnError(err)
54 |
55 | bin1 := as.NewBin("bin1", i)
56 | client.PutBins(nil, key, bin1)
57 | }
58 |
59 | t := time.Now()
60 | stm := as.NewStatement(*shared.Namespace, *shared.Set)
61 | res, err := client.QueryAggregate(nil, stm, filename, filename, as.StringValue("bin1"))
62 | shared.PanicOnError(err)
63 |
64 | for rec := range res.Results() {
65 | log.Printf("Result %f should equal %d\n", rec.Record.Bins["SUCCESS"], sum)
66 | }
67 | log.Println("Map/Reduce took", time.Now().Sub(t))
68 | }
69 |
--------------------------------------------------------------------------------
/examples/query-aggregate/udf/average.lua:
--------------------------------------------------------------------------------
1 | function average(s, name)
2 |
3 | local function mapper(out, rec)
4 | out['sum'] = (out['sum'] or 0) + (rec[name] or 0)
5 | out['count'] = (out['count'] or 0) + 1
6 | return out
7 | end
8 |
9 | local function reducer(a, b)
10 | local out = map()
11 |
12 | out['sum'] = a['sum'] + b['sum']
13 | out['count'] = a['count'] + b['count']
14 | return out
15 | end
16 |
17 | return s : aggregate(map{sum = 0, count = 0}, mapper) : reduce(reducer)
18 | end
19 |
--------------------------------------------------------------------------------
/examples/query-aggregate/udf/sum_single_bin.lua:
--------------------------------------------------------------------------------
1 | local function reducer(val1,val2)
2 | return val1 + val2
3 | end
4 |
5 | function sum_single_bin(stream,name)
6 | local function mapper(rec)
7 | return rec[name]
8 | end
9 |
10 | return stream : map(mapper) : reduce(reducer)
11 | end
12 |
--------------------------------------------------------------------------------
/examples/scan_paginate/scan_paginate.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "log"
22 | "time"
23 |
24 | as "github.com/aerospike/aerospike-client-go/v8"
25 | shared "github.com/aerospike/aerospike-client-go/v8/examples/shared"
26 | )
27 |
28 | func main() {
29 | runExample(shared.Client)
30 |
31 | log.Println("Example finished successfully.")
32 | }
33 |
34 | func runExample(client *as.Client) {
35 | log.Printf("Scan parallel: namespace=" + *shared.Namespace + " set=" + *shared.Set)
36 | recordCount := 0
37 | begin := time.Now()
38 | policy := as.NewScanPolicy()
39 | policy.MaxRecords = 30
40 |
41 | pf := as.NewPartitionFilterAll()
42 |
43 | receivedRecords := 1
44 | for receivedRecords > 0 {
45 | receivedRecords = 0
46 |
47 | log.Println("Scanning Page:", recordCount/int(policy.MaxRecords))
48 | recordset, err := client.ScanPartitions(policy, pf, *shared.Namespace, *shared.Set)
49 | shared.PanicOnError(err)
50 |
51 | for rec := range recordset.Results() {
52 | if rec.Err != nil {
53 | // if there was an error, handle it if needed
54 | // Scans are retried in Aerospike servers v5+
55 | log.Println(err)
56 | continue
57 | }
58 |
59 | recordCount++
60 | receivedRecords++
61 | }
62 | }
63 |
64 | log.Println("Total records returned: ", recordCount)
65 | log.Println("Elapsed time: ", time.Since(begin), " seconds")
66 | }
67 |
--------------------------------------------------------------------------------
/examples/scan_parallel/scan_parallel.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "log"
22 | "time"
23 |
24 | as "github.com/aerospike/aerospike-client-go/v8"
25 | shared "github.com/aerospike/aerospike-client-go/v8/examples/shared"
26 | )
27 |
28 | func main() {
29 | runExample(shared.Client)
30 |
31 | log.Println("Example finished successfully.")
32 | }
33 |
34 | func runExample(client *as.Client) {
35 | log.Printf("Scan parallel: namespace=" + *shared.Namespace + " set=" + *shared.Set)
36 |
37 | recordCount := 0
38 | begin := time.Now()
39 | policy := as.NewScanPolicy()
40 | recordset, err := client.ScanAll(policy, *shared.Namespace, *shared.Set)
41 | shared.PanicOnError(err)
42 |
43 | for rec := range recordset.Results() {
44 | if rec.Err != nil {
45 | // if there was an error, handle it if needed
46 | // Scans are retried in Aerospike servers v5+
47 | log.Println(err)
48 | continue
49 | }
50 |
51 | recordCount++
52 |
53 | if (recordCount % 100000) == 0 {
54 | log.Println("Records ", recordCount)
55 | }
56 | }
57 |
58 | end := time.Now()
59 | seconds := float64(end.Sub(begin)) / float64(time.Second)
60 | log.Println("Total records returned: ", recordCount)
61 | log.Println("Elapsed time: ", seconds, " seconds")
62 | performance := shared.Round(float64(recordCount)/float64(seconds), 0.5, 0)
63 | log.Println("Records/second: ", performance)
64 | }
65 |
--------------------------------------------------------------------------------
/exists_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | // guarantee existsCommand implements command interface
22 | var _ command = &existsCommand{}
23 |
24 | type existsCommand struct {
25 | baseReadCommand
26 |
27 | exists bool
28 | }
29 |
30 | func newExistsCommand(cluster *Cluster, policy *BasePolicy, key *Key) (existsCommand, Error) {
31 | brc, err := newBaseReadCommand(cluster, policy, key)
32 | if err != nil {
33 | return existsCommand{}, err
34 | }
35 |
36 | return existsCommand{
37 | baseReadCommand: brc,
38 | }, nil
39 | }
40 |
41 | func (cmd *existsCommand) writeBuffer(ifc command) Error {
42 | return cmd.setExists(cmd.policy, cmd.key)
43 | }
44 |
45 | func (cmd *existsCommand) parseResult(ifc command, conn *Connection) Error {
46 | rp, err := newRecordParser(&cmd.baseCommand)
47 | if err != nil {
48 | return err
49 | }
50 |
51 | if err := rp.parseFields(cmd.policy.Txn, cmd.key, false); err != nil {
52 | return err
53 | }
54 |
55 | switch rp.resultCode {
56 | case types.OK:
57 | cmd.exists = true
58 | case types.KEY_NOT_FOUND_ERROR:
59 | cmd.exists = false
60 | case types.FILTERED_OUT:
61 | cmd.exists = true
62 | return ErrFilteredOut.err()
63 | default:
64 | return newError(rp.resultCode)
65 | }
66 |
67 | return nil
68 | }
69 |
70 | func (cmd *existsCommand) Exists() bool {
71 | return cmd.exists
72 | }
73 |
74 | func (cmd *existsCommand) Execute() Error {
75 | return cmd.execute(cmd)
76 | }
77 |
78 | func (cmd *existsCommand) commandType() commandType {
79 | return ttExists
80 | }
81 |
--------------------------------------------------------------------------------
/field_type.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // FieldType represents the type of the field in Aerospike Wire Protocol
18 | type FieldType int
19 |
20 | // FieldType constants used in the Aerospike Wire Protocol.
21 | const (
22 | NAMESPACE FieldType = 0
23 | TABLE FieldType = 1
24 | KEY FieldType = 2
25 | RECORD_VERSION FieldType = 3
26 | DIGEST_RIPE FieldType = 4
27 | MRT_ID FieldType = 5
28 | MRT_DEADLINE FieldType = 6
29 | QUERY_ID FieldType = 7
30 | SOCKET_TIMEOUT FieldType = 9
31 | RECORDS_PER_SECOND FieldType = 10
32 | PID_ARRAY FieldType = 11
33 | DIGEST_ARRAY FieldType = 12
34 | MAX_RECORDS FieldType = 13
35 | BVAL_ARRAY FieldType = 15
36 | INDEX_NAME FieldType = 21
37 | INDEX_RANGE FieldType = 22
38 | INDEX_CONTEXT FieldType = 23
39 | INDEX_TYPE FieldType = 26
40 | UDF_PACKAGE_NAME FieldType = 30
41 | UDF_FUNCTION FieldType = 31
42 | UDF_ARGLIST FieldType = 32
43 | UDF_OP FieldType = 33
44 | QUERY_BINLIST FieldType = 40
45 | BATCH_INDEX FieldType = 41
46 | BATCH_INDEX_WITH_SET FieldType = 42
47 | FILTER_EXP FieldType = 43
48 | )
49 |
--------------------------------------------------------------------------------
/generation_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // GenerationPolicy determines how to handle record writes based on record generation.
18 | type GenerationPolicy int
19 |
20 | const (
21 | // NONE means: Do not use record generation to restrict writes.
22 | NONE GenerationPolicy = iota
23 |
24 | // EXPECT_GEN_EQUAL means: Update/Delete record if expected generation is equal to server generation. Otherwise, fail.
25 | EXPECT_GEN_EQUAL
26 |
27 | // EXPECT_GEN_GT means: Update/Delete record if expected generation greater than the server generation. Otherwise, fail.
28 | // This is useful for restore after backup.
29 | EXPECT_GEN_GT
30 | )
31 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/aerospike/aerospike-client-go/v8
2 |
3 | go 1.23.0
4 |
5 | require (
6 | github.com/onsi/ginkgo/v2 v2.22.2
7 | github.com/onsi/gomega v1.36.2
8 | github.com/wadey/gocovmerge v0.0.0-20160331181800-b5bfa59ec0ad
9 | github.com/yuin/gopher-lua v1.1.1
10 | golang.org/x/sync v0.12.0
11 | )
12 |
13 | require (
14 | github.com/go-logr/logr v1.4.2 // indirect
15 | github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
16 | github.com/google/go-cmp v0.6.0 // indirect
17 | github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
18 | github.com/kr/pretty v0.3.1 // indirect
19 | github.com/stretchr/testify v1.10.0 // indirect
20 | golang.org/x/net v0.37.0 // indirect
21 | golang.org/x/sys v0.31.0 // indirect
22 | golang.org/x/text v0.23.0 // indirect
23 | golang.org/x/tools v0.31.0 // indirect
24 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
25 | gopkg.in/yaml.v3 v3.0.1 // indirect
26 | )
27 |
--------------------------------------------------------------------------------
/hll_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // HLLPolicy determines the HyperLogLog operation policy.
18 | type HLLPolicy struct {
19 | flags int
20 | }
21 |
22 | // DefaultHLLPolicy uses the default policy when performing HLL operations.
23 | func DefaultHLLPolicy() *HLLPolicy {
24 | return &HLLPolicy{HLLWriteFlagsDefault}
25 | }
26 |
27 | // NewHLLPolicy uses specified HLLWriteFlags when performing HLL operations.
28 | func NewHLLPolicy(flags int) *HLLPolicy {
29 | return &HLLPolicy{flags}
30 | }
31 |
--------------------------------------------------------------------------------
/hll_write_flags.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // HLLWriteFlags specifies the HLL write operation flags.
18 |
19 | const (
20 | // HLLWriteFlagsDefault is Default. Allow create or update.
21 | HLLWriteFlagsDefault = 0
22 |
23 | // HLLWriteFlagsCreateOnly behaves like the following:
24 | // If the bin already exists, the operation will be denied.
25 | // If the bin does not exist, a new bin will be created.
26 | HLLWriteFlagsCreateOnly = 1
27 |
28 | // HLLWriteFlagsUpdateOnly behaves like the following:
29 | // If the bin already exists, the bin will be overwritten.
30 | // If the bin does not exist, the operation will be denied.
31 | HLLWriteFlagsUpdateOnly = 2
32 |
33 | // HLLWriteFlagsNoFail does not raise error if operation is denied.
34 | HLLWriteFlagsNoFail = 4
35 |
36 | // HLLWriteFlagsAllowFold allows the resulting set to be the minimum of provided index bits.
37 | // Also, allow the usage of less precise HLL algorithms when minHash bits
38 | // of all participating sets do not match.
39 | HLLWriteFlagsAllowFold = 8
40 | )
41 |
--------------------------------------------------------------------------------
/host.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "fmt"
19 | "net"
20 | "strconv"
21 |
22 | "github.com/aerospike/aerospike-client-go/v8/types"
23 | )
24 |
25 | // Host name/port of database server.
26 | type Host struct {
27 |
28 | // Host name or IP address of database server.
29 | Name string
30 |
31 | //TLSName defines the TLS certificate name used for secure connections.
32 | TLSName string
33 |
34 | // Port of database server.
35 | Port int
36 | }
37 |
38 | // NewHost initializes new host instance.
39 | func NewHost(name string, port int) *Host {
40 | return &Host{Name: name, Port: port}
41 | }
42 |
43 | // Implements stringer interface
44 | func (h *Host) String() string {
45 | return net.JoinHostPort(h.Name, strconv.Itoa(h.Port))
46 | }
47 |
48 | // Implements stringer interface
49 | func (h *Host) equals(other *Host) bool {
50 | return h.Name == other.Name && h.Port == other.Port
51 | }
52 |
53 | // NewHosts initializes new host instances by a passed slice of addresses.
54 | func NewHosts(addresses ...string) ([]*Host, Error) {
55 | aerospikeHosts := make([]*Host, 0, len(addresses))
56 | for _, address := range addresses {
57 | hostStr, portStr, err := net.SplitHostPort(address)
58 | if err != nil {
59 | return nil, newErrorAndWrap(err, types.PARAMETER_ERROR, fmt.Sprintf("error parsing address %s: %s", address, err))
60 | }
61 | port, err := strconv.Atoi(portStr)
62 | if err != nil {
63 | return nil, newErrorAndWrap(err, types.PARAMETER_ERROR, fmt.Sprintf("error converting port %s: %s", address, err))
64 | }
65 |
66 | host := NewHost(hostStr, port)
67 | aerospikeHosts = append(aerospikeHosts, host)
68 | }
69 |
70 | return aerospikeHosts, nil
71 | }
72 |
--------------------------------------------------------------------------------
/host_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike_test
16 |
17 | import (
18 | as "github.com/aerospike/aerospike-client-go/v8"
19 |
20 | gg "github.com/onsi/ginkgo/v2"
21 | gm "github.com/onsi/gomega"
22 | )
23 |
24 | // ALL tests are isolated by SetName and Key, which are 50 random characters
25 | var _ = gg.Describe("Aerospike", func() {
26 |
27 | gg.Describe("Host", func() {
28 |
29 | gg.It("must handle multiple valid host strings", func() {
30 | // use the same client for all
31 | hosts, err := as.NewHosts("host1:4000", "host2:3000", "127.0.0.1:1200", "[2001:0db8:85a3:0000:0000:8a2e:0370]:7334")
32 | gm.Expect(err).ToNot(gm.HaveOccurred())
33 | gm.Expect(hosts).To(gm.Equal([]*as.Host{as.NewHost("host1", 4000), as.NewHost("host2", 3000), as.NewHost("127.0.0.1", 1200), as.NewHost("2001:0db8:85a3:0000:0000:8a2e:0370", 7334)}))
34 | })
35 |
36 | gg.It("must error on invalid host strings", func() {
37 | // use the same client for all
38 | hosts, err := as.NewHosts("host1:4000", "host2://+3000")
39 | gm.Expect(err).To(gm.HaveOccurred())
40 | gm.Expect(hosts).To(gm.BeNil())
41 | })
42 | })
43 | })
44 |
--------------------------------------------------------------------------------
/index_collection_type.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "fmt"
19 | )
20 |
21 | // IndexCollectionType is the secondary index collection type.
22 | type IndexCollectionType int
23 |
24 | const (
25 |
26 | // ICT_DEFAULT is the Normal scalar index.
27 | ICT_DEFAULT IndexCollectionType = iota
28 |
29 | // ICT_LIST is Index list elements.
30 | ICT_LIST
31 |
32 | // ICT_MAPKEYS is Index map keys.
33 | ICT_MAPKEYS
34 |
35 | // ICT_MAPVALUES is Index map values.
36 | ICT_MAPVALUES
37 | )
38 |
39 | func (ict IndexCollectionType) String() string {
40 | switch ict {
41 | // Normal scalar index.
42 | case ICT_DEFAULT:
43 | return "ICT_DEFAULT"
44 | // Index list elements.
45 | case ICT_LIST:
46 | return "ICT_LIST"
47 | // Index map keys.
48 | case ICT_MAPKEYS:
49 | return "ICT_MAPKEYS"
50 | // Index map values.
51 | case ICT_MAPVALUES:
52 | return "ICT_MAPVALUES"
53 | }
54 | panic(unreachable)
55 | }
56 |
57 | // ictToString converts IndexCollectionType to string representations
58 | func ictToString(ict IndexCollectionType) string {
59 | switch ict {
60 |
61 | case ICT_LIST:
62 | return "LIST"
63 |
64 | case ICT_MAPKEYS:
65 | return "MAPKEYS"
66 |
67 | case ICT_MAPVALUES:
68 | return "MAPVALUES"
69 |
70 | default:
71 | panic(fmt.Sprintf("Unknown IndexCollectionType value %v", ict))
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/index_type.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // IndexType the type of the secondary index.
18 | type IndexType string
19 |
20 | const (
21 | // NUMERIC specifies an index on numeric values.
22 | NUMERIC IndexType = "NUMERIC"
23 |
24 | // STRING specifies an index on string values.
25 | STRING IndexType = "STRING"
26 |
27 | // BLOB specifies a []byte index. Requires server version 7.0+.
28 | BLOB IndexType = "BLOB"
29 |
30 | // GEO2DSPHERE specifies 2-dimensional spherical geospatial index.
31 | GEO2DSPHERE IndexType = "GEO2DSPHERE"
32 | )
33 |
--------------------------------------------------------------------------------
/info_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "time"
19 | )
20 |
21 | // InfoPolicy contains attributes used for info commands.
22 | type InfoPolicy struct {
23 |
24 | // Info command socket timeout.
25 | // Default is 2 seconds.
26 | Timeout time.Duration
27 | }
28 |
29 | // NewInfoPolicy generates a new InfoPolicy with default values.
30 | func NewInfoPolicy() *InfoPolicy {
31 | return &InfoPolicy{
32 | Timeout: _DEFAULT_TIMEOUT,
33 | }
34 | }
35 |
36 | func (p *InfoPolicy) deadline() time.Time {
37 | var deadline time.Time
38 | if p != nil && p.Timeout > 0 {
39 | deadline = time.Now().Add(p.Timeout)
40 | }
41 |
42 | return deadline
43 | }
44 |
45 | func (p *InfoPolicy) timeout() time.Duration {
46 | if p != nil && p.Timeout > 0 {
47 | return p.Timeout
48 | }
49 |
50 | return _DEFAULT_TIMEOUT
51 | }
52 |
--------------------------------------------------------------------------------
/internal/atomic/array.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic
16 |
17 | import (
18 | "fmt"
19 | "sync"
20 | )
21 |
22 | // Array implement a fixed width array with atomic semantics
23 | type Array struct {
24 | items []interface{}
25 | length int
26 | mutex sync.RWMutex
27 | }
28 |
29 | // NewArray generates a new Array instance.
30 | func NewArray(length int) *Array {
31 | return &Array{
32 | length: length,
33 | items: make([]interface{}, length),
34 | }
35 | }
36 |
37 | // Get atomically retrieves an element from the Array.
38 | // If idx is out of range, it will return nil
39 | func (aa *Array) Get(idx int) interface{} {
40 | // do not lock if not needed
41 | if idx < 0 || idx >= aa.length {
42 | return nil
43 | }
44 |
45 | aa.mutex.RLock()
46 | res := aa.items[idx]
47 | aa.mutex.RUnlock()
48 | return res
49 | }
50 |
51 | // Set atomically sets an element in the Array.
52 | // If idx is out of range, it will return an error
53 | func (aa *Array) Set(idx int, node interface{}) error {
54 | // do not lock if not needed
55 | if idx < 0 || idx >= aa.length {
56 | return fmt.Errorf("index %d is larger than array size (%d)", idx, aa.length)
57 | }
58 |
59 | aa.mutex.Lock()
60 | aa.items[idx] = node
61 | aa.mutex.Unlock()
62 | return nil
63 | }
64 |
65 | // Length returns the array size.
66 | func (aa *Array) Length() int {
67 | aa.mutex.RLock()
68 | res := aa.length
69 | aa.mutex.RUnlock()
70 |
71 | return res
72 | }
73 |
--------------------------------------------------------------------------------
/internal/atomic/atomic_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic_test
16 |
17 | import (
18 | "testing"
19 |
20 | gg "github.com/onsi/ginkgo/v2"
21 | gm "github.com/onsi/gomega"
22 | )
23 |
24 | func TestAerospike(t *testing.T) {
25 | gm.RegisterFailHandler(gg.Fail)
26 | gg.RunSpecs(t, "Atomic Types Suite")
27 | }
28 |
--------------------------------------------------------------------------------
/internal/atomic/bool.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic
16 |
17 | import (
18 | "sync"
19 | )
20 |
21 | // Bool implements a synchronized boolean value
22 | type Bool struct {
23 | m sync.Mutex
24 | val bool
25 | }
26 |
27 | // NewBool generates a new Boolean instance.
28 | func NewBool(value bool) *Bool {
29 | return &Bool{
30 | val: value,
31 | }
32 | }
33 |
34 | // String implements the Stringer interface
35 | func (ab *Bool) String() string {
36 | res := ab.Get()
37 | if res {
38 | return "true"
39 | }
40 | return "false"
41 | }
42 |
43 | // GomegaString implements the GomegaStringer interface
44 | // to prevent race conditions in tests
45 | func (ab *Bool) GomegaString() string {
46 | return ab.String()
47 | }
48 |
49 | // Get atomically retrieves the boolean value.
50 | func (ab *Bool) Get() bool {
51 | ab.m.Lock()
52 | res := ab.val
53 | ab.m.Unlock()
54 | return res
55 | }
56 |
57 | // Set atomically sets the boolean value.
58 | func (ab *Bool) Set(newVal bool) {
59 | ab.m.Lock()
60 | ab.val = newVal
61 | ab.m.Unlock()
62 | }
63 |
64 | // Or atomically applies OR operation to the boolean value.
65 | func (ab *Bool) Or(newVal bool) bool {
66 | if !newVal {
67 | return ab.Get()
68 | }
69 | ab.Set(newVal)
70 | return true
71 | }
72 |
73 | // CompareAndToggle atomically sets the boolean value if the current value is equal to updated value.
74 | func (ab *Bool) CompareAndToggle(expect bool) bool {
75 | res := false
76 | ab.m.Lock()
77 | if ab.val == expect {
78 | res = true
79 | ab.val = !ab.val
80 | }
81 | ab.m.Unlock()
82 | return res
83 | }
84 |
--------------------------------------------------------------------------------
/internal/atomic/bool_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic_test
16 |
17 | import (
18 | "runtime"
19 | "sync"
20 |
21 | "github.com/aerospike/aerospike-client-go/v8/internal/atomic"
22 |
23 | gg "github.com/onsi/ginkgo/v2"
24 | gm "github.com/onsi/gomega"
25 | )
26 |
27 | var _ = gg.Describe("Atomic Bool", func() {
28 | // atomic tests require actual parallelism
29 | runtime.GOMAXPROCS(runtime.NumCPU())
30 |
31 | var ab *atomic.Bool
32 |
33 | gg.BeforeEach(func() {
34 | ab = atomic.NewBool(true)
35 | })
36 |
37 | gg.It("must CompareAndToggle correctly", func() {
38 | gm.Expect(ab.CompareAndToggle(true)).To(gm.BeTrue())
39 | gm.Expect(ab.CompareAndToggle(true)).To(gm.BeFalse())
40 | })
41 |
42 | gg.It("must CompareAndToggle correctly", func() {
43 | var count int = 1e5
44 | wg := new(sync.WaitGroup)
45 | wg.Add(count * 4)
46 | for i := 0; i < count; i++ {
47 | go func() {
48 | defer wg.Done()
49 | ab.Set(true)
50 | }()
51 | }
52 |
53 | for i := 0; i < count; i++ {
54 | go func() {
55 | defer wg.Done()
56 | ab.Set(false)
57 | }()
58 | }
59 |
60 | for i := 0; i < count; i++ {
61 | go func() {
62 | defer wg.Done()
63 | ab.Get()
64 | }()
65 | }
66 |
67 | for i := 0; i < count; i++ {
68 | go func(i int) {
69 | defer wg.Done()
70 | ab.CompareAndToggle(i%2 == 0)
71 | }(i)
72 | }
73 |
74 | wg.Wait()
75 | })
76 |
77 | })
78 |
--------------------------------------------------------------------------------
/internal/atomic/guard.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic
16 |
17 | import "sync"
18 |
19 | // Guard allows synchronized access to a value
20 | type Guard[T any] struct {
21 | val *T
22 | m sync.Mutex
23 | }
24 |
25 | // NewGuard creates a new instance of Guard
26 | func NewGuard[T any](val *T) *Guard[T] {
27 | return &Guard[T]{val: val}
28 | }
29 |
30 | // Do calls the passed closure.
31 | func (g *Guard[T]) Do(f func(*T)) {
32 | g.m.Lock()
33 | defer g.m.Unlock()
34 | f(g.val)
35 | }
36 |
37 | // DoVal calls the passed closure with a dereferenced internal value.
38 | func (g *Guard[T]) DoVal(f func(T)) {
39 | g.m.Lock()
40 | defer g.m.Unlock()
41 | f(*g.val)
42 | }
43 |
44 | // Call the passed closure allowing to replace the content.
45 | func (g *Guard[T]) Update(f func(**T)) {
46 | g.m.Lock()
47 | defer g.m.Unlock()
48 | f(&g.val)
49 | }
50 |
51 | // Calls the passed closure allowing to replace the content.
52 | // It will call the init func if the internal values is nil.
53 | func (g *Guard[T]) InitDo(init func() *T, f func(*T)) {
54 | g.m.Lock()
55 | defer g.m.Unlock()
56 | if g.val == nil {
57 | g.val = init()
58 | }
59 | f(g.val)
60 | }
61 |
62 | // Calls the passed closure allowing to replace the content.
63 | // It will call the init func if the internal values is nil.
64 | // It is used for reference values like slices and maps.
65 | func (g *Guard[T]) InitDoVal(init func() T, f func(T)) {
66 | g.m.Lock()
67 | defer g.m.Unlock()
68 | if g.val == nil {
69 | t := init()
70 | g.val = &t
71 | }
72 | f(*g.val)
73 | }
74 |
75 | // Release returns the internal value and sets it to nil
76 | func (g *Guard[T]) Release() *T {
77 | g.m.Lock()
78 | defer g.m.Unlock()
79 | res := g.val
80 | g.val = nil
81 | return res
82 | }
83 |
--------------------------------------------------------------------------------
/internal/atomic/int_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic_test
16 |
17 | import (
18 | "runtime"
19 | "sync"
20 |
21 | "github.com/aerospike/aerospike-client-go/v8/internal/atomic"
22 |
23 | gg "github.com/onsi/ginkgo/v2"
24 | gm "github.com/onsi/gomega"
25 | )
26 |
27 | var _ = gg.Describe("Atomic Int", func() {
28 | // atomic tests require actual parallelism
29 | runtime.GOMAXPROCS(runtime.NumCPU())
30 |
31 | var ai *atomic.Int
32 | wg := new(sync.WaitGroup)
33 |
34 | gg.BeforeEach(func() {
35 | ai = atomic.NewInt(0)
36 | })
37 |
38 | gg.It("must Offer() more elements than queue's capacity, and still not block", func() {
39 | var count int = 1e6
40 | wg.Add(count)
41 | for i := 0; i < count; i++ {
42 | go func() {
43 | defer wg.Done()
44 | ai.IncrementAndGet()
45 | }()
46 | }
47 |
48 | wg.Wait()
49 | gm.Expect(ai.Get()).To(gm.Equal(count))
50 | })
51 |
52 | })
53 |
--------------------------------------------------------------------------------
/internal/atomic/queue.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic
16 |
17 | import "sync"
18 |
19 | // Queue is a non-blocking FIFO queue.
20 | // If the queue is empty, nil is returned.
21 | // if the queue is full, offer will return false
22 | type Queue struct {
23 | head, tail uint32
24 | data []interface{}
25 | size uint32
26 | wrapped bool
27 | mutex sync.Mutex
28 | }
29 |
30 | // NewQueue creates a new queue with initial size.
31 | func NewQueue(size int) *Queue {
32 | if size <= 0 {
33 | panic("Queue size cannot be less than 1")
34 | }
35 |
36 | return &Queue{
37 | wrapped: false,
38 | data: make([]interface{}, uint32(size)),
39 | size: uint32(size),
40 | }
41 | }
42 |
43 | // Offer adds an item to the queue unless the queue is full.
44 | // In case the queue is full, the item will not be added to the queue
45 | // and false will be returned
46 | func (q *Queue) Offer(obj interface{}) bool {
47 | q.mutex.Lock()
48 |
49 | // make sure queue is not full
50 | if q.tail == q.head && q.wrapped {
51 | q.mutex.Unlock()
52 | return false
53 | }
54 |
55 | if q.head+1 == q.size {
56 | q.wrapped = true
57 | }
58 |
59 | q.head = (q.head + 1) % q.size
60 | q.data[q.head] = obj
61 | q.mutex.Unlock()
62 | return true
63 | }
64 |
65 | // Poll removes and returns an item from the queue.
66 | // If the queue is empty, nil will be returned.
67 | func (q *Queue) Poll() (res interface{}) {
68 | q.mutex.Lock()
69 |
70 | // if queue is not empty
71 | if q.wrapped || (q.tail != q.head) {
72 | if q.tail+1 == q.size {
73 | q.wrapped = false
74 | }
75 | q.tail = (q.tail + 1) % q.size
76 | res = q.data[q.tail]
77 | }
78 |
79 | q.mutex.Unlock()
80 | return res
81 | }
82 |
--------------------------------------------------------------------------------
/internal/atomic/queue_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package atomic_test
16 |
17 | import (
18 | "runtime"
19 |
20 | "github.com/aerospike/aerospike-client-go/v8/internal/atomic"
21 |
22 | gg "github.com/onsi/ginkgo/v2"
23 | gm "github.com/onsi/gomega"
24 | )
25 |
26 | type testStruct struct{ i int }
27 |
28 | var _ = gg.Describe("Atomic Queue", func() {
29 | // atomic tests require actual parallelism
30 | runtime.GOMAXPROCS(runtime.NumCPU())
31 |
32 | var qcap int
33 | var q *atomic.Queue
34 | var elem interface{}
35 |
36 | gg.BeforeEach(func() {
37 | qcap = 10
38 | q = atomic.NewQueue(qcap)
39 | })
40 |
41 | gg.It("must Offer() more elements than queue's capacity, and still not block", func() {
42 | for i := 0; i < 2*qcap; i++ {
43 | q.Offer(&testStruct{})
44 | }
45 | })
46 |
47 | gg.It("must Poll() more elements than queue's capacity, and still not block", func() {
48 | for i := 0; i < 2*qcap; i++ {
49 | elem = q.Poll()
50 | }
51 | gm.Expect(elem).To(gm.BeNil())
52 | })
53 |
54 | gg.It("must Offer() more elements than queue's capacity, and Poll() as many as capacity", func() {
55 | // test for many iterations
56 | for j := 0; j < 10; j++ {
57 | for i := 0; i < 2*qcap; i++ {
58 | q.Offer(&testStruct{i})
59 | }
60 |
61 | for i := 0; i < 2*qcap; i++ {
62 | obj := q.Poll()
63 | if i < qcap {
64 | gm.Expect(obj.(*testStruct).i).To(gm.Equal(i))
65 | } else {
66 | gm.Expect(obj).To(gm.BeNil())
67 | }
68 | }
69 | }
70 | })
71 |
72 | })
73 |
--------------------------------------------------------------------------------
/internal/atomic/sync_val.go:
--------------------------------------------------------------------------------
1 | package atomic
2 |
3 | import "sync"
4 |
5 | // SyncVal allows synchronized access to a value
6 | type SyncVal[T any] struct {
7 | val T
8 | lock sync.RWMutex
9 | }
10 |
11 | // NewSyncVal creates a new instance of SyncVal
12 | func NewSyncVal[T any](val T) *SyncVal[T] {
13 | return &SyncVal[T]{val: val}
14 | }
15 |
16 | // Set updates the value of SyncVal with the passed argument
17 | func (sv *SyncVal[T]) Set(val T) {
18 | sv.lock.Lock()
19 | sv.val = val
20 | sv.lock.Unlock()
21 | }
22 |
23 | // Get returns the value inside the SyncVal
24 | func (sv *SyncVal[T]) Get() T {
25 | sv.lock.RLock()
26 | val := sv.val
27 | sv.lock.RUnlock()
28 | return val
29 | }
30 |
31 | // GetSyncedVia returns the value returned by the function f.
32 | func (sv *SyncVal[T]) GetSyncedVia(f func(T) (T, error)) (T, error) {
33 | sv.lock.RLock()
34 | defer sv.lock.RUnlock()
35 |
36 | val, err := f(sv.val)
37 | return val, err
38 | }
39 |
40 | // Update gets a function and passes the value of SyncVal to it.
41 | // If the resulting err is nil, it will update the value of SyncVal.
42 | // It will return the resulting error to the caller.
43 | func (sv *SyncVal[T]) Update(f func(T) (T, error)) error {
44 | sv.lock.Lock()
45 | defer sv.lock.Unlock()
46 |
47 | val, err := f(sv.val)
48 | if err == nil {
49 | sv.val = val
50 | }
51 | return err
52 | }
53 |
54 | // MapSyncValue returns the value returned by the function f.
55 | func MapSyncValue[T any, U any](sv *SyncVal[T], f func(T) (U, error)) (U, error) {
56 | sv.lock.RLock()
57 | defer sv.lock.RUnlock()
58 |
59 | val, err := f(sv.val)
60 | return val, err
61 | }
62 |
--------------------------------------------------------------------------------
/internal/atomic/typed_val.go:
--------------------------------------------------------------------------------
1 | package atomic
2 |
3 | import "sync/atomic"
4 |
5 | // TypedVal allows synchronized access to a value
6 | type TypedVal[T any] atomic.Value
7 |
8 | // Set updates the value of TypedVal with the passed argument
9 | func (sv *TypedVal[T]) Set(val T) {
10 | (*atomic.Value)(sv).Store(&val)
11 | }
12 |
13 | // Get returns the value inside the TypedVal
14 | func (sv *TypedVal[T]) Get() T {
15 | res := (*atomic.Value)(sv).Load()
16 | if res != nil {
17 | return *res.(*T)
18 | }
19 |
20 | // return zero value; for pointers, it will be nil
21 | var t T
22 | return t
23 | }
24 |
--------------------------------------------------------------------------------
/internal/lua/instance.go:
--------------------------------------------------------------------------------
1 | //go:build !app_engine
2 | // +build !app_engine
3 |
4 | // Copyright 2014-2022 Aerospike, Inc.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | package lua
19 |
20 | import (
21 | luaLib "github.com/aerospike/aerospike-client-go/v8/internal/lua/resources"
22 | "github.com/aerospike/aerospike-client-go/v8/logger"
23 | "github.com/aerospike/aerospike-client-go/v8/types"
24 | lua "github.com/yuin/gopher-lua"
25 | )
26 |
27 | // SetPath sets the interpreter's current Lua Path
28 | func SetPath(lpath string) {
29 | lua.LuaPath = lpath
30 | }
31 |
32 | // Path returns the interpreter's current Lua Path
33 | func Path() string {
34 | return lua.LuaPath
35 | }
36 |
37 | // LuaPool is the global LState pool
38 | var LuaPool = types.NewPool(64)
39 |
40 | func newInstance(params ...interface{}) interface{} {
41 | L := lua.NewState()
42 |
43 | registerLuaAerospikeType(L)
44 | registerLuaStreamType(L)
45 | registerLuaListType(L)
46 | registerLuaMapType(L)
47 |
48 | if err := L.DoString(luaLib.LibStreamOps); err != nil {
49 | logger.Logger.Error(err.Error())
50 | return nil
51 | }
52 |
53 | if err := L.DoString(luaLib.LibAerospike); err != nil {
54 | logger.Logger.Error(err.Error())
55 | return nil
56 | }
57 |
58 | return L
59 | }
60 |
61 | func finalizeInstance(instance interface{}) {
62 | if instance != nil {
63 | instance.(*lua.LState).Close()
64 | }
65 | }
66 |
67 | func init() {
68 | LuaPool.New = newInstance
69 | LuaPool.Finalize = finalizeInstance
70 | }
71 |
--------------------------------------------------------------------------------
/internal/lua/lua_aerospike.go:
--------------------------------------------------------------------------------
1 | //go:build !app_engine
2 | // +build !app_engine
3 |
4 | // Copyright 2014-2022 Aerospike, Inc.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | package lua
19 |
20 | import (
21 | "github.com/aerospike/aerospike-client-go/v8/logger"
22 | lua "github.com/yuin/gopher-lua"
23 | )
24 |
25 | const luaLuaAerospikeTypeName = "LuaAerospike"
26 |
27 | // Registers my luaAerospike type to given L.
28 | func registerLuaAerospikeType(L *lua.LState) {
29 | mt := L.NewTypeMetatable(luaLuaAerospikeTypeName)
30 |
31 | L.SetGlobal("aerospike", mt)
32 |
33 | // static attributes
34 | L.SetField(mt, "log", L.NewFunction(luaAerospikeLog))
35 |
36 | L.SetMetatable(mt, mt)
37 | }
38 |
39 | func luaAerospikeLog(L *lua.LState) int {
40 | if L.GetTop() < 2 || L.GetTop() > 3 {
41 | L.ArgError(1, "2 arguments are expected for aerospike:log method")
42 | return 0
43 | }
44 |
45 | // account for calling it on a table
46 | paramIdx := 1
47 | if L.GetTop() == 3 {
48 | paramIdx = 2
49 | }
50 |
51 | level := L.CheckInt(paramIdx)
52 | str := L.CheckString(paramIdx + 1)
53 |
54 | switch level {
55 | case 1:
56 | logger.Logger.Warn(str)
57 | case 2:
58 | logger.Logger.Info(str)
59 | case 3, 4:
60 | logger.Logger.Debug(str)
61 | }
62 |
63 | return 0
64 | }
65 |
--------------------------------------------------------------------------------
/internal/lua/lua_aerospike_test.go:
--------------------------------------------------------------------------------
1 | //go:build !app_engine
2 | // +build !app_engine
3 |
4 | // Copyright 2014-2022 Aerospike, Inc.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | package lua_test
19 |
20 | import (
21 | lua "github.com/yuin/gopher-lua"
22 |
23 | gg "github.com/onsi/ginkgo/v2"
24 | gm "github.com/onsi/gomega"
25 |
26 | ilua "github.com/aerospike/aerospike-client-go/v8/internal/lua"
27 | )
28 |
29 | var _ = gg.Describe("Lua Aerospike API Test", func() {
30 |
31 | // code vs result
32 | testMatrix := map[string]interface{}{
33 | "aerospike.log(1, 'Warn')": nil,
34 | "warn('Warn %d', 1)": nil,
35 |
36 | "aerospike.log(2, 'Info')": nil,
37 | "info('Info %d', 2)": nil,
38 |
39 | "aerospike.log(3, 'Debug')": nil,
40 | "trace('Trace %d', 3)": nil,
41 |
42 | "aerospike.log(4, 'Debug')": nil,
43 | "debug('Debug %d', 4)": nil,
44 | }
45 |
46 | gg.It("must run all code blocks", func() {
47 | instance := ilua.LuaPool.Get().(*lua.LState)
48 | defer instance.Close()
49 | for source := range testMatrix {
50 | err := instance.DoString(source)
51 | gm.Expect(err).NotTo(gm.HaveOccurred())
52 | }
53 |
54 | })
55 |
56 | })
57 |
--------------------------------------------------------------------------------
/internal/lua/lua_suite_test.go:
--------------------------------------------------------------------------------
1 | //go:build !app_engine
2 | // +build !app_engine
3 |
4 | // Copyright 2014-2022 Aerospike, Inc.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | package lua_test
19 |
20 | import (
21 | "testing"
22 |
23 | gg "github.com/onsi/ginkgo/v2"
24 | gm "github.com/onsi/gomega"
25 | )
26 |
27 | func TestLua(t *testing.T) {
28 | gm.RegisterFailHandler(gg.Fail)
29 | gg.RunSpecs(t, "Lua Libs Test")
30 | }
31 |
--------------------------------------------------------------------------------
/internal/seq/seq.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package seq
16 |
17 | import (
18 | "errors"
19 | "sync"
20 | )
21 |
22 | var Break = errors.New("Break")
23 |
24 | func Do[T any](seq []T, f func(T) error) {
25 | for i := range seq {
26 | if err := f(seq[i]); err == Break {
27 | break
28 | }
29 | }
30 | }
31 |
32 | func ParDo[T any](seq []T, f func(T)) {
33 | if len(seq) == 0 {
34 | return
35 | }
36 |
37 | wg := new(sync.WaitGroup)
38 | wg.Add(len(seq))
39 | for i := range seq {
40 | go func(t T) {
41 | defer wg.Done()
42 | f(t)
43 | }(seq[i])
44 | }
45 | wg.Wait()
46 | }
47 |
48 | func Any[T any](seq []T, f func(T) bool) bool {
49 | for i := range seq {
50 | if f(seq[i]) {
51 | return true
52 | }
53 | }
54 | return false
55 | }
56 |
57 | func All[T any](seq []T, f func(T) bool) bool {
58 | if len(seq) == 0 {
59 | return false
60 | }
61 |
62 | for i := range seq {
63 | if !f(seq[i]) {
64 | return false
65 | }
66 | }
67 | return true
68 | }
69 |
70 | func Clone[T any](seq []T) []T {
71 | if seq == nil {
72 | return nil
73 | }
74 |
75 | if len(seq) == 0 {
76 | return []T{}
77 | }
78 |
79 | res := make([]T, len(seq))
80 | copy(res, seq)
81 | return res
82 | }
83 |
--------------------------------------------------------------------------------
/key_reflect_test.go:
--------------------------------------------------------------------------------
1 | //go:build !as_performance
2 |
3 | // Copyright 2014-2022 Aerospike, Inc.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package aerospike_test
18 |
19 | import (
20 | gg "github.com/onsi/ginkgo/v2"
21 | )
22 |
23 | // ALL tests are isolated by SetName and Key, which are 50 random characters
24 | var _ = gg.Describe("Key Test Reflection", func() {
25 |
26 | // gg.Context("Digests should be the same", func() {
27 |
28 | // gg.It("for Arrays", func() {
29 |
30 | // // The following two cases should be in exact order
31 | // key, _ := as.NewKey("namespace", "set", []int{1, 2, 3})
32 | // gm.Expect(hex.EncodeToString(key.Digest())).To(gm.Equal("a8b63a8208ebebb49d027d51899121fd0d03d2f7"))
33 |
34 | // keyInterfaceArrayOfTheSameValues, _ := as.NewKey("namespace", "set", []interface{}{1, 2, 3})
35 | // gm.Expect(hex.EncodeToString(keyInterfaceArrayOfTheSameValues.Digest())).To(gm.Equal(hex.EncodeToString(key.Digest())))
36 |
37 | // })
38 |
39 | // })
40 |
41 | })
42 |
--------------------------------------------------------------------------------
/language.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // Language specifies User defined function languages.
18 | type Language string
19 |
20 | const (
21 |
22 | // LUA embedded programming language.
23 | LUA Language = "LUA"
24 | )
25 |
--------------------------------------------------------------------------------
/metrics_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types/histogram"
19 | )
20 |
21 | // MetricsPolicy specifies client periodic metrics configuration.
22 | type MetricsPolicy struct {
23 | // Histogram type specifies if the histogram should be [histogram.Linear] or [histogram.Logarithmic].
24 | //
25 | // Default: [histogram.Logarithmic]
26 | HistogramType histogram.Type
27 |
28 | // LatencyColumns defines the number of elapsed time range buckets in latency histograms.
29 | //
30 | // Default: 24
31 | LatencyColumns int //= 24;
32 |
33 | // Depending on the type of histogram:
34 | //
35 | // For logarithmic histograms, the buckets are: =base^(columns-1)
36 | //
37 | // // LatencyColumns=5 latencyBase=8
38 | // <8µs <64µs <512µs <4096µs >=4096
39 | //
40 | // // LatencyColumns=7 LatencyBase=4
41 | // <4µs <16µs <64µs <256µs <1024µs <4096 >=4096µs
42 | //
43 | // For linear histograms, the buckets are: =base*(column-1)
44 | //
45 | // // LatencyColumns=5 latencyBase=15
46 | // <15µs <30µs <45µs <60µs >=60µs
47 | //
48 | // // LatencyColumns=7 LatencyBase=5
49 | // <5µs <10µs <15µs <20µs <25µs <30µs >=30µs
50 | //
51 | // Default: 2
52 | LatencyBase int //= 2;
53 | }
54 |
55 | func DefaultMetricsPolicy() *MetricsPolicy {
56 | return &MetricsPolicy{
57 | HistogramType: histogram.Logarithmic,
58 | LatencyColumns: 24,
59 | LatencyBase: 2,
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/operate_command_read.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | type operateCommandRead struct {
18 | readCommand
19 |
20 | args operateArgs
21 | }
22 |
23 | func newOperateCommandRead(cluster *Cluster, key *Key, args operateArgs) (operateCommandRead, Error) {
24 | rdCommand, err := newReadCommand(cluster, &args.writePolicy.BasePolicy, key, nil)
25 | if err != nil {
26 | return operateCommandRead{}, err
27 | }
28 |
29 | res := operateCommandRead{
30 | readCommand: rdCommand,
31 | args: args,
32 | }
33 |
34 | res.isOperation = true
35 |
36 | return res, nil
37 | }
38 |
39 | func (cmd *operateCommandRead) writeBuffer(ifc command) (err Error) {
40 | return cmd.setOperate(cmd.args.writePolicy, cmd.key, &cmd.args)
41 | }
42 |
43 | func (cmd *operateCommandRead) Execute() Error {
44 | return cmd.execute(cmd)
45 | }
46 |
47 | func (cmd *operateCommandRead) commandType() commandType {
48 | return ttOperate
49 | }
50 |
--------------------------------------------------------------------------------
/operate_command_write.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "github.com/aerospike/aerospike-client-go/v8/types"
18 |
19 | type operateCommandWrite struct {
20 | baseWriteCommand
21 |
22 | record *Record
23 | args operateArgs
24 | }
25 |
26 | func newOperateCommandWrite(cluster *Cluster, key *Key, args operateArgs) (operateCommandWrite, Error) {
27 | bwc, err := newBaseWriteCommand(cluster, args.writePolicy, key)
28 | if err != nil {
29 | return operateCommandWrite{}, err
30 | }
31 |
32 | return operateCommandWrite{
33 | baseWriteCommand: bwc,
34 | args: args,
35 | }, nil
36 | }
37 |
38 | func (cmd *operateCommandWrite) writeBuffer(ifc command) (err Error) {
39 | return cmd.setOperate(cmd.policy, cmd.key, &cmd.args)
40 | }
41 |
42 | func (cmd *operateCommandWrite) parseResult(ifc command, conn *Connection) Error {
43 | rp, err := newRecordParser(&cmd.baseCommand)
44 | if err != nil {
45 | return err
46 | }
47 |
48 | if err := rp.parseFields(cmd.policy.Txn, cmd.key, true); err != nil {
49 | return err
50 | }
51 |
52 | switch rp.resultCode {
53 | case types.OK:
54 | var err Error
55 | cmd.record, err = rp.parseRecord(cmd.key, true)
56 | if err != nil {
57 | return err
58 | }
59 | return nil
60 | case types.KEY_NOT_FOUND_ERROR:
61 | return ErrKeyNotFound.err()
62 | case types.FILTERED_OUT:
63 | return ErrFilteredOut.err()
64 | default:
65 | return newError(rp.resultCode)
66 | }
67 | }
68 |
69 | func (cmd *operateCommandWrite) Execute() Error {
70 | return cmd.execute(cmd)
71 | }
72 |
73 | func (cmd *operateCommandWrite) commandType() commandType {
74 | return ttOperate
75 | }
76 |
77 | func (cmd *operateCommandWrite) GetRecord() *Record {
78 | return cmd.record
79 | }
80 |
--------------------------------------------------------------------------------
/partition_status.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Portions may be licensed to Aerospike, Inc. under one or more contributor
4 | // license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
7 | // use this file except in compliance with the License. You may obtain a copy of
8 | // the License at http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | // License for the specific language governing permissions and limitations under
14 | // the License.
15 |
16 | package aerospike
17 |
18 | import (
19 | "fmt"
20 | )
21 |
22 | // PartitionStatus encapsulates the pagination status in partitions.
23 | type PartitionStatus struct {
24 | // BVal
25 | BVal int64
26 | // Id shows the partition Id.
27 | Id int
28 | // Retry signifies if the partition requires a retry.
29 | Retry bool
30 | // Digest records the digest of the last key digest received from the server
31 | // for this partition.
32 | Digest []byte
33 |
34 | // the following fields are transient
35 | node *Node
36 | sequence int
37 | }
38 |
39 | func newPartitionStatus(id int) *PartitionStatus {
40 | return &PartitionStatus{Id: id, Retry: true}
41 | }
42 |
43 | func (ps *PartitionStatus) String() string {
44 | r := 'F'
45 | if ps.Retry {
46 | r = 'T'
47 | }
48 | return fmt.Sprintf("%04d:%c", ps.Id, r)
49 | }
50 |
--------------------------------------------------------------------------------
/pkg/bcrypt/.gitignore:
--------------------------------------------------------------------------------
1 | 6.out
2 | *.6
3 | _obj
4 | _test
5 | _testmain.go
6 |
--------------------------------------------------------------------------------
/pkg/bcrypt/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 James Keane . All rights reserved.
2 | Copyright (c) 2006 Damien Miller .
3 | Copyright (c) 2011 ZooWar.com, All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are
7 | met:
8 |
9 | * Redistributions of source code must retain the above copyright
10 | notice, this list of conditions and the following disclaimer.
11 | * Redistributions in binary form must reproduce the above
12 | copyright notice, this list of conditions and the following disclaimer
13 | in the documentation and/or other materials provided with the
14 | distribution.
15 | * Neither the name of weekendlogic nor the names of its
16 | contributors may be used to endorse or promote products derived from
17 | this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/pkg/bcrypt/README:
--------------------------------------------------------------------------------
1 | Installation:
2 | goinstall github.com/jameskeane/bcrypt
3 |
4 | Example use:
5 | package main
6 |
7 | import (
8 | "fmt"
9 | "github.com/jameskeane/bcrypt"
10 | )
11 |
12 | var password = "WyWihatdyd?frub1"
13 | var bad_password = "just a wild guess"
14 |
15 | func main() {
16 | // generate a random salt with default rounds of complexity
17 | salt, _ := bcrypt.Salt()
18 |
19 | // generate a random salt with 10 rounds of complexity
20 | salt, _ = bcrypt.Salt(10)
21 |
22 | // hash and verify a password with random salt
23 | hash, _ := bcrypt.Hash(password)
24 | if bcrypt.Match(password, hash) {
25 | fmt.Println("They match")
26 | }
27 |
28 | // hash and verify a password with a static salt
29 | hash, _ = bcrypt.Hash(password, salt)
30 | if bcrypt.Match(password, hash) {
31 | fmt.Println("They match")
32 | }
33 |
34 | // verify a random password fails to match the hashed password
35 | if !bcrypt.Match(bad_password, hash) {
36 | fmt.Println("They don't match")
37 | }
38 | }
39 |
40 | Todo:
41 | grep 'TODO' * -r
42 |
43 | Notes:
44 | * This library is derived from jBcrypt by Damien Miller
45 | * bcrypt_test.go is from ZooWar.com
46 |
47 |
--------------------------------------------------------------------------------
/pkg/ripemd160/ripemd160_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2010 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ripemd160
6 |
7 | // Test vectors are from:
8 | // http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
9 |
10 | import (
11 | "fmt"
12 | "io"
13 | "testing"
14 | )
15 |
16 | type mdTest struct {
17 | out string
18 | in string
19 | }
20 |
21 | var vectors = [...]mdTest{
22 | {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""},
23 | {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"},
24 | {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"},
25 | {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"},
26 | {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"},
27 | {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
28 | {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
29 | {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
30 | }
31 |
32 | func TestVectors(t *testing.T) {
33 | for i := 0; i < len(vectors); i++ {
34 | tv := vectors[i]
35 | md := New()
36 | for j := 0; j < 3; j++ {
37 | if j < 2 {
38 | io.WriteString(md, tv.in)
39 | } else {
40 | io.WriteString(md, tv.in[0:len(tv.in)/2])
41 | // md.Sum(nil) // removed due to our changes in the code; we use only one Sum() and then reset
42 | io.WriteString(md, tv.in[len(tv.in)/2:])
43 | }
44 | s := fmt.Sprintf("%x", md.Sum(nil))
45 | if s != tv.out {
46 | t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out)
47 | }
48 | md.Reset()
49 | }
50 | }
51 | }
52 |
53 | func TestMillionA(t *testing.T) {
54 | md := New()
55 | for i := 0; i < 100000; i++ {
56 | io.WriteString(md, "aaaaaaaaaa")
57 | }
58 | out := "52783243c1697bdbe16d37f97f68f08325dc1528"
59 | s := fmt.Sprintf("%x", md.Sum(nil))
60 | if s != out {
61 | t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out)
62 | }
63 | md.Reset()
64 | }
65 |
--------------------------------------------------------------------------------
/query_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | type queryCommand struct {
18 | baseMultiCommand
19 |
20 | policy *QueryPolicy
21 | writePolicy *WritePolicy
22 | statement *Statement
23 | operations []*Operation
24 | }
25 |
26 | func newQueryCommand(node *Node, policy *QueryPolicy, writePolicy *WritePolicy, statement *Statement, operations []*Operation, recordset *Recordset) *queryCommand {
27 | res := &queryCommand{
28 | baseMultiCommand: *newStreamingMultiCommand(node, recordset, statement.Namespace, false),
29 | policy: policy,
30 | writePolicy: writePolicy,
31 | statement: statement,
32 | operations: operations,
33 | }
34 | res.rawCDT = policy.RawCDT
35 |
36 | return res
37 | }
38 |
39 | func (cmd *queryCommand) getPolicy(ifc command) Policy {
40 | return cmd.policy
41 | }
42 |
43 | func (cmd *queryCommand) writeBuffer(ifc command) (err Error) {
44 | return cmd.setQuery(cmd.policy, cmd.writePolicy, cmd.statement, cmd.recordset.TaskId(), cmd.operations, cmd.writePolicy != nil, nil)
45 | }
46 |
47 | func (cmd *queryCommand) parseResult(ifc command, conn *Connection) Error {
48 | return cmd.baseMultiCommand.parseResult(ifc, conn)
49 | }
50 |
51 | func (cmd *queryCommand) commandType() commandType {
52 | return ttQuery
53 | }
54 |
55 | // Execute will run the query.
56 | func (cmd *queryCommand) Execute() Error {
57 | err := cmd.execute(cmd)
58 | if err != nil {
59 | cmd.recordset.sendError(err)
60 | }
61 | return err
62 | }
63 |
--------------------------------------------------------------------------------
/query_duration.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package aerospike
19 |
20 | // QueryDuration defines the expected query duration. The server treats the query in different ways depending on the expected duration.
21 | // This enum is ignored for aggregation queries, background queries and server versions < 6.0.
22 | type QueryDuration int
23 |
24 | const (
25 | // LONG specifies that the query is expected to return more than 100 records per node. The server optimizes for a large record set in
26 | // the following ways:
27 | //
28 | // Allow query to be run in multiple threads using the server's query threading configuration.
29 | // Do not relax read consistency for AP namespaces.
30 | // Add the query to the server's query monitor.
31 | // Do not add the overall latency to the server's latency histogram.
32 | // Do not allow server timeouts.
33 | LONG = iota
34 |
35 | // Short specifies that the query is expected to return less than 100 records per node. The server optimizes for a small record set in
36 | // the following ways:
37 | // Always run the query in one thread and ignore the server's query threading configuration.
38 | // Allow query to be inlined directly on the server's service thread.
39 | // Relax read consistency for AP namespaces.
40 | // Do not add the query to the server's query monitor.
41 | // Add the overall latency to the server's latency histogram.
42 | // Allow server timeouts. The default server timeout for a short query is 1 second.
43 | SHORT
44 |
45 | // LONG_RELAX_AP will treat query as a LONG query, but relax read consistency for AP namespaces.
46 | // This value is treated exactly like LONG for server versions < 7.1.
47 | LONG_RELAX_AP
48 | )
49 |
--------------------------------------------------------------------------------
/query_executor.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "time"
19 | )
20 |
21 | func (clnt *Client) queryPartitions(policy *QueryPolicy, tracker *partitionTracker, statement *Statement, recordset *Recordset) {
22 | defer recordset.signalEnd()
23 |
24 | // for exponential backoff
25 | interval := policy.SleepBetweenRetries
26 |
27 | var errs Error
28 | for {
29 | list, err := tracker.assignPartitionsToNodes(clnt.Cluster(), statement.Namespace)
30 | if err != nil {
31 | errs = chainErrors(err, errs)
32 | recordset.sendError(errs)
33 | tracker.partitionError()
34 | return
35 | }
36 |
37 | maxConcurrentNodes := policy.MaxConcurrentNodes
38 | if maxConcurrentNodes <= 0 {
39 | maxConcurrentNodes = len(list)
40 | }
41 |
42 | if recordset.IsActive() {
43 | weg := newWeightedErrGroup(maxConcurrentNodes)
44 | for _, nodePartition := range list {
45 | cmd := newQueryPartitionCommand(policy, tracker, nodePartition, statement, recordset)
46 | weg.execute(cmd)
47 | }
48 | errs = chainErrors(weg.wait(), errs)
49 | }
50 |
51 | done, err := tracker.isClusterComplete(clnt.Cluster(), &policy.BasePolicy)
52 | if !recordset.IsActive() || done || err != nil {
53 | errs = chainErrors(err, errs)
54 | // Query is complete.
55 | if errs != nil {
56 | tracker.partitionError()
57 | recordset.sendError(errs)
58 | }
59 | return
60 | }
61 |
62 | if policy.SleepBetweenRetries > 0 {
63 | // Sleep before trying again.
64 | time.Sleep(interval)
65 |
66 | if policy.SleepMultiplier > 1 {
67 | interval = time.Duration(float64(interval) * policy.SleepMultiplier)
68 | }
69 | }
70 |
71 | recordset.resetTaskID()
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/query_partition_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | type queryPartitionCommand queryCommand
18 |
19 | func newQueryPartitionCommand(
20 | policy *QueryPolicy,
21 | tracker *partitionTracker,
22 | nodePartitions *nodePartitions,
23 | statement *Statement,
24 | recordset *Recordset,
25 | ) *queryPartitionCommand {
26 | cmd := &queryPartitionCommand{
27 | baseMultiCommand: *newCorrectStreamingMultiCommand(recordset, statement.Namespace),
28 | policy: policy,
29 | writePolicy: nil,
30 | statement: statement,
31 | operations: nil,
32 | }
33 | cmd.rawCDT = policy.RawCDT
34 | cmd.terminationErrorType = statement.terminationError()
35 | cmd.tracker = tracker
36 | cmd.nodePartitions = nodePartitions
37 | cmd.node = nodePartitions.node
38 |
39 | return cmd
40 | }
41 |
42 | func (cmd *queryPartitionCommand) getPolicy(ifc command) Policy {
43 | return cmd.policy
44 | }
45 |
46 | func (cmd *queryPartitionCommand) writeBuffer(ifc command) Error {
47 | return cmd.setQuery(cmd.policy, cmd.writePolicy, cmd.statement, cmd.recordset.TaskId(), cmd.operations, cmd.writePolicy != nil, cmd.nodePartitions)
48 | }
49 |
50 | func (cmd *queryPartitionCommand) shouldRetry(e Error) bool {
51 | return cmd.tracker != nil && cmd.tracker.shouldRetry(cmd.nodePartitions, e)
52 | }
53 |
54 | func (cmd *queryPartitionCommand) commandType() commandType {
55 | return ttQuery
56 | }
57 |
58 | func (cmd *queryPartitionCommand) Execute() Error {
59 | err := cmd.execute(cmd)
60 | if err != nil {
61 | // signal to the executor that no retries should be attempted
62 | // don't send error unless no retries are planned
63 | if !cmd.shouldRetry(err) {
64 | cmd.recordset.sendError(err)
65 | }
66 | }
67 | return err
68 | }
69 |
--------------------------------------------------------------------------------
/query_partitiopn_objects_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | type queryPartitionObjectsCommand queryCommand
18 |
19 | func newQueryPartitionObjectsCommand(
20 | policy *QueryPolicy,
21 | tracker *partitionTracker,
22 | nodePartitions *nodePartitions,
23 | statement *Statement,
24 | recordset *Recordset,
25 | ) *queryPartitionObjectsCommand {
26 | cmd := &queryPartitionObjectsCommand{
27 | baseMultiCommand: *newCorrectStreamingMultiCommand(recordset, statement.Namespace),
28 | policy: policy,
29 | writePolicy: nil,
30 | statement: statement,
31 | operations: nil,
32 | }
33 | cmd.terminationErrorType = statement.terminationError()
34 | cmd.tracker = tracker
35 | cmd.nodePartitions = nodePartitions
36 | cmd.node = nodePartitions.node
37 |
38 | return cmd
39 | }
40 |
41 | func (cmd *queryPartitionObjectsCommand) getPolicy(ifc command) Policy {
42 | return cmd.policy
43 | }
44 |
45 | func (cmd *queryPartitionObjectsCommand) writeBuffer(ifc command) Error {
46 | return cmd.setQuery(cmd.policy, cmd.writePolicy, cmd.statement, cmd.recordset.TaskId(), cmd.operations, cmd.writePolicy != nil, cmd.nodePartitions)
47 | }
48 |
49 | func (cmd *queryPartitionObjectsCommand) shouldRetry(e Error) bool {
50 | return cmd.tracker != nil && cmd.tracker.shouldRetry(cmd.nodePartitions, e)
51 | }
52 |
53 | func (cmd *queryPartitionObjectsCommand) commandType() commandType {
54 | return ttQuery
55 | }
56 |
57 | func (cmd *queryPartitionObjectsCommand) Execute() Error {
58 | err := cmd.execute(cmd)
59 | if err != nil {
60 | // signal to the executor that no retries should be attempted
61 | // don't send error unless no retries are planned
62 | if !cmd.shouldRetry(err) {
63 | cmd.recordset.sendError(err)
64 | }
65 | }
66 | return err
67 | }
68 |
--------------------------------------------------------------------------------
/read_header_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | type readHeaderCommand struct {
22 | baseReadCommand
23 | }
24 |
25 | func newReadHeaderCommand(cluster *Cluster, policy *BasePolicy, key *Key) (readHeaderCommand, Error) {
26 | brc, err := newBaseReadCommand(cluster, policy, key)
27 | if err != nil {
28 | return readHeaderCommand{}, err
29 | }
30 |
31 | newReadHeaderCmd := readHeaderCommand{
32 | baseReadCommand: brc,
33 | }
34 |
35 | return newReadHeaderCmd, nil
36 | }
37 |
38 | func (cmd *readHeaderCommand) writeBuffer(ifc command) Error {
39 | return cmd.setReadHeader(cmd.policy, cmd.key)
40 | }
41 |
42 | func (cmd *readHeaderCommand) parseResult(ifc command, conn *Connection) Error {
43 | rp, err := newRecordParser(&cmd.baseCommand)
44 | if err != nil {
45 | return err
46 | }
47 |
48 | if err := rp.parseFields(cmd.policy.Txn, cmd.key, false); err != nil {
49 | return err
50 | }
51 |
52 | if rp.resultCode == 0 {
53 | cmd.record = newRecord(cmd.node, cmd.key, nil, rp.generation, rp.expiration)
54 | } else {
55 | switch rp.resultCode {
56 | case types.KEY_NOT_FOUND_ERROR:
57 | cmd.record = nil
58 | case types.FILTERED_OUT:
59 | return ErrFilteredOut.err()
60 | default:
61 | return newError(rp.resultCode)
62 | }
63 | }
64 | return nil
65 | }
66 |
67 | func (cmd *readHeaderCommand) GetRecord() *Record {
68 | return cmd.record
69 | }
70 |
71 | func (cmd *readHeaderCommand) Execute() Error {
72 | return cmd.execute(cmd)
73 | }
74 |
75 | func (cmd *readHeaderCommand) commandType() commandType {
76 | return ttGetHeader
77 | }
78 |
--------------------------------------------------------------------------------
/read_mode_ap.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package aerospike
19 |
20 | // ReadModeAP is the read policy in AP (availability) mode namespaces.
21 | // It indicates how duplicates should be consulted in a read operation.
22 | // Only makes a difference during migrations and only applicable in AP mode.
23 | type ReadModeAP int
24 |
25 | const (
26 | // ReadModeAPOne indicates that a single node should be involved in the read operation.
27 | ReadModeAPOne ReadModeAP = iota
28 |
29 | // ReadModeAPAll indicates that all duplicates should be consulted in
30 | // the read operation.
31 | ReadModeAPAll
32 | )
33 |
--------------------------------------------------------------------------------
/read_mode_sc.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package aerospike
19 |
20 | // ReadModeSC is the read policy in SC (strong consistency) mode namespaces.
21 | // Determines SC read consistency options.
22 | type ReadModeSC int
23 |
24 | const (
25 | // ReadModeSCSession ensures this client will only see an increasing sequence of record versions.
26 | // Client only reads from master. This is the default.
27 | ReadModeSCSession ReadModeSC = iota
28 |
29 | // ReadModeSCLinearize ensures all clients will only see an increasing sequence of record versions.
30 | // Client only reads from master.
31 | ReadModeSCLinearize
32 |
33 | // ReadModeSCAllowReplica indicates that the client may read from master or any full (non-migrating) replica.
34 | // Increasing sequence of record versions is not guaranteed.
35 | ReadModeSCAllowReplica
36 |
37 | // ReadModeSCAllowUnavailable indicates that the client may read from master or any full (non-migrating) replica or from unavailable
38 | // partitions. Increasing sequence of record versions is not guaranteed.
39 | ReadModeSCAllowUnavailable
40 | )
41 |
--------------------------------------------------------------------------------
/record.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "fmt"
18 |
19 | // Record is the container struct for database records.
20 | // Records are equivalent to rows.
21 | type Record struct {
22 | // Key is the record's key.
23 | // Might be empty, or may only consist of digest value.
24 | Key *Key
25 |
26 | // Node from which the Record is originating from.
27 | Node *Node
28 |
29 | // Bins is the map of requested name/value bins.
30 | Bins BinMap
31 |
32 | // Generation shows record modification count.
33 | Generation uint32
34 |
35 | // Expiration is TTL (Time-To-Live).
36 | // Number of seconds until record expires.
37 | Expiration uint32
38 | }
39 |
40 | func newRecord(node *Node, key *Key, bins BinMap, generation, expiration uint32) *Record {
41 | r := &Record{
42 | Node: node,
43 | Key: key,
44 | Bins: bins,
45 | Generation: generation,
46 | Expiration: expiration,
47 | }
48 |
49 | // always assign a map of length zero if Bins is nil
50 | if r.Bins == nil {
51 | r.Bins = make(BinMap)
52 | }
53 |
54 | return r
55 | }
56 |
57 | // String implements the Stringer interface.
58 | // Returns string representation of record.
59 | func (rc *Record) String() string {
60 | return fmt.Sprintf("%s %v", rc.Key, rc.Bins)
61 | }
62 |
63 | // udfError returns the the error string returned by a UDF execute in a batch.
64 | // Returns nil if an error did not occur.
65 | func (rc *Record) udfError() string {
66 | return rc.Bins["FAILURE"].(string)
67 | }
68 |
69 | // udfResult returns the value returned by a UDF execute in a batch.
70 | // The result may be nil.
71 | func (rc *Record) udfResult() BinMap {
72 | return BinMap(rc.Bins["SUCCESS"].(map[string]interface{}))
73 | }
74 |
--------------------------------------------------------------------------------
/record_exists_action.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // RecordExistsAction determines how to handle writes when
18 | // the record already exists.
19 | type RecordExistsAction int
20 |
21 | const (
22 |
23 | // UPDATE means: Create or update record.
24 | // Merge write command bins with existing bins.
25 | UPDATE RecordExistsAction = iota
26 |
27 | // UPDATE_ONLY means: Update record only. Fail if record does not exist.
28 | // Merge write command bins with existing bins.
29 | UPDATE_ONLY
30 |
31 | // REPLACE means: Create or replace record.
32 | // Delete existing bins not referenced by write command bins.
33 | // Supported by Aerospike 2 server versions >= 2.7.5 and
34 | // Aerospike 3 server versions >= 3.1.6 and later.
35 | REPLACE
36 |
37 | // REPLACE_ONLY means: Replace record only. Fail if record does not exist.
38 | // Delete existing bins not referenced by write command bins.
39 | // Supported by Aerospike 2 server versions >= 2.7.5 and
40 | // Aerospike 3 server versions >= 3.1.6 and later.
41 | REPLACE_ONLY
42 |
43 | // CREATE_ONLY means: Create only. Fail if record exists.
44 | CREATE_ONLY
45 | )
46 |
--------------------------------------------------------------------------------
/recordset_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "time"
19 |
20 | "github.com/aerospike/aerospike-client-go/v8/types"
21 |
22 | gg "github.com/onsi/ginkgo/v2"
23 | gm "github.com/onsi/gomega"
24 | )
25 |
26 | // ALL tests are isolated by SetName and Key, which are 50 random characters
27 | var _ = gg.Describe("Recordset test", func() {
28 |
29 | gg.It("must avoid panic on sendError", func() {
30 | rs := newRecordset(100, 1)
31 |
32 | rs.sendError(newError(types.PARAMETER_ERROR, "Error"))
33 | rs.wgGoroutines.Done()
34 | rs.Close()
35 | rs.sendError(newError(types.PARAMETER_ERROR, "Error"))
36 |
37 | timeout := time.After(time.Second)
38 | select {
39 | case res := <-rs.Results():
40 | gm.Expect(res).ToNot(gm.BeNil())
41 | case <-timeout:
42 | panic("wrong result!")
43 | }
44 | })
45 |
46 | })
47 |
--------------------------------------------------------------------------------
/replica_policy.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2022 Aerospike, Inc.
3 | *
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 | * license agreements.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 | * use this file except in compliance with the License. You may obtain a copy of
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package aerospike
19 |
20 | // ReplicaPolicy defines type of node partition targeted by read commands.
21 | type ReplicaPolicy int
22 |
23 | const (
24 | // MASTER reads from node containing key's master partition.
25 | // This is the default behavior.
26 | MASTER ReplicaPolicy = iota
27 |
28 | // MASTER_PROLES Distributes reads across nodes containing key's master and replicated partitions
29 | // in round-robin fashion.
30 | MASTER_PROLES
31 |
32 | // RANDOM Distribute reads across all nodes in cluster in round-robin fashion.
33 | // This option is useful when the replication factor equals the number
34 | // of nodes in the cluster and the overhead of requesting proles is not desired.
35 | RANDOM
36 |
37 | // SEQUENCE Tries node containing master partition first.
38 | // If connection fails, all commands try nodes containing replicated partitions.
39 | // If socketTimeout is reached, reads also try nodes containing replicated partitions,
40 | // but writes remain on master node.
41 | SEQUENCE
42 |
43 | // PREFER_RACK Tries nodes on the same rack first.
44 | //
45 | // This option requires ClientPolicy.Rackaware to be enabled
46 | // in order to function properly.
47 | PREFER_RACK
48 | )
49 |
--------------------------------------------------------------------------------
/role.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Portions may be licensed to Aerospike, Inc. under one or more contributor
4 | // license agreements.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
7 | // use this file except in compliance with the License. You may obtain a copy of
8 | // the License at http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | // License for the specific language governing permissions and limitations under
14 | // the License.
15 |
16 | package aerospike
17 |
18 | // Role allows granular access to database entities for users.
19 | type Role struct {
20 | // Name is role name
21 | Name string
22 |
23 | // Privilege is the list of assigned privileges
24 | Privileges []Privilege
25 |
26 | // While is the list of allowable IP addresses
27 | Whitelist []string
28 |
29 | // ReadQuota is the maximum reads per second limit for the role
30 | ReadQuota uint32
31 |
32 | // WriteQuota is the maximum writes per second limit for the role
33 | WriteQuota uint32
34 | }
35 |
36 | // Pre-defined user roles.
37 | const (
38 | // UserAdmin allows to manages users and their roles.
39 | UserAdmin privilegeCode = "user-admin"
40 |
41 | // SysAdmin allows to manage indexes, user defined functions and server configuration.
42 | SysAdmin privilegeCode = "sys-admin"
43 |
44 | // DataAdmin allows to manage indicies and user defined functions.
45 | DataAdmin privilegeCode = "data-admin"
46 |
47 | // UDFAdmin allows to manage user defined functions.
48 | UDFAdmin privilegeCode = "udf-admin"
49 |
50 | // SIndexAdmin allows to manage indicies.
51 | SIndexAdmin privilegeCode = "sindex-admin"
52 |
53 | // ReadWriteUDF allows read, write and UDF transactions with the database.
54 | ReadWriteUDF privilegeCode = "read-write-udf"
55 |
56 | // ReadWrite allows read and write transactions with the database.
57 | ReadWrite privilegeCode = "read-write"
58 |
59 | // Read allows read transactions with the database.
60 | Read privilegeCode = "read"
61 |
62 | // Write allows write transactions with the database.
63 | Write privilegeCode = "write"
64 |
65 | // Truncate allow issuing truncate commands.
66 | Truncate privilegeCode = "truncate"
67 | )
68 |
--------------------------------------------------------------------------------
/scan_executor.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "time"
19 | )
20 |
21 | func (clnt *Client) scanPartitions(policy *ScanPolicy, tracker *partitionTracker, namespace string, setName string, recordset *Recordset, binNames ...string) {
22 | defer recordset.signalEnd()
23 |
24 | // for exponential backoff
25 | interval := policy.SleepBetweenRetries
26 |
27 | var errs Error
28 | for {
29 | list, err := tracker.assignPartitionsToNodes(clnt.Cluster(), namespace)
30 | if err != nil {
31 | errs = chainErrors(err, errs)
32 | recordset.sendError(errs)
33 | tracker.partitionError()
34 | return
35 | }
36 |
37 | maxConcurrentNodes := policy.MaxConcurrentNodes
38 | if maxConcurrentNodes <= 0 {
39 | maxConcurrentNodes = len(list)
40 | }
41 |
42 | if recordset.IsActive() {
43 | weg := newWeightedErrGroup(maxConcurrentNodes)
44 | for _, nodePartition := range list {
45 | cmd := newScanPartitionCommand(policy, tracker, nodePartition, namespace, setName, binNames, recordset)
46 | weg.execute(cmd)
47 | }
48 | errs = chainErrors(weg.wait(), errs)
49 | }
50 |
51 | if done, err := tracker.isClusterComplete(clnt.Cluster(), &policy.BasePolicy); !recordset.IsActive() || done || err != nil {
52 | errs = chainErrors(err, errs)
53 | // Scan is complete.
54 | if errs != nil {
55 | tracker.partitionError()
56 | recordset.sendError(errs)
57 | }
58 | return
59 | }
60 |
61 | if policy.SleepBetweenRetries > 0 {
62 | // Sleep before trying again.
63 | time.Sleep(interval)
64 |
65 | if policy.SleepMultiplier > 1 {
66 | interval = time.Duration(float64(interval) * policy.SleepMultiplier)
67 | }
68 | }
69 |
70 | recordset.resetTaskID()
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/scan_partition_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "github.com/aerospike/aerospike-client-go/v8/types"
18 |
19 | type scanPartitionCommand struct {
20 | baseMultiCommand
21 |
22 | policy *ScanPolicy
23 | namespace string
24 | setName string
25 | binNames []string
26 | }
27 |
28 | func newScanPartitionCommand(
29 | policy *ScanPolicy,
30 | tracker *partitionTracker,
31 | nodePartitions *nodePartitions,
32 | namespace string,
33 | setName string,
34 | binNames []string,
35 | recordset *Recordset,
36 | ) *scanPartitionCommand {
37 | cmd := &scanPartitionCommand{
38 | baseMultiCommand: *newCorrectStreamingMultiCommand(recordset, namespace),
39 | policy: policy,
40 | namespace: namespace,
41 | setName: setName,
42 | binNames: binNames,
43 | }
44 | cmd.rawCDT = policy.RawCDT
45 | cmd.terminationErrorType = types.SCAN_TERMINATED
46 | cmd.tracker = tracker
47 | cmd.nodePartitions = nodePartitions
48 | cmd.node = nodePartitions.node
49 |
50 | return cmd
51 | }
52 |
53 | func (cmd *scanPartitionCommand) getPolicy(ifc command) Policy {
54 | return cmd.policy
55 | }
56 |
57 | func (cmd *scanPartitionCommand) writeBuffer(ifc command) Error {
58 | return cmd.setScan(cmd.policy, &cmd.namespace, &cmd.setName, cmd.binNames, cmd.recordset.taskID, cmd.nodePartitions)
59 | }
60 |
61 | func (cmd *scanPartitionCommand) shouldRetry(e Error) bool {
62 | return cmd.tracker != nil && cmd.tracker.shouldRetry(cmd.nodePartitions, e)
63 | }
64 |
65 | func (cmd *scanPartitionCommand) commandType() commandType {
66 | return ttScan
67 | }
68 |
69 | func (cmd *scanPartitionCommand) Execute() Error {
70 | err := cmd.execute(cmd)
71 | if err != nil {
72 | // signal to the executor that no retries should be attempted
73 | // don't send error unless no retries are planned
74 | if !cmd.shouldRetry(err) {
75 | cmd.recordset.sendError(err)
76 | }
77 | }
78 | return err
79 | }
80 |
--------------------------------------------------------------------------------
/scan_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // ScanPolicy encapsulates parameters used in scan operations.
18 | //
19 | // Inherited Policy fields Policy.Txn are ignored in scan commands.
20 | type ScanPolicy struct {
21 | MultiPolicy
22 | }
23 |
24 | // NewScanPolicy creates a new ScanPolicy instance with default values.
25 | // Set MaxRetries for scans on server versions >= 4.9. All other
26 | // scans are not retried.
27 | //
28 | // The latest servers support retries on individual data partitions.
29 | // This feature is useful when a cluster is migrating and partition(s)
30 | // are missed or incomplete on the first scan attempt.
31 | //
32 | // If the first scan attempt misses 2 of 4096 partitions, then only
33 | // those 2 partitions are retried in the next scan attempt from the
34 | // last key digest received for each respective partition. A higher
35 | // default MaxRetries is used because it's wasteful to invalidate
36 | // all scan results because a single partition was missed.
37 | func NewScanPolicy() *ScanPolicy {
38 | mp := *NewMultiPolicy()
39 | mp.TotalTimeout = 0
40 |
41 | return &ScanPolicy{
42 | MultiPolicy: mp,
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/single_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | Buffer "github.com/aerospike/aerospike-client-go/v8/utils/buffer"
19 | )
20 |
21 | type singleCommand struct {
22 | baseCommand
23 |
24 | cluster *Cluster
25 | key *Key
26 | partition *Partition
27 | }
28 |
29 | func newSingleCommand(cluster *Cluster, key *Key, partition *Partition) singleCommand {
30 | return singleCommand{
31 | baseCommand: baseCommand{},
32 | cluster: cluster,
33 | key: key,
34 | partition: partition,
35 | }
36 | }
37 |
38 | func (cmd *singleCommand) getConnection(policy Policy) (*Connection, Error) {
39 | return cmd.node.getConnectionWithHint(policy.GetBasePolicy().TotalTimeout, policy.GetBasePolicy().SocketTimeout, cmd.key.digest[0])
40 | }
41 |
42 | func (cmd *singleCommand) putConnection(conn *Connection) {
43 | cmd.node.putConnectionWithHint(conn, cmd.key.digest[0])
44 | }
45 |
46 | func (cmd *singleCommand) emptySocket(conn *Connection) Error {
47 | // There should not be any more bytes.
48 | // Empty the socket to be safe.
49 | sz := Buffer.BytesToInt64(cmd.dataBuffer, 0)
50 | headerLength := cmd.dataBuffer[8]
51 | receiveSize := int(sz&0xFFFFFFFFFFFF) - int(headerLength)
52 |
53 | // Read remaining message bytes.
54 | if receiveSize > 0 {
55 | if err := cmd.sizeBufferSz(receiveSize, false); err != nil {
56 | return err
57 | }
58 | if _, err := conn.Read(cmd.dataBuffer, receiveSize); err != nil {
59 | return err
60 | }
61 | }
62 | return nil
63 | }
64 |
--------------------------------------------------------------------------------
/task.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "time"
19 |
20 | "github.com/aerospike/aerospike-client-go/v8/internal/atomic"
21 | "github.com/aerospike/aerospike-client-go/v8/types"
22 | )
23 |
24 | // Task interface defines methods for asynchronous tasks.
25 | type Task interface {
26 | IsDone() (bool, Error)
27 |
28 | onComplete(ifc Task) chan Error
29 | OnComplete() chan Error
30 | }
31 |
32 | // baseTask is used to poll for server task completion.
33 | type baseTask struct {
34 | retries atomic.Int
35 | cluster *Cluster
36 | }
37 |
38 | // newTask initializes task with fields needed to query server nodes.
39 | func newTask(cluster *Cluster) *baseTask {
40 | return &baseTask{
41 | cluster: cluster,
42 | }
43 | }
44 |
45 | // Wait for asynchronous task to complete using default sleep interval.
46 | func (btsk *baseTask) onComplete(ifc Task) chan Error {
47 | ch := make(chan Error, 1)
48 |
49 | // goroutine will loop every until IsDone() returns true or error
50 | go func() {
51 | // always close the channel on return
52 | defer close(ch)
53 |
54 | var interval = 100 * time.Millisecond
55 |
56 | for {
57 | time.Sleep(interval)
58 |
59 | done, err := ifc.IsDone()
60 | // Every 5 failed retries increase the interval
61 | if btsk.retries.IncrementAndGet()%5 == 0 {
62 | interval *= 2
63 |
64 | if interval > 5*time.Second {
65 | interval = 5 * time.Second
66 | }
67 | }
68 | if err != nil {
69 | if err.Matches(types.TIMEOUT) {
70 | err.markInDoubt(true)
71 | }
72 | ch <- err
73 | return
74 | } else if done {
75 | ch <- nil
76 | return
77 | }
78 | } // for
79 | }()
80 |
81 | return ch
82 | }
83 |
--------------------------------------------------------------------------------
/task_drop_index.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // DropIndexTask is used to poll for long running create index completion.
18 | type DropIndexTask struct {
19 | *baseTask
20 |
21 | namespace string
22 | indexName string
23 | }
24 |
25 | // NewDropIndexTask initializes a task with fields needed to query server nodes.
26 | func NewDropIndexTask(cluster *Cluster, namespace string, indexName string) *DropIndexTask {
27 | return &DropIndexTask{
28 | baseTask: newTask(cluster),
29 | namespace: namespace,
30 | indexName: indexName,
31 | }
32 | }
33 |
34 | // IsDone queries all nodes for task completion status.
35 | func (tski *DropIndexTask) IsDone() (bool, Error) {
36 | command := "sindex-exists:ns=" + tski.namespace + ";indexname=" + tski.indexName
37 | nodes := tski.cluster.GetNodes()
38 | complete := false
39 |
40 | for _, node := range nodes {
41 | responseMap, err := node.requestInfoWithRetry(&tski.cluster.infoPolicy, 5, command)
42 | if err != nil {
43 | return false, err
44 | }
45 |
46 | for _, response := range responseMap {
47 | if response == "false" {
48 | complete = true
49 | continue
50 | }
51 |
52 | return false, nil
53 | }
54 | }
55 | return complete, nil
56 | }
57 |
58 | // OnComplete returns a channel that will be closed as soon as the task is finished.
59 | // If an error is encountered during operation, an error will be sent on the channel.
60 | func (tski *DropIndexTask) OnComplete() chan Error {
61 | return tski.onComplete(tski)
62 | }
63 |
--------------------------------------------------------------------------------
/task_index.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "regexp"
19 | "strconv"
20 | "strings"
21 | )
22 |
23 | // IndexTask is used to poll for long running create index completion.
24 | type IndexTask struct {
25 | *baseTask
26 |
27 | namespace string
28 | indexName string
29 | }
30 |
31 | // NewIndexTask initializes a task with fields needed to query server nodes.
32 | func NewIndexTask(cluster *Cluster, namespace string, indexName string) *IndexTask {
33 | return &IndexTask{
34 | baseTask: newTask(cluster),
35 | namespace: namespace,
36 | indexName: indexName,
37 | }
38 | }
39 |
40 | // IsDone queries all nodes for task completion status.
41 | func (tski *IndexTask) IsDone() (bool, Error) {
42 | command := "sindex/" + tski.namespace + "/" + tski.indexName
43 | nodes := tski.cluster.GetNodes()
44 | complete := false
45 |
46 | r := regexp.MustCompile(`\.*load_pct=(\d+)\.*`)
47 |
48 | for _, node := range nodes {
49 | responseMap, err := node.requestInfoWithRetry(&tski.cluster.infoPolicy, 5, command)
50 | if err != nil {
51 | return false, err
52 | }
53 |
54 | for _, response := range responseMap {
55 | find := "load_pct="
56 | index := strings.Index(response, find)
57 |
58 | if index < 0 {
59 | if tski.retries.Get() > 20 {
60 | complete = true
61 | }
62 | continue
63 | }
64 |
65 | matchRes := r.FindStringSubmatch(response)
66 | // we know it exists and is a valid number
67 | pct, _ := strconv.Atoi(matchRes[1])
68 |
69 | if pct >= 0 && pct < 100 {
70 | return false, nil
71 | }
72 | complete = true
73 | }
74 | }
75 | return complete, nil
76 | }
77 |
78 | // OnComplete returns a channel that will be closed as soon as the task is finished.
79 | // If an error is encountered during operation, an error will be sent on the channel.
80 | func (tski *IndexTask) OnComplete() chan Error {
81 | return tski.onComplete(tski)
82 | }
83 |
--------------------------------------------------------------------------------
/task_register.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "strings"
19 | )
20 |
21 | // RegisterTask is used to poll for UDF registration completion.
22 | type RegisterTask struct {
23 | *baseTask
24 |
25 | packageName string
26 | }
27 |
28 | // NewRegisterTask initializes a RegisterTask with fields needed to query server nodes.
29 | func NewRegisterTask(cluster *Cluster, packageName string) *RegisterTask {
30 | return &RegisterTask{
31 | baseTask: newTask(cluster),
32 | packageName: packageName,
33 | }
34 | }
35 |
36 | // IsDone will query all nodes for task completion status.
37 | func (tskr *RegisterTask) IsDone() (bool, Error) {
38 | command := "udf-list"
39 | nodes := tskr.cluster.GetNodes()
40 | done := false
41 |
42 | for _, node := range nodes {
43 | responseMap, err := node.requestInfoWithRetry(&tskr.cluster.infoPolicy, 5, command)
44 | if err != nil {
45 | return false, err
46 | }
47 |
48 | for _, response := range responseMap {
49 | find := "filename=" + tskr.packageName
50 | index := strings.Index(response, find)
51 |
52 | if index < 0 {
53 | return false, nil
54 | }
55 | done = true
56 | }
57 | }
58 | return done, nil
59 | }
60 |
61 | // OnComplete returns a channel that will be closed as soon as the task is finished.
62 | // If an error is encountered during operation, an error will be sent on the channel.
63 | func (tskr *RegisterTask) OnComplete() chan Error {
64 | return tskr.onComplete(tskr)
65 | }
66 |
--------------------------------------------------------------------------------
/task_remove.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "strings"
19 | )
20 |
21 | // RemoveTask is used to poll for UDF registration completion.
22 | type RemoveTask struct {
23 | *baseTask
24 |
25 | packageName string
26 | }
27 |
28 | // NewRemoveTask initializes a RemoveTask with fields needed to query server nodes.
29 | func NewRemoveTask(cluster *Cluster, packageName string) *RemoveTask {
30 | return &RemoveTask{
31 | baseTask: newTask(cluster),
32 | packageName: packageName,
33 | }
34 | }
35 |
36 | // IsDone will query all nodes for task completion status.
37 | func (tskr *RemoveTask) IsDone() (bool, Error) {
38 | command := "udf-list"
39 | nodes := tskr.cluster.GetNodes()
40 | done := false
41 |
42 | find := "filename=" + tskr.packageName
43 | for _, node := range nodes {
44 | responseMap, err := node.requestInfoWithRetry(&tskr.cluster.infoPolicy, 5, command)
45 | if err != nil {
46 | return false, err
47 | }
48 |
49 | for _, response := range responseMap {
50 | index := strings.Index(response, find)
51 |
52 | if index >= 0 {
53 | return false, nil
54 | }
55 | done = true
56 | }
57 | }
58 | return done, nil
59 | }
60 |
61 | // OnComplete returns a channel that will be closed as soon as the task is finished.
62 | // If an error is encountered during operation, an error will be sent on the channel.
63 | func (tskr *RemoveTask) OnComplete() chan Error {
64 | return tskr.onComplete(tskr)
65 | }
66 |
--------------------------------------------------------------------------------
/test/resources/average.lua:
--------------------------------------------------------------------------------
1 | function average(s, name)
2 |
3 | local function mapper(out, rec)
4 | out['sum'] = (out['sum'] or 0) + (rec[name] or 0)
5 | out['count'] = (out['count'] or 0) + 1
6 | return out
7 | end
8 |
9 | local function reducer(a, b)
10 | local out = map()
11 |
12 | out['sum'] = a['sum'] + b['sum']
13 | out['count'] = a['count'] + b['count']
14 | return out
15 | end
16 |
17 | return s : aggregate(map{sum = 0, count = 0}, mapper) : reduce(reducer)
18 | end
19 |
--------------------------------------------------------------------------------
/test/resources/sum_single_bin.lua:
--------------------------------------------------------------------------------
1 | local function reducer(val1,val2)
2 | return val1 + val2
3 | end
4 |
5 | function sum_single_bin(stream,name)
6 | local function mapper(rec)
7 | return rec[name]
8 | end
9 |
10 | return stream : map(mapper) : reduce(reducer)
11 | end
12 |
--------------------------------------------------------------------------------
/tools.go:
--------------------------------------------------------------------------------
1 | //go:build tools
2 | // +build tools
3 |
4 | // Copyright 2014-2022 Aerospike, Inc.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | // This package imports things required by build scripts, to force `go mod` to see them as dependencies
19 | package aerospike
20 |
21 | import (
22 | _ "github.com/wadey/gocovmerge"
23 | )
24 |
--------------------------------------------------------------------------------
/tools/asinfo/asinfo.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package main
16 |
17 | import (
18 | "flag"
19 | "log"
20 | "os"
21 | "strings"
22 |
23 | as "github.com/aerospike/aerospike-client-go/v8"
24 | )
25 |
26 | var (
27 | host = flag.String("h", "127.0.0.1", "host (default 127.0.0.1)")
28 | port = flag.Int("p", 3000, "port (default 3000)")
29 | value = flag.String("v", "", "(fetch single value - default all)")
30 | user = flag.String("U", "", "User.")
31 | password = flag.String("P", "", "Password.")
32 |
33 | clientPolicy *as.ClientPolicy
34 | )
35 |
36 | func main() {
37 | flag.Parse()
38 | log.SetOutput(os.Stdout)
39 | log.SetFlags(0)
40 |
41 | clientPolicy = as.NewClientPolicy()
42 | if *user != "" {
43 | clientPolicy.User = *user
44 | clientPolicy.Password = *password
45 | }
46 | *value = strings.Trim(*value, " ")
47 |
48 | // connect to the host
49 | conn, err := as.NewConnection(clientPolicy, as.NewHost(*host, *port))
50 | dieIfError(err)
51 |
52 | infoMap, err := conn.RequestInfo(*value)
53 | dieIfError(err)
54 |
55 | defer conn.Close()
56 |
57 | if len(infoMap) == 0 {
58 | log.Printf("Query successful, no information for -v \"%s\"\n\n", *value)
59 | return
60 | }
61 |
62 | outfmt := "%d : %s\n %s\n"
63 | cnt := 1
64 | for k, v := range infoMap {
65 | log.Printf(outfmt, cnt, k, v)
66 | cnt++
67 | }
68 | }
69 |
70 | // dieIfError calls each callback in turn before printing the error via log.Fatalln.
71 | func dieIfError(err error, cleanup ...func()) {
72 | if err != nil {
73 | log.Println("Error:")
74 | for _, cb := range cleanup {
75 | cb()
76 | }
77 | log.Fatalln(err.Error())
78 | }
79 | return
80 | }
81 |
--------------------------------------------------------------------------------
/touch_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | // guarantee touchCommand implements command interface
22 | var _ command = &touchCommand{}
23 |
24 | type touchCommand struct {
25 | baseWriteCommand
26 | }
27 |
28 | func newTouchCommand(cluster *Cluster, policy *WritePolicy, key *Key) (touchCommand, Error) {
29 | bwc, err := newBaseWriteCommand(cluster, policy, key)
30 | if err != nil {
31 | return touchCommand{}, err
32 | }
33 |
34 | newTouchCmd := touchCommand{
35 | baseWriteCommand: bwc,
36 | }
37 |
38 | return newTouchCmd, nil
39 | }
40 |
41 | func (cmd *touchCommand) writeBuffer(ifc command) Error {
42 | return cmd.setTouch(cmd.policy, cmd.key)
43 | }
44 |
45 | func (cmd *touchCommand) parseResult(ifc command, conn *Connection) Error {
46 | resultCode, err := cmd.parseHeader()
47 | if err != nil {
48 | return newCustomNodeError(cmd.node, err.resultCode())
49 | }
50 |
51 | switch resultCode {
52 | case types.OK:
53 | return nil
54 | case types.KEY_NOT_FOUND_ERROR:
55 | return ErrKeyNotFound.err()
56 | case types.FILTERED_OUT:
57 | return ErrFilteredOut.err()
58 | default:
59 | return newError(types.ResultCode(resultCode))
60 | }
61 | }
62 |
63 | func (cmd *touchCommand) isRead() bool {
64 | return false
65 | }
66 |
67 | func (cmd *touchCommand) Execute() Error {
68 | return cmd.execute(cmd)
69 | }
70 |
71 | func (cmd *touchCommand) commandType() commandType {
72 | return ttPut
73 | }
74 |
--------------------------------------------------------------------------------
/txn_add_keys_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | // guarantee txnAddKeysCommand implements command interface
22 | var _ command = &txnAddKeysCommand{}
23 |
24 | type txnAddKeysCommand struct {
25 | baseWriteCommand
26 |
27 | args operateArgs
28 | txn *Txn
29 | }
30 |
31 | func newTxnAddKeysCommand(
32 | cluster *Cluster,
33 | key *Key,
34 | args operateArgs,
35 | txn *Txn,
36 | ) (txnAddKeysCommand, Error) {
37 | bwc, err := newBaseWriteCommand(cluster, args.writePolicy, key)
38 | if err != nil {
39 | return txnAddKeysCommand{}, err
40 | }
41 |
42 | newTxnAddKeysCmd := txnAddKeysCommand{
43 | baseWriteCommand: bwc,
44 | args: args,
45 | txn: txn,
46 | }
47 |
48 | return newTxnAddKeysCmd, nil
49 | }
50 |
51 | func (cmd *txnAddKeysCommand) writeBuffer(ifc command) Error {
52 | return cmd.setTxnAddKeys(cmd.policy, cmd.key, cmd.args)
53 | }
54 |
55 | func (cmd *txnAddKeysCommand) parseResult(ifc command, conn *Connection) Error {
56 | rp, err := newRecordParser(&cmd.baseCommand)
57 | if err != nil {
58 | return err
59 | }
60 | rp.parseTranDeadline(cmd.txn)
61 |
62 | if rp.resultCode != types.OK {
63 | return newCustomNodeError(cmd.node, rp.resultCode)
64 | }
65 |
66 | return nil
67 | }
68 |
69 | func (cmd *txnAddKeysCommand) Execute() Error {
70 | return cmd.execute(cmd)
71 | }
72 |
--------------------------------------------------------------------------------
/txn_close.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | // guarantee txnCloseCommand implements command interface
22 | var _ command = &txnCloseCommand{}
23 |
24 | type txnCloseCommand struct {
25 | baseWriteCommand
26 |
27 | txn *Txn
28 | }
29 |
30 | func newTxnCloseCommand(
31 | cluster *Cluster,
32 | txn *Txn,
33 | writePolicy *WritePolicy,
34 | key *Key,
35 | ) (txnCloseCommand, Error) {
36 | bwc, err := newBaseWriteCommand(cluster, writePolicy, key)
37 | if err != nil {
38 | return txnCloseCommand{}, err
39 | }
40 |
41 | newTxnCloseCmd := txnCloseCommand{
42 | baseWriteCommand: bwc,
43 | txn: txn,
44 | }
45 |
46 | return newTxnCloseCmd, nil
47 | }
48 |
49 | func (cmd *txnCloseCommand) writeBuffer(ifc command) Error {
50 | return cmd.setTxnClose(cmd.txn, cmd.key)
51 | }
52 |
53 | func (cmd *txnCloseCommand) parseResult(ifc command, conn *Connection) Error {
54 | resultCode, err := cmd.parseHeader()
55 | if err != nil {
56 | return newCustomNodeError(cmd.node, err.resultCode())
57 | }
58 |
59 | if resultCode == 0 || resultCode == types.KEY_NOT_FOUND_ERROR {
60 | return nil
61 | }
62 |
63 | return newCustomNodeError(cmd.node, types.ResultCode(resultCode))
64 | }
65 |
66 | func (cmd *txnCloseCommand) Execute() Error {
67 | return cmd.execute(cmd)
68 | }
69 |
70 | func (cmd *txnCloseCommand) onInDoubt() {
71 | return
72 | }
73 |
--------------------------------------------------------------------------------
/txn_error.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "github.com/aerospike/aerospike-client-go/v8/types"
18 |
19 | // TxnError implements Error interface for aerospike multi-record transaction specific errors.
20 | type TxnError struct {
21 | AerospikeError
22 |
23 | // Error status of the attempted commit.
24 | CommitError CommitError
25 |
26 | // Verify result for each read key in the Transaction. May be nil if failure occurred before verify.
27 | VerifyRecords []*BatchRecord
28 |
29 | // Roll forward/backward result for each write key in the Transaction. May be nil if failure occurred before
30 | // roll forward/backward.
31 | RollRecords []*BatchRecord
32 | }
33 |
34 | var _ error = &TxnError{}
35 | var _ Error = &TxnError{}
36 |
37 | func NewTxnCommitError(err CommitError, verifyRecords, rollRecords []*BatchRecord, cause Error) Error {
38 | if cause == nil {
39 | res := newError(types.TXN_FAILED, string(err))
40 | return &TxnError{
41 | AerospikeError: *(res.(*AerospikeError)),
42 | CommitError: err,
43 | VerifyRecords: verifyRecords,
44 | RollRecords: rollRecords,
45 | }
46 | }
47 |
48 | embed := newError(types.TXN_FAILED, string(err)).wrap(cause)
49 | return &TxnError{
50 | AerospikeError: *(embed.(*AerospikeError)),
51 | CommitError: err,
52 | VerifyRecords: verifyRecords,
53 | RollRecords: rollRecords,
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/txn_mark_roll_forward.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | // guarantee txnMarkRollForwardCommand implements command interface
22 | var _ command = &txnMarkRollForwardCommand{}
23 |
24 | type txnMarkRollForwardCommand struct {
25 | baseWriteCommand
26 | }
27 |
28 | func newTxnMarkRollForwardCommand(
29 | cluster *Cluster,
30 | writePolicy *WritePolicy,
31 | key *Key,
32 | ) (txnMarkRollForwardCommand, Error) {
33 | bwc, err := newBaseWriteCommand(cluster, writePolicy, key)
34 | if err != nil {
35 | return txnMarkRollForwardCommand{}, err
36 | }
37 |
38 | newMarkRollForwardCmd := txnMarkRollForwardCommand{
39 | baseWriteCommand: bwc,
40 | }
41 |
42 | return newMarkRollForwardCmd, nil
43 | }
44 |
45 | func (cmd *txnMarkRollForwardCommand) writeBuffer(ifc command) Error {
46 | return cmd.setTxnMarkRollForward(cmd.key)
47 | }
48 |
49 | func (cmd *txnMarkRollForwardCommand) parseResult(ifc command, conn *Connection) Error {
50 | resultCode, err := cmd.parseHeader()
51 | if err != nil {
52 | return newCustomNodeError(cmd.node, err.resultCode())
53 | }
54 |
55 | if resultCode == 0 || resultCode == types.MRT_COMMITTED {
56 | return nil
57 | }
58 |
59 | return newCustomNodeError(cmd.node, types.ResultCode(resultCode))
60 | }
61 |
62 | func (cmd *txnMarkRollForwardCommand) Execute() Error {
63 | return cmd.execute(cmd)
64 | }
65 |
--------------------------------------------------------------------------------
/txn_roll_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2024 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "time"
18 |
19 | // Transaction policy fields used to batch roll forward/backward records on
20 | // commit or abort. Used a placeholder for now as there are no additional fields beyond BatchPolicy.
21 | type TxnRollPolicy struct {
22 | BatchPolicy
23 | }
24 |
25 | // NewTxnRollPolicy creates a new TxnRollPolicy instance with default values.
26 | func NewTxnRollPolicy() *TxnRollPolicy {
27 | mp := *NewBatchPolicy()
28 | mp.ReplicaPolicy = MASTER
29 | mp.MaxRetries = 5
30 | mp.SocketTimeout = 3 * time.Second
31 | mp.TotalTimeout = 10 * time.Second
32 | mp.SleepBetweenRetries = 1 * time.Second
33 |
34 | return &TxnRollPolicy{
35 | BatchPolicy: mp,
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/txn_verify_policy.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2024 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import "time"
18 |
19 | // Transaction policy fields used to batch verify record versions on commit.
20 | // Used a placeholder for now as there are no additional fields beyond BatchPolicy.
21 | type TxnVerifyPolicy struct {
22 | BatchPolicy
23 | }
24 |
25 | // NewTxnRollPolicy creates a new TxnVerifyPolicy instance with default values.
26 | func NewTxnVerifyPolicy() *TxnVerifyPolicy {
27 | mp := *NewBatchPolicy()
28 | mp.ReadModeSC = ReadModeSCLinearize
29 | mp.ReplicaPolicy = MASTER
30 | mp.MaxRetries = 5
31 | mp.TotalTimeout = 10 * time.Millisecond
32 | mp.SleepBetweenRetries = 1 * time.Millisecond
33 |
34 | return &TxnVerifyPolicy{
35 | BatchPolicy: mp,
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/types/epoc.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "math"
5 | "time"
6 | )
7 |
8 | const (
9 | // CITRUSLEAF_EPOCH defines the citrusleaf epoc: Jan 01 2010 00:00:00 GMT
10 | CITRUSLEAF_EPOCH = 1262304000
11 | )
12 |
13 | // TTL converts an Expiration time from citrusleaf epoc to TTL in seconds.
14 | func TTL(secsFromCitrusLeafEpoc uint32) uint32 {
15 | switch secsFromCitrusLeafEpoc {
16 | // don't convert magic values
17 | case 0: // when set to don't expire, this value is returned
18 | return math.MaxUint32
19 | default:
20 | // Record may not have expired on server, but delay or clock differences may
21 | // cause it to look expired on client. Floor at 1, not 0, to avoid old
22 | // "never expires" interpretation.
23 | now := time.Now().Unix()
24 | expiration := int64(CITRUSLEAF_EPOCH + secsFromCitrusLeafEpoc)
25 | if (expiration < 0 && now >= 0) || expiration > now {
26 | return uint32(expiration - now)
27 | }
28 | return 1
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/types/histogram/bench_histogram_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2024 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package histogram_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/aerospike/aerospike-client-go/v8/types/histogram"
21 | )
22 |
23 | var (
24 | _median int
25 | _medianu64 uint64
26 | )
27 |
28 | func Benchmark_Histogram_Linear_Add(b *testing.B) {
29 | h := histogram.New[int](histogram.Linear, 5, 10)
30 | for i := 0; i < b.N; i++ {
31 | h.Add(i)
32 | }
33 | }
34 |
35 | func Benchmark_Histogram_Linear_Median(b *testing.B) {
36 | h := histogram.New[int](histogram.Linear, 50, 101)
37 | for i := 0; i < 10000; i++ {
38 | h.Add(i)
39 | }
40 |
41 | b.ResetTimer()
42 | for i := 0; i < b.N; i++ {
43 | _median = h.Median()
44 | }
45 | }
46 |
47 | func Benchmark_Histogram_Log_Add(b *testing.B) {
48 | h := histogram.NewExponential[int](2, 10)
49 | for i := 0; i < b.N; i++ {
50 | h.Add(i)
51 | }
52 | }
53 |
54 | func Benchmark_Histogram_Log_Median(b *testing.B) {
55 | h := histogram.NewExponential[int](2, 32)
56 | for i := 0; i < 100000; i++ {
57 | h.Add(i)
58 | }
59 |
60 | b.ResetTimer()
61 | for i := 0; i < b.N; i++ {
62 | _median = h.Median()
63 | }
64 | }
65 |
66 | func Benchmark_Histogram_Log2_Add(b *testing.B) {
67 | h := histogram.NewLog2(10)
68 | for i := 0; i < b.N; i++ {
69 | h.Add(uint64(i))
70 | }
71 | }
72 |
73 | func Benchmark_Histogram_Log2_Median(b *testing.B) {
74 | h := histogram.NewLog2(32)
75 | for i := 0; i < 100000; i++ {
76 | h.Add(uint64(i))
77 | }
78 |
79 | b.ResetTimer()
80 | for i := 0; i < b.N; i++ {
81 | _medianu64 = h.Median()
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/types/particle_type/particle_type.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package particleType
16 |
17 | // Server particle types. Unsupported types are commented out.
18 | const (
19 | //revive:disable
20 | NULL = 0
21 | INTEGER = 1
22 | FLOAT = 2
23 | STRING = 3
24 | BLOB = 4
25 | DIGEST = 6
26 | PHP_BLOB = 11 // Had to reintroduce to support the old PHP7 client
27 | BOOL = 17
28 | HLL = 18
29 | MAP = 19
30 | LIST = 20
31 | LDT = 21
32 | GEOJSON = 23
33 | //revive:enable
34 | )
35 |
--------------------------------------------------------------------------------
/types/pool.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package types
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/internal/atomic"
19 | )
20 |
21 | // Pool implements a general purpose fixed-size pool.
22 | type Pool struct {
23 | pool *atomic.Queue
24 |
25 | // New will create a new object
26 | New func(params ...interface{}) interface{}
27 | // IsUsable checks if the object polled from the pool is still fresh and usable
28 | IsUsable func(obj interface{}, params ...interface{}) bool
29 | // CanReturn checkes if the object is eligible to go back to the pool
30 | CanReturn func(obj interface{}) bool
31 | // Finalize will be called when an object is not eligible to go back to the pool.
32 | // Usable to close connections, file handles, ...
33 | Finalize func(obj interface{})
34 | }
35 |
36 | // NewPool creates a new fixed size pool.
37 | func NewPool(poolSize int) *Pool {
38 | return &Pool{
39 | pool: atomic.NewQueue(poolSize),
40 | }
41 | }
42 |
43 | // Get returns an element from the pool.
44 | // If the pool is empty, or the returned element is not usable,
45 | // nil or the result of the New function will be returned
46 | func (bp *Pool) Get(params ...interface{}) interface{} {
47 | res := bp.pool.Poll()
48 | if res == nil || (bp.IsUsable != nil && !bp.IsUsable(res, params...)) {
49 | // not usable, so finalize
50 | if res != nil && bp.Finalize != nil {
51 | bp.Finalize(res)
52 | }
53 |
54 | if bp.New != nil {
55 | res = bp.New(params...)
56 | }
57 | }
58 |
59 | return res
60 | }
61 |
62 | // Put will add the elem back to the pool, unless the pool is full.
63 | func (bp *Pool) Put(obj interface{}) {
64 | finalize := true
65 | if bp.CanReturn == nil || bp.CanReturn(obj) {
66 | finalize = !bp.pool.Offer(obj)
67 | }
68 |
69 | if finalize && bp.Finalize != nil {
70 | bp.Finalize(obj)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/types/pool/buffer_pool_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2021 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package pool
16 |
17 | import (
18 | "math/rand"
19 |
20 | gg "github.com/onsi/ginkgo/v2"
21 | gm "github.com/onsi/gomega"
22 | )
23 |
24 | var _ = gg.Describe("BufferPool Test", func() {
25 |
26 | const (
27 | Min = 1 << 10
28 | Max = 1 << 16
29 | )
30 |
31 | gg.Context("Any size Buffer Pool", func() {
32 | bp := NewTieredBufferPool(Min, Max)
33 | check := func(sz int) {
34 | buf := bp.Get(sz)
35 |
36 | gm.Expect(len(buf)).To(gm.BeNumerically(">=", sz))
37 | if sz <= Max {
38 | if powerOf2(sz) {
39 | gm.Expect(len(buf)).To(gm.BeNumerically("==", 1<<(fastLog2(uint64(sz)))))
40 | gm.Expect(cap(buf)).To(gm.BeNumerically("==", 1<<(fastLog2(uint64(sz)))))
41 | } else {
42 | gm.Expect(len(buf)).To(gm.BeNumerically("==", 1<<(fastLog2(uint64(sz))+1)))
43 | gm.Expect(cap(buf)).To(gm.BeNumerically("==", 1<<(fastLog2(uint64(sz))+1)))
44 | }
45 | } else {
46 | gm.Expect(len(buf)).To(gm.BeNumerically("==", sz))
47 | }
48 | bp.Put(buf)
49 | }
50 |
51 | gg.It("should return a buffer with correct size", func() {
52 | bp = NewTieredBufferPool(Min, Max)
53 |
54 | for i := 1; i < 24; i++ {
55 | check(1<> 17) ^ (s0 >> 26))
44 | res := r.src[1] + s0
45 | return res
46 | }
47 |
48 | // Read will fill the argument slice with random bytes.
49 | // Implements the Reader interface.
50 | func (r *Xor128Rand) Read(p []byte) (n int, err error) {
51 | l := len(p) / 8
52 | for i := 0; i < l; i += 8 {
53 | binary.PutUvarint(p[i:], r.Uint64())
54 | }
55 | return len(p), nil
56 | }
57 |
--------------------------------------------------------------------------------
/types/types.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package types
16 |
--------------------------------------------------------------------------------
/types/types_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package types_test
16 |
17 | import (
18 | "testing"
19 |
20 | gg "github.com/onsi/ginkgo/v2"
21 | gm "github.com/onsi/gomega"
22 | )
23 |
24 | func TestTypes(t *testing.T) {
25 | gm.RegisterFailHandler(gg.Fail)
26 | gg.RunSpecs(t, "Aerospike Client Library Types Suite")
27 | }
28 |
--------------------------------------------------------------------------------
/udf.go:
--------------------------------------------------------------------------------
1 | package aerospike
2 |
3 | // UDF carries information about UDFs on the server
4 | type UDF struct {
5 | // Filename of the UDF
6 | Filename string
7 | // Hash digest of the UDF
8 | Hash string
9 | // Language of UDF
10 | Language Language
11 | }
12 |
--------------------------------------------------------------------------------
/user_roles.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Portions may be licensed to Aerospike, Inc. under one or more contributor
4 | // license agreements.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
7 | // use this file except in compliance with the License. You may obtain a copy of
8 | // the License at http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | // License for the specific language governing permissions and limitations under
14 | // the License.
15 |
16 | package aerospike
17 |
18 | // UserRoles contains information about a user.
19 | type UserRoles struct {
20 | // User name.
21 | User string
22 |
23 | // Roles is a list of assigned roles.
24 | Roles []string
25 |
26 | // ReadInfo is the list of read statistics. List may be nil.
27 | // Current statistics by offset are:
28 | //
29 | // 0: read quota in records per second
30 | // 1: single record read command rate (TPS)
31 | // 2: read scan/query record per second rate (RPS)
32 | // 3: number of limitless read scans/queries
33 | //
34 | // Future server releases may add additional statistics.
35 | ReadInfo []int
36 |
37 | // WriteInfo is the list of write statistics. List may be nil.
38 | // Current statistics by offset are:
39 | //
40 | // 0: write quota in records per second
41 | // 1: single record write command rate (TPS)
42 | // 2: write scan/query record per second rate (RPS)
43 | // 3: number of limitless write scans/queries
44 | //
45 | // Future server releases may add additional statistics.
46 | WriteInfo []int
47 |
48 | // ConnsInUse is the number of currently open connections for the user
49 | ConnsInUse int
50 | }
51 |
--------------------------------------------------------------------------------
/value_helpers.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | // MapIter allows to define general maps of your own type to be used in the Go client
18 | // without the use of reflection.
19 | // function PackMap should be exactly Like the following (Do not change, just copy/paste and adapt PackXXX methods):
20 | //
21 | // func (cm *CustomMap) PackMap(buf aerospike.BufferEx) (int, error) {
22 | // size := 0
23 | // for k, v := range cm {
24 | // n, err := PackXXX(buf, k)
25 | // size += n
26 | // if err != nil {
27 | // return size, err
28 | // }
29 | //
30 | // n, err = PackXXX(buf, v)
31 | // size += n
32 | // if err != nil {
33 | // return size, err
34 | // }
35 | // }
36 | // return size, nil
37 | // }
38 | type MapIter interface {
39 | PackMap(buf BufferEx) (int, error)
40 | Len() int
41 | }
42 |
43 | // ListIter allows to define general maps of your own type to be used in the Go client
44 | // without the use of reflection.
45 | // function PackList should be exactly Like the following (Do not change, just copy/paste and adapt PackXXX methods):
46 | //
47 | // func (cs *CustomSlice) PackList(buf aerospike.BufferEx) (int, error) {
48 | // size := 0
49 | // for _, elem := range cs {
50 | // n, err := PackXXX(buf, elem)
51 | // size += n
52 | // if err != nil {
53 | // return size, err
54 | // }
55 | // }
56 | // return size, nil
57 | // }
58 | type ListIter interface {
59 | PackList(buf BufferEx) (int, error)
60 | Len() int
61 | }
62 |
--------------------------------------------------------------------------------
/value_reflect.go:
--------------------------------------------------------------------------------
1 | //go:build !as_performance
2 |
3 | // Copyright 2014-2022 Aerospike, Inc.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package aerospike
18 |
19 | import (
20 | "reflect"
21 | )
22 |
23 | func init() {
24 | newValueReflect = concreteNewValueReflect
25 | }
26 |
27 | // if the returned value is nil, the caller will panic
28 | func concreteNewValueReflect(v interface{}) Value {
29 | // check for array and map
30 | rv := reflect.ValueOf(v)
31 | switch rv.Kind() {
32 | case reflect.Array, reflect.Slice:
33 | l := rv.Len()
34 | arr := make([]interface{}, l)
35 | for i := 0; i < l; i++ {
36 | arr[i] = rv.Index(i).Interface()
37 | }
38 |
39 | return NewListValue(arr)
40 | case reflect.Map:
41 | l := rv.Len()
42 | amap := make(map[interface{}]interface{}, l)
43 | for _, i := range rv.MapKeys() {
44 | amap[i.Interface()] = rv.MapIndex(i).Interface()
45 | }
46 |
47 | return NewMapValue(amap)
48 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
49 | return NewLongValue(reflect.ValueOf(v).Int())
50 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
51 | return NewLongValue(int64(reflect.ValueOf(v).Uint()))
52 | case reflect.String:
53 | return NewStringValue(rv.String())
54 | }
55 |
56 | return nil
57 | }
58 |
--------------------------------------------------------------------------------
/werrgroup.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "context"
19 | "sync"
20 |
21 | "golang.org/x/sync/semaphore"
22 |
23 | "github.com/aerospike/aerospike-client-go/v8/logger"
24 | )
25 |
26 | type werrGroup struct {
27 | sem *semaphore.Weighted
28 | ctx context.Context
29 | wg sync.WaitGroup
30 | el sync.Mutex
31 | errs Error
32 |
33 | // function to defer; used for recordset signals
34 | f func()
35 | }
36 |
37 | func newWeightedErrGroup(maxConcurrency int) *werrGroup {
38 | if maxConcurrency <= 0 {
39 | maxConcurrency = 1
40 | }
41 |
42 | return &werrGroup{
43 | sem: semaphore.NewWeighted(int64(maxConcurrency)),
44 | ctx: context.Background(),
45 | }
46 | }
47 |
48 | func (weg *werrGroup) execute(cmd command) {
49 | weg.wg.Add(1)
50 |
51 | if err := weg.sem.Acquire(weg.ctx, 1); err != nil {
52 | logger.Logger.Error("Constraint Semaphore failed: %s", err.Error())
53 | }
54 |
55 | go func() {
56 | defer weg.sem.Release(1)
57 | defer weg.wg.Done()
58 | if weg.f != nil {
59 | defer weg.f()
60 | }
61 |
62 | if err := cmd.Execute(); err != nil {
63 | weg.el.Lock()
64 | weg.errs = chainErrors(err, weg.errs)
65 | weg.el.Unlock()
66 | }
67 | }()
68 | }
69 |
70 | func (weg *werrGroup) wait() Error {
71 | weg.wg.Wait()
72 | return weg.errs
73 | }
74 |
--------------------------------------------------------------------------------
/write_command.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014-2022 Aerospike, Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package aerospike
16 |
17 | import (
18 | "github.com/aerospike/aerospike-client-go/v8/types"
19 | )
20 |
21 | // guarantee writeCommand implements command interface
22 | var _ command = &writeCommand{}
23 |
24 | type writeCommand struct {
25 | baseWriteCommand
26 |
27 | bins []*Bin
28 | binMap BinMap
29 | operation OperationType
30 | }
31 |
32 | func newWriteCommand(
33 | cluster *Cluster,
34 | policy *WritePolicy,
35 | key *Key,
36 | bins []*Bin,
37 | binMap BinMap,
38 | operation OperationType,
39 | ) (writeCommand, Error) {
40 | bwc, err := newBaseWriteCommand(cluster, policy, key)
41 | if err != nil {
42 | return writeCommand{}, err
43 | }
44 |
45 | newWriteCmd := writeCommand{
46 | baseWriteCommand: bwc,
47 | bins: bins,
48 | binMap: binMap,
49 | operation: operation,
50 | }
51 |
52 | return newWriteCmd, nil
53 | }
54 |
55 | func (cmd *writeCommand) writeBuffer(ifc command) Error {
56 | return cmd.setWrite(cmd.policy, cmd.operation, cmd.key, cmd.bins, cmd.binMap)
57 | }
58 |
59 | func (cmd *writeCommand) parseResult(ifc command, conn *Connection) Error {
60 | resultCode, err := cmd.parseHeader()
61 | if err != nil {
62 | return newCustomNodeError(cmd.node, err.resultCode())
63 | }
64 |
65 | if resultCode != types.OK {
66 | if resultCode == types.KEY_NOT_FOUND_ERROR {
67 | return ErrKeyNotFound.err()
68 | } else if resultCode == types.FILTERED_OUT {
69 | return ErrFilteredOut.err()
70 | }
71 |
72 | return newCustomNodeError(cmd.node, types.ResultCode(resultCode))
73 | }
74 |
75 | return nil
76 | }
77 |
78 | func (cmd *writeCommand) Execute() Error {
79 | return cmd.execute(cmd)
80 | }
81 |
--------------------------------------------------------------------------------