summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/go/internal/admin/prog/valgrind.go3
-rw-r--r--client/go/internal/admin/prog/valgrind_test.go5
-rw-r--r--client/go/internal/admin/vespa-wrapper/startcbinary/valgrind.go3
-rw-r--r--client/go/internal/admin/vespa-wrapper/startcbinary/valgrind_test.go5
-rw-r--r--client/go/internal/cli/auth/zts/zts.go2
-rw-r--r--client/go/internal/cli/cmd/config.go10
-rw-r--r--client/go/internal/cli/cmd/config_test.go1
-rw-r--r--client/go/internal/cli/cmd/feed.go57
-rw-r--r--client/go/internal/cli/cmd/feed_test.go15
-rw-r--r--client/go/internal/cli/cmd/root.go4
-rw-r--r--client/go/internal/cli/cmd/test.go2
-rw-r--r--client/go/internal/cli/cmd/visit_test.go2
-rw-r--r--client/go/internal/mock/http.go4
-rw-r--r--client/go/internal/util/http.go71
-rw-r--r--client/go/internal/vespa/document/dispatcher.go129
-rw-r--r--client/go/internal/vespa/document/dispatcher_test.go15
-rw-r--r--client/go/internal/vespa/document/document.go21
-rw-r--r--client/go/internal/vespa/document/feeder.go7
-rw-r--r--client/go/internal/vespa/document/http.go110
-rw-r--r--client/go/internal/vespa/document/http_test.go64
-rw-r--r--client/go/internal/vespa/document/throttler.go41
-rw-r--r--client/go/internal/vespa/document/throttler_test.go6
-rw-r--r--client/go/internal/vespa/target.go16
-rw-r--r--client/go/internal/vespa/target_cloud.go4
-rw-r--r--config-model/src/main/java/com/yahoo/schema/OnnxModel.java7
-rw-r--r--config-model/src/main/java/com/yahoo/schema/expressiontransforms/InputRecorder.java14
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java25
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java7
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/ml/OnnxModelInfo.java24
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidatorTest.java11
-rw-r--r--config-proxy/src/main/java/com/yahoo/vespa/config/proxy/filedistribution/FileReferencesAndDownloadsMaintainer.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java12
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintainer.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java2
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java39
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/IndexFacts.java98
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java42
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/cluster/SchemaResolver.java58
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java3
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java14
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java15
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java8
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLog.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLogger.java22
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveUriUpdater.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArtifactExpirer.java17
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdater.java16
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingDatabaseMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudDatabaseMaintainer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainer.java18
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java14
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentExpirer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentInfoMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java12
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EnclaveAccessMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/HostInfoUpdater.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/InfrastructureUpgrader.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsVersionStatusUpdater.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceTagMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleCleanupMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/UserManagementMaintainer.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdater.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdaterTest.java20
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainerTest.java12
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java16
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java7
-rw-r--r--default_build_settings.cmake18
-rw-r--r--document/src/vespa/document/select/parse_utils.cpp2
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java2
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java6
-rw-r--r--functions.cmake8
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/CoreDumpMetadata.java45
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/bindings/ReportCoreDumpRequest.java2
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollector.java5
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java2
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollectorTest.java5
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DiskReplacer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostDeprovisioner.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostResumeProvisioner.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainer.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java29
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainerTest.java2
-rw-r--r--searchcore/src/tests/proton/common/attribute_updater/attribute_updater_test.cpp6
-rw-r--r--searchlib/src/tests/attribute/attribute_test.cpp44
-rw-r--r--searchlib/src/tests/attribute/extendattributes/extendattribute.cpp176
-rw-r--r--searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp24
-rw-r--r--searchlib/src/tests/memoryindex/field_index/field_index_test.cpp36
-rw-r--r--searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp4
-rw-r--r--searchlib/src/tests/predicate/document_features_store_test.cpp14
-rw-r--r--searchlib/src/vespa/searchlib/attribute/attributevector.h3
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h14
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp36
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistattribute.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postingstore.cpp12
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp2
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/feature_store.h3
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/field_index.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/word_store.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/predicate/document_features_store.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/predicate/simple_index.hpp6
-rw-r--r--searchlib/src/vespa/searchlib/tensor/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp10
-rw-r--r--searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h2
-rw-r--r--searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h4
-rw-r--r--searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp30
-rw-r--r--searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h8
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp181
-rw-r--r--searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h54
-rw-r--r--storage/src/vespa/storage/bucketdb/btree_lockable_map.hpp2
-rw-r--r--storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp4
-rw-r--r--streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp26
-rw-r--r--vdslib/src/tests/distribution/distributiontest.cpp6
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java2
-rw-r--r--vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java26
-rw-r--r--vespajlib/src/main/java/com/yahoo/slime/SlimeUtils.java95
-rw-r--r--vespalib/src/tests/btree/btree-stress/btree_stress_test.cpp2
-rw-r--r--vespalib/src/tests/btree/btree_test.cpp2
-rw-r--r--vespalib/src/tests/datastore/array_store/array_store_test.cpp68
-rw-r--r--vespalib/src/tests/datastore/array_store_config/array_store_config_test.cpp22
-rw-r--r--vespalib/src/tests/datastore/buffer_stats/buffer_stats_test.cpp14
-rw-r--r--vespalib/src/tests/datastore/buffer_type/buffer_type_test.cpp160
-rw-r--r--vespalib/src/tests/datastore/datastore/datastore_test.cpp128
-rw-r--r--vespalib/src/tests/datastore/free_list/free_list_test.cpp12
-rw-r--r--vespalib/src/tests/datastore/unique_store/unique_store_test.cpp41
-rw-r--r--vespalib/src/tests/datastore/unique_store_string_allocator/unique_store_string_allocator_test.cpp18
-rw-r--r--vespalib/src/tests/signalhandler/CMakeLists.txt5
-rw-r--r--vespalib/src/vespa/vespalib/btree/btree.h4
-rw-r--r--vespalib/src/vespa/vespalib/btree/btreenodeallocator.h4
-rw-r--r--vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp8
-rw-r--r--vespalib/src/vespa/vespalib/btree/btreenodestore.h16
-rw-r--r--vespalib/src/vespa/vespalib/btree/btreenodestore.hpp10
-rw-r--r--vespalib/src/vespa/vespalib/btree/btreestore.h10
-rw-r--r--vespalib/src/vespa/vespalib/btree/btreestore.hpp26
-rw-r--r--vespalib/src/vespa/vespalib/datastore/allocator.h2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/allocator.hpp26
-rw-r--r--vespalib/src/vespa/vespalib/datastore/array_store.h20
-rw-r--r--vespalib/src/vespa/vespalib/datastore/array_store.hpp105
-rw-r--r--vespalib/src/vespa/vespalib/datastore/array_store_config.cpp14
-rw-r--r--vespalib/src/vespa/vespalib/datastore/array_store_config.h28
-rw-r--r--vespalib/src/vespa/vespalib/datastore/array_store_simple_type_mapper.h6
-rw-r--r--vespalib/src/vespa/vespalib/datastore/array_store_type_mapper.h2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp7
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_free_list.h7
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp40
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_stats.h50
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_type.cpp155
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_type.h108
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_type.hpp74
-rw-r--r--vespalib/src/vespa/vespalib/datastore/bufferstate.cpp122
-rw-r--r--vespalib/src/vespa/vespalib/datastore/bufferstate.h39
-rw-r--r--vespalib/src/vespa/vespalib/datastore/datastore.h14
-rw-r--r--vespalib/src/vespa/vespalib/datastore/datastore.hpp14
-rw-r--r--vespalib/src/vespa/vespalib/datastore/datastorebase.cpp125
-rw-r--r--vespalib/src/vespa/vespalib/datastore/datastorebase.h57
-rw-r--r--vespalib/src/vespa/vespalib/datastore/free_list.h1
-rw-r--r--vespalib/src/vespa/vespalib/datastore/free_list_allocator.h2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/free_list_allocator.hpp10
-rw-r--r--vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.h2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.hpp10
-rw-r--r--vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h8
-rw-r--r--vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp22
-rw-r--r--vespalib/src/vespa/vespalib/datastore/memory_stats.cpp16
-rw-r--r--vespalib/src/vespa/vespalib/datastore/memory_stats.h8
-rw-r--r--vespalib/src/vespa/vespalib/datastore/raw_allocator.h6
-rw-r--r--vespalib/src/vespa/vespalib/datastore/raw_allocator.hpp14
-rw-r--r--vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.h4
-rw-r--r--vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.hpp14
-rw-r--r--vespalib/src/vespa/vespalib/datastore/unique_store.hpp2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/unique_store_allocator.hpp2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/unique_store_enumerator.hpp2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.cpp18
-rw-r--r--vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.h8
-rw-r--r--vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.hpp9
-rw-r--r--vespalib/src/vespa/vespalib/util/CMakeLists.txt4
-rw-r--r--vespalib/src/vespa/vespalib/util/time.cpp2
-rw-r--r--vespalib/src/vespa/vespalib/util/time.h2
214 files changed, 2309 insertions, 1733 deletions
diff --git a/client/go/internal/admin/prog/valgrind.go b/client/go/internal/admin/prog/valgrind.go
index 7d3fb059f8f..2d7f0a597d9 100644
--- a/client/go/internal/admin/prog/valgrind.go
+++ b/client/go/internal/admin/prog/valgrind.go
@@ -22,9 +22,10 @@ func (p *Spec) ConfigureValgrind() {
p.shouldUseValgrind = false
p.shouldUseCallgrind = false
env := p.Getenv(envvars.VESPA_USE_VALGRIND)
+ allValgrind := env == "all"
parts := strings.Split(env, " ")
for _, part := range parts {
- if p.BaseName == part {
+ if p.BaseName == part || allValgrind {
trace.Trace("using valgrind as", p.Program, "has basename in", envvars.VESPA_USE_VALGRIND, "=>", env)
backticks := util.BackTicksWithStderr
out, err := backticks.Run(VALGRIND_PROG, "--help")
diff --git a/client/go/internal/admin/prog/valgrind_test.go b/client/go/internal/admin/prog/valgrind_test.go
index 6ec622277c6..11d9424405f 100644
--- a/client/go/internal/admin/prog/valgrind_test.go
+++ b/client/go/internal/admin/prog/valgrind_test.go
@@ -52,6 +52,11 @@ func TestValgrindDetection(t *testing.T) {
assert.Equal(t, false, spec.shouldUseValgrind)
assert.Equal(t, false, spec.shouldUseCallgrind)
+ t.Setenv("VESPA_USE_VALGRIND", "all")
+ spec.ConfigureValgrind()
+ assert.Equal(t, true, spec.shouldUseValgrind)
+ assert.Equal(t, false, spec.shouldUseCallgrind)
+
t.Setenv("VESPA_USE_VALGRIND", "foo bar")
spec.ConfigureValgrind()
assert.Equal(t, false, spec.shouldUseValgrind)
diff --git a/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind.go b/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind.go
index 43a1ed602bd..cccb37df8e5 100644
--- a/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind.go
+++ b/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind.go
@@ -18,9 +18,10 @@ func (p *ProgSpec) configureValgrind() {
p.shouldUseValgrind = false
p.shouldUseCallgrind = false
env := p.getenv(envvars.VESPA_USE_VALGRIND)
+ allValgrind := env == "all"
parts := strings.Split(env, " ")
for _, part := range parts {
- if p.BaseName == part {
+ if p.BaseName == part || allValgrind {
trace.Trace("using valgrind as", p.Program, "has basename in", envvars.VESPA_USE_VALGRIND, "=>", env)
backticks := util.BackTicksWithStderr
out, err := backticks.Run("which", "valgrind")
diff --git a/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind_test.go b/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind_test.go
index 48cc78474ed..1a105d66c4a 100644
--- a/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind_test.go
+++ b/client/go/internal/admin/vespa-wrapper/startcbinary/valgrind_test.go
@@ -52,6 +52,11 @@ func TestValgrindDetection(t *testing.T) {
assert.Equal(t, false, spec.shouldUseValgrind)
assert.Equal(t, false, spec.shouldUseCallgrind)
+ t.Setenv("VESPA_USE_VALGRIND", "all")
+ spec.configureValgrind()
+ assert.Equal(t, true, spec.shouldUseValgrind)
+ assert.Equal(t, false, spec.shouldUseCallgrind)
+
t.Setenv("VESPA_USE_VALGRIND", "foo bar")
spec.configureValgrind()
assert.Equal(t, false, spec.shouldUseValgrind)
diff --git a/client/go/internal/cli/auth/zts/zts.go b/client/go/internal/cli/auth/zts/zts.go
index 1e84912a271..caa2d03367d 100644
--- a/client/go/internal/cli/auth/zts/zts.go
+++ b/client/go/internal/cli/auth/zts/zts.go
@@ -37,7 +37,7 @@ func (c *Client) AccessToken(domain string, certificate tls.Certificate) (string
if err != nil {
return "", err
}
- util.SetCertificate(c.client, []tls.Certificate{certificate})
+ util.SetCertificates(c.client, []tls.Certificate{certificate})
response, err := c.client.Do(req, 10*time.Second)
if err != nil {
return "", err
diff --git a/client/go/internal/cli/cmd/config.go b/client/go/internal/cli/cmd/config.go
index fd049864096..2d32c454842 100644
--- a/client/go/internal/cli/cmd/config.go
+++ b/client/go/internal/cli/cmd/config.go
@@ -544,12 +544,12 @@ func (c *Config) list(includeUnset bool) []string {
}
// flagValue returns the set value and default value of the named flag.
-func (c *Config) flagValue(name string) (string, string) {
+func (c *Config) flagValue(name string) (string, string, bool) {
f, ok := c.flags[name]
if !ok {
- return "", ""
+ return "", "", ok
}
- return f.Value.String(), f.DefValue
+ return f.Value.String(), f.DefValue, f.Changed
}
// getNonEmpty returns value of given option, if that value is non-empty
@@ -564,9 +564,9 @@ func (c *Config) getNonEmpty(option string) (string, bool) {
// get returns the value associated with option, from the most preferred source in the following order: flag > local
// config > global config.
func (c *Config) get(option string) (string, bool) {
- flagValue, flagDefault := c.flagValue(option)
+ flagValue, flagDefault, changed := c.flagValue(option)
// explicit flag value always takes precedence over everything else
- if flagValue != flagDefault {
+ if changed {
return flagValue, true
}
// ... then local config, if option is explicitly defined there
diff --git a/client/go/internal/cli/cmd/config_test.go b/client/go/internal/cli/cmd/config_test.go
index 612904061de..458878b4356 100644
--- a/client/go/internal/cli/cmd/config_test.go
+++ b/client/go/internal/cli/cmd/config_test.go
@@ -28,6 +28,7 @@ func TestConfig(t *testing.T) {
assertConfigCommand(t, configHome, "", "config", "set", "target", "http://127.0.0.1:8080")
assertConfigCommand(t, configHome, "", "config", "set", "target", "https://127.0.0.1")
assertConfigCommand(t, configHome, "target = https://127.0.0.1\n", "config", "get", "target")
+ assertConfigCommand(t, configHome, "target = local\n", "config", "get", "-t", "local", "target")
// application
assertConfigCommandErr(t, configHome, "Error: invalid application: \"foo\"\n", "config", "set", "application", "foo")
diff --git a/client/go/internal/cli/cmd/feed.go b/client/go/internal/cli/cmd/feed.go
index c8e032929b8..895a22d2be5 100644
--- a/client/go/internal/cli/cmd/feed.go
+++ b/client/go/internal/cli/cmd/feed.go
@@ -9,17 +9,20 @@ import (
"time"
"github.com/spf13/cobra"
+ "github.com/vespa-engine/vespa/client/go/internal/util"
+ "github.com/vespa-engine/vespa/client/go/internal/vespa"
"github.com/vespa-engine/vespa/client/go/internal/vespa/document"
)
-func addFeedFlags(cmd *cobra.Command, concurrency *int) {
- // TOOD(mpolden): Remove this flag
- cmd.PersistentFlags().IntVarP(concurrency, "concurrency", "T", 64, "Number of goroutines to use for dispatching")
+func addFeedFlags(cmd *cobra.Command, verbose *bool, connections *int) {
+ cmd.PersistentFlags().IntVarP(connections, "connections", "N", 8, "The number of connections to use")
+ cmd.PersistentFlags().BoolVarP(verbose, "verbose", "v", false, "Verbose mode. Print errors as they happen")
}
func newFeedCmd(cli *CLI) *cobra.Command {
var (
- concurrency int
+ verbose bool
+ connections int
)
cmd := &cobra.Command{
Use: "feed FILE",
@@ -27,42 +30,66 @@ func newFeedCmd(cli *CLI) *cobra.Command {
Long: `Feed documents to a Vespa cluster.
A high performance feeding client. This can be used to feed large amounts of
-documents to Vespa cluster efficiently.
+documents to a Vespa cluster efficiently.
The contents of FILE must be either a JSON array or JSON objects separated by
newline (JSONL).
+
+If FILE is a single dash ('-'), documents will be read from standard input.
`,
Example: `$ vespa feed documents.jsonl
+$ cat documents.jsonl | vespa feed -
`,
Args: cobra.ExactArgs(1),
DisableAutoGenTag: true,
SilenceUsage: true,
Hidden: true, // TODO(mpolden): Remove when ready for public use
RunE: func(cmd *cobra.Command, args []string) error {
- f, err := os.Open(args[0])
- if err != nil {
- return err
+ var r io.Reader
+ if args[0] == "-" {
+ r = cli.Stdin
+ } else {
+ f, err := os.Open(args[0])
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ r = f
}
- defer f.Close()
- return feed(f, cli, concurrency)
+ return feed(r, cli, verbose, connections)
},
}
- addFeedFlags(cmd, &concurrency)
+ addFeedFlags(cmd, &verbose, &connections)
return cmd
}
-func feed(r io.Reader, cli *CLI, concurrency int) error {
+func createServiceClients(service *vespa.Service, n int) []util.HTTPClient {
+ clients := make([]util.HTTPClient, 0, n)
+ for i := 0; i < n; i++ {
+ client := service.Client().Clone()
+ util.ForceHTTP2(client, service.TLSOptions.KeyPair) // Feeding should always use HTTP/2
+ clients = append(clients, client)
+ }
+ return clients
+}
+
+func feed(r io.Reader, cli *CLI, verbose bool, connections int) error {
service, err := documentService(cli)
if err != nil {
return err
}
+ clients := createServiceClients(service, connections)
client := document.NewClient(document.ClientOptions{
BaseURL: service.BaseURL,
- }, service)
- throttler := document.NewThrottler()
+ }, clients)
+ throttler := document.NewThrottler(connections)
// TODO(mpolden): Make doom duration configurable
circuitBreaker := document.NewCircuitBreaker(10*time.Second, 0)
- dispatcher := document.NewDispatcher(client, throttler, circuitBreaker)
+ errWriter := io.Discard
+ if verbose {
+ errWriter = cli.Stderr
+ }
+ dispatcher := document.NewDispatcher(client, throttler, circuitBreaker, errWriter)
dec := document.NewDecoder(r)
start := cli.now()
diff --git a/client/go/internal/cli/cmd/feed_test.go b/client/go/internal/cli/cmd/feed_test.go
index 1bf1ef6ab9b..521d2b2abd0 100644
--- a/client/go/internal/cli/cmd/feed_test.go
+++ b/client/go/internal/cli/cmd/feed_test.go
@@ -1,6 +1,7 @@
package cmd
import (
+ "bytes"
"os"
"path/filepath"
"testing"
@@ -42,7 +43,7 @@ func TestFeed(t *testing.T) {
require.Nil(t, cli.Run("feed", jsonFile))
assert.Equal(t, "", stderr.String())
- assert.Equal(t, `{
+ want := `{
"feeder.seconds": 1.000,
"feeder.ok.count": 1,
"feeder.ok.rate": 1.000,
@@ -63,5 +64,15 @@ func TestFeed(t *testing.T) {
"200": 1
}
}
-`, stdout.String())
+`
+ assert.Equal(t, want, stdout.String())
+
+ stdout.Reset()
+ cli.Stdin = bytes.NewBuffer([]byte(`{
+ "put": "id:ns:type::doc1",
+ "fields": {"foo": "123"}
+}`))
+ httpClient.NextResponseString(200, `{"message":"OK"}`)
+ require.Nil(t, cli.Run("feed", "-"))
+ assert.Equal(t, want, stdout.String())
}
diff --git a/client/go/internal/cli/cmd/root.go b/client/go/internal/cli/cmd/root.go
index 58e940d59ef..360af9d0dcf 100644
--- a/client/go/internal/cli/cmd/root.go
+++ b/client/go/internal/cli/cmd/root.go
@@ -366,7 +366,7 @@ func (c *CLI) createCloudTarget(targetType string, opts targetOptions) (vespa.Ta
return nil, errHint(err, "Deployment to cloud requires a certificate. Try 'vespa auth cert'")
}
deploymentTLSOptions = vespa.TLSOptions{
- KeyPair: &kp.KeyPair,
+ KeyPair: []tls.Certificate{kp.KeyPair},
CertificateFile: kp.CertificateFile,
PrivateKeyFile: kp.PrivateKeyFile,
}
@@ -377,7 +377,7 @@ func (c *CLI) createCloudTarget(targetType string, opts targetOptions) (vespa.Ta
return nil, errHint(err, "Deployment to hosted requires an Athenz certificate", "Try renewing certificate with 'athenz-user-cert'")
}
apiTLSOptions = vespa.TLSOptions{
- KeyPair: &kp.KeyPair,
+ KeyPair: []tls.Certificate{kp.KeyPair},
CertificateFile: kp.CertificateFile,
PrivateKeyFile: kp.PrivateKeyFile,
}
diff --git a/client/go/internal/cli/cmd/test.go b/client/go/internal/cli/cmd/test.go
index 4a53fe6bed3..05633b1135e 100644
--- a/client/go/internal/cli/cmd/test.go
+++ b/client/go/internal/cli/cmd/test.go
@@ -263,7 +263,7 @@ func verify(step step, defaultCluster string, defaultParameters map[string]strin
var response *http.Response
if externalEndpoint {
- util.SetCertificate(context.cli.httpClient, []tls.Certificate{})
+ util.SetCertificates(context.cli.httpClient, []tls.Certificate{})
response, err = context.cli.httpClient.Do(request, 60*time.Second)
} else {
response, err = service.Do(request, 600*time.Second) // Vespa should provide a response within the given request timeout
diff --git a/client/go/internal/cli/cmd/visit_test.go b/client/go/internal/cli/cmd/visit_test.go
index 4302680b9d9..b6e5b893e0b 100644
--- a/client/go/internal/cli/cmd/visit_test.go
+++ b/client/go/internal/cli/cmd/visit_test.go
@@ -47,7 +47,7 @@ func TestQuoteFunc(t *testing.T) {
res := quoteArgForUrl(s)
if i < 32 || i > 127 {
assert.Equal(t, "a+z", res)
- } else {
+ } else if testing.Verbose() { // go test -v
fmt.Printf("res %3d => '%s'\n", i, res)
}
}
diff --git a/client/go/internal/mock/http.go b/client/go/internal/mock/http.go
index 9c55f2e79bf..58614d7e5bd 100644
--- a/client/go/internal/mock/http.go
+++ b/client/go/internal/mock/http.go
@@ -6,6 +6,8 @@ import (
"net/http"
"strconv"
"time"
+
+ "github.com/vespa-engine/vespa/client/go/internal/util"
)
type HTTPClient struct {
@@ -58,3 +60,5 @@ func (c *HTTPClient) Do(request *http.Request, timeout time.Duration) (*http.Res
},
nil
}
+
+func (c *HTTPClient) Clone() util.HTTPClient { return c }
diff --git a/client/go/internal/util/http.go b/client/go/internal/util/http.go
index cb35932c8e7..dcf05ed3a14 100644
--- a/client/go/internal/util/http.go
+++ b/client/go/internal/util/http.go
@@ -2,9 +2,10 @@
package util
import (
- "bytes"
+ "context"
"crypto/tls"
"fmt"
+ "net"
"net/http"
"time"
@@ -14,6 +15,7 @@ import (
type HTTPClient interface {
Do(request *http.Request, timeout time.Duration) (response *http.Response, error error)
+ Clone() HTTPClient
}
type defaultHTTPClient struct {
@@ -31,50 +33,57 @@ func (c *defaultHTTPClient) Do(request *http.Request, timeout time.Duration) (re
return c.client.Do(request)
}
-func SetCertificate(client HTTPClient, certificates []tls.Certificate) {
+func (c *defaultHTTPClient) Clone() HTTPClient { return CreateClient(c.client.Timeout) }
+
+func SetCertificates(client HTTPClient, certificates []tls.Certificate) {
c, ok := client.(*defaultHTTPClient)
if !ok {
return
}
- // Use HTTP/2 transport explicitly. Connection reuse does not work properly when using regular http.Transport, even
- // though it upgrades to HTTP/2 automatically
- // https://github.com/golang/go/issues/16582
- // https://github.com/golang/go/issues/22091
- var transport *http2.Transport
- if _, ok := c.client.Transport.(*http.Transport); ok {
- transport = &http2.Transport{}
- c.client.Transport = transport
- } else if t, ok := c.client.Transport.(*http2.Transport); ok {
- transport = t
- } else {
- panic(fmt.Sprintf("unknown transport type: %T", c.client.Transport))
- }
- if ok && !c.hasCertificates(transport.TLSClientConfig, certificates) {
- transport.TLSClientConfig = &tls.Config{
+ var tlsConfig *tls.Config = nil
+ if certificates != nil {
+ tlsConfig = &tls.Config{
Certificates: certificates,
MinVersion: tls.VersionTLS12,
}
}
+ if tr, ok := c.client.Transport.(*http.Transport); ok {
+ tr.TLSClientConfig = tlsConfig
+ } else if tr, ok := c.client.Transport.(*http2.Transport); ok {
+ tr.TLSClientConfig = tlsConfig
+ } else {
+ panic(fmt.Sprintf("unknown transport type: %T", c.client.Transport))
+ }
}
-func (c *defaultHTTPClient) hasCertificates(tlsConfig *tls.Config, certs []tls.Certificate) bool {
- if tlsConfig == nil {
- return false
- }
- if len(tlsConfig.Certificates) != len(certs) {
- return false
+func ForceHTTP2(client HTTPClient, certificates []tls.Certificate) {
+ c, ok := client.(*defaultHTTPClient)
+ if !ok {
+ return
}
- for i := 0; i < len(certs); i++ {
- if len(tlsConfig.Certificates[i].Certificate) != len(certs[i].Certificate) {
- return false
+ var tlsConfig *tls.Config = nil
+ var dialFunc func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error)
+ if certificates != nil {
+ tlsConfig = &tls.Config{
+ Certificates: certificates,
+ MinVersion: tls.VersionTLS12,
}
- for j := 0; j < len(certs[i].Certificate); j++ {
- if !bytes.Equal(tlsConfig.Certificates[i].Certificate[j], certs[i].Certificate[j]) {
- return false
- }
+ } else {
+ // No certificate, so force H2C (HTTP/2 over clear-text) by using a non-TLS Dialer
+ dialer := net.Dialer{}
+ dialFunc = func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
+ return dialer.DialContext(ctx, network, addr)
}
}
- return true
+ // Use HTTP/2 transport explicitly. Connection reuse does not work properly when using regular http.Transport, even
+ // though it upgrades to HTTP/2 automatically
+ // https://github.com/golang/go/issues/16582
+ // https://github.com/golang/go/issues/22091
+ c.client.Transport = &http2.Transport{
+ AllowHTTP: true,
+ TLSClientConfig: tlsConfig,
+ DialTLSContext: dialFunc,
+ }
}
func CreateClient(timeout time.Duration) HTTPClient {
diff --git a/client/go/internal/vespa/document/dispatcher.go b/client/go/internal/vespa/document/dispatcher.go
index 7011ae7a9b6..838a7bc45ee 100644
--- a/client/go/internal/vespa/document/dispatcher.go
+++ b/client/go/internal/vespa/document/dispatcher.go
@@ -1,7 +1,9 @@
package document
import (
+ "container/list"
"fmt"
+ "io"
"sync"
"sync/atomic"
"time"
@@ -16,64 +18,70 @@ type Dispatcher struct {
circuitBreaker CircuitBreaker
stats Stats
- closed bool
+ started bool
ready chan Id
results chan Result
inflight map[string]*documentGroup
inflightCount int64
+ errWriter io.Writer
mu sync.RWMutex
wg sync.WaitGroup
resultWg sync.WaitGroup
}
-// documentGroup holds document operations which share their ID, and must be dispatched in order.
-type documentGroup struct {
- id Id
- operations []documentOp
- mu sync.Mutex
-}
-
+// documentOp represents a document operation and the number of times it has been attempted.
type documentOp struct {
document Document
attempts int
}
-func (g *documentGroup) append(op documentOp) {
+// documentGroup holds document operations which share an ID, and must be dispatched in order.
+type documentGroup struct {
+ ops *list.List
+ mu sync.Mutex
+}
+
+func (g *documentGroup) add(op documentOp, first bool) {
g.mu.Lock()
defer g.mu.Unlock()
- g.operations = append(g.operations, op)
+ if g.ops == nil {
+ g.ops = list.New()
+ }
+ if first {
+ g.ops.PushFront(op)
+ } else {
+ g.ops.PushBack(op)
+ }
}
-func NewDispatcher(feeder Feeder, throttler Throttler, breaker CircuitBreaker) *Dispatcher {
+func NewDispatcher(feeder Feeder, throttler Throttler, breaker CircuitBreaker, errWriter io.Writer) *Dispatcher {
d := &Dispatcher{
feeder: feeder,
throttler: throttler,
circuitBreaker: breaker,
inflight: make(map[string]*documentGroup),
+ errWriter: errWriter,
}
d.start()
return d
}
-func (d *Dispatcher) dispatchAll(g *documentGroup) {
- g.mu.Lock()
- defer g.mu.Unlock()
- for i := 0; i < len(g.operations); i++ {
- op := g.operations[i]
- ok := false
- for !ok {
- op.attempts++
- result := d.feeder.Send(op.document)
- d.results <- result
- ok = result.Status.Success()
- if !d.shouldRetry(op, result) {
- break
- }
- }
- d.releaseSlot()
+func (d *Dispatcher) sendDocumentIn(group *documentGroup) {
+ group.mu.Lock()
+ defer group.mu.Unlock()
+ defer d.releaseSlot()
+ first := group.ops.Front()
+ if first == nil {
+ panic("sending from empty document group, this should not happen")
+ }
+ op := group.ops.Remove(first).(documentOp)
+ op.attempts++
+ result := d.feeder.Send(op.document)
+ d.results <- result
+ if d.shouldRetry(op, result) {
+ d.enqueue(op)
}
- g.operations = nil
}
func (d *Dispatcher) shouldRetry(op documentOp, result Result) bool {
@@ -83,12 +91,26 @@ func (d *Dispatcher) shouldRetry(op documentOp, result Result) bool {
return false
}
if result.HTTPStatus == 429 || result.HTTPStatus == 503 {
+ fmt.Fprintf(d.errWriter, "feed: %s was throttled with status %d: retrying\n", op.document, result.HTTPStatus)
d.throttler.Throttled(atomic.LoadInt64(&d.inflightCount))
return true
}
- if result.HTTPStatus == 500 || result.HTTPStatus == 502 || result.HTTPStatus == 504 {
+ if result.Err != nil || result.HTTPStatus == 500 || result.HTTPStatus == 502 || result.HTTPStatus == 504 {
+ retry := op.attempts <= maxAttempts
+ msg := "feed: " + op.document.String() + " failed with "
+ if result.Err != nil {
+ msg += "error " + result.Err.Error()
+ } else {
+ msg += fmt.Sprintf("status %d", result.HTTPStatus)
+ }
+ if retry {
+ msg += ": retrying"
+ } else {
+ msg += fmt.Sprintf(": giving up after %d attempts", maxAttempts)
+ }
+ fmt.Fprintln(d.errWriter, msg)
d.circuitBreaker.Error(fmt.Errorf("request failed with status %d", result.HTTPStatus))
- if op.attempts <= maxAttempts {
+ if retry {
return true
}
}
@@ -98,9 +120,12 @@ func (d *Dispatcher) shouldRetry(op documentOp, result Result) bool {
func (d *Dispatcher) start() {
d.mu.Lock()
defer d.mu.Unlock()
+ if d.started {
+ return
+ }
d.ready = make(chan Id, 4096)
d.results = make(chan Result, 4096)
- d.closed = false
+ d.started = true
d.wg.Add(1)
go func() {
defer d.wg.Done()
@@ -118,13 +143,11 @@ func (d *Dispatcher) readDocuments() {
d.mu.RLock()
group := d.inflight[id.String()]
d.mu.RUnlock()
- if group != nil {
- d.wg.Add(1)
- go func() {
- defer d.wg.Done()
- d.dispatchAll(group)
- }()
- }
+ d.wg.Add(1)
+ go func() {
+ defer d.wg.Done()
+ d.sendDocumentIn(group)
+ }()
}
}
@@ -134,28 +157,22 @@ func (d *Dispatcher) readResults() {
}
}
-func (d *Dispatcher) Enqueue(doc Document) error {
+func (d *Dispatcher) enqueue(op documentOp) error {
d.mu.Lock()
- if d.closed {
+ if !d.started {
return fmt.Errorf("dispatcher is closed")
}
- group, ok := d.inflight[doc.Id.String()]
- if ok {
- group.append(documentOp{document: doc})
- } else {
- group = &documentGroup{
- id: doc.Id,
- operations: []documentOp{{document: doc}},
- }
- d.inflight[doc.Id.String()] = group
+ group, ok := d.inflight[op.document.Id.String()]
+ if !ok {
+ group = &documentGroup{}
+ d.inflight[op.document.Id.String()] = group
}
d.mu.Unlock()
- d.enqueueWithSlot(doc.Id)
+ group.add(op, op.attempts > 0)
+ d.enqueueWithSlot(op.document.Id)
return nil
}
-func (d *Dispatcher) Stats() Stats { return d.stats }
-
func (d *Dispatcher) enqueueWithSlot(id Id) {
d.acquireSlot()
d.ready <- id
@@ -173,16 +190,20 @@ func (d *Dispatcher) releaseSlot() { atomic.AddInt64(&d.inflightCount, -1) }
func closeAndWait[T any](ch chan T, wg *sync.WaitGroup, d *Dispatcher, markClosed bool) {
d.mu.Lock()
- if !d.closed {
+ if d.started {
close(ch)
if markClosed {
- d.closed = true
+ d.started = false
}
}
d.mu.Unlock()
wg.Wait()
}
+func (d *Dispatcher) Enqueue(doc Document) error { return d.enqueue(documentOp{document: doc}) }
+
+func (d *Dispatcher) Stats() Stats { return d.stats }
+
// Close closes the dispatcher and waits for all inflight operations to complete.
func (d *Dispatcher) Close() error {
closeAndWait(d.ready, &d.wg, d, false)
diff --git a/client/go/internal/vespa/document/dispatcher_test.go b/client/go/internal/vespa/document/dispatcher_test.go
index 8a6d8c6117c..80bc5f603ae 100644
--- a/client/go/internal/vespa/document/dispatcher_test.go
+++ b/client/go/internal/vespa/document/dispatcher_test.go
@@ -1,6 +1,7 @@
package document
import (
+ "io"
"sync"
"testing"
"time"
@@ -29,7 +30,7 @@ func (f *mockFeeder) Send(doc Document) Result {
} else {
f.documents = append(f.documents, doc)
}
- if !result.Status.Success() {
+ if !result.Success() {
result.Stats.Errors = 1
}
return result
@@ -38,9 +39,9 @@ func (f *mockFeeder) Send(doc Document) Result {
func TestDispatcher(t *testing.T) {
feeder := &mockFeeder{}
clock := &manualClock{tick: time.Second}
- throttler := newThrottler(clock.now)
+ throttler := newThrottler(8, clock.now)
breaker := NewCircuitBreaker(time.Second, 0)
- dispatcher := NewDispatcher(feeder, throttler, breaker)
+ dispatcher := NewDispatcher(feeder, throttler, breaker, io.Discard)
docs := []Document{
{Id: mustParseId("id:ns:type::doc1"), Operation: OperationPut, Body: []byte(`{"fields":{"foo": "123"}}`)},
{Id: mustParseId("id:ns:type::doc2"), Operation: OperationPut, Body: []byte(`{"fields":{"bar": "456"}}`)},
@@ -71,9 +72,9 @@ func TestDispatcherOrdering(t *testing.T) {
{Id: mustParseId("id:ns:type::doc9"), Operation: OperationPut},
}
clock := &manualClock{tick: time.Second}
- throttler := newThrottler(clock.now)
+ throttler := newThrottler(8, clock.now)
breaker := NewCircuitBreaker(time.Second, 0)
- dispatcher := NewDispatcher(feeder, throttler, breaker)
+ dispatcher := NewDispatcher(feeder, throttler, breaker, io.Discard)
for _, d := range docs {
dispatcher.Enqueue(d)
}
@@ -107,9 +108,9 @@ func TestDispatcherOrderingWithFailures(t *testing.T) {
}
feeder.failAfterN(2)
clock := &manualClock{tick: time.Second}
- throttler := newThrottler(clock.now)
+ throttler := newThrottler(8, clock.now)
breaker := NewCircuitBreaker(time.Second, 0)
- dispatcher := NewDispatcher(feeder, throttler, breaker)
+ dispatcher := NewDispatcher(feeder, throttler, breaker, io.Discard)
for _, d := range docs {
dispatcher.Enqueue(d)
}
diff --git a/client/go/internal/vespa/document/document.go b/client/go/internal/vespa/document/document.go
index 98cb2d1b6c6..efb60ad8c0a 100644
--- a/client/go/internal/vespa/document/document.go
+++ b/client/go/internal/vespa/document/document.go
@@ -130,6 +130,27 @@ type Decoder struct {
jsonl bool
}
+func (d Document) String() string {
+ var sb strings.Builder
+ switch d.Operation {
+ case OperationPut:
+ sb.WriteString("put ")
+ case OperationUpdate:
+ sb.WriteString("update ")
+ case OperationRemove:
+ sb.WriteString("remove ")
+ }
+ sb.WriteString(d.Id.String())
+ if d.Condition != "" {
+ sb.WriteString(", condition=")
+ sb.WriteString(d.Condition)
+ }
+ if d.Create {
+ sb.WriteString(", create=true")
+ }
+ return sb.String()
+}
+
func (d *Decoder) guessMode() error {
for !d.array && !d.jsonl {
b, err := d.buf.ReadByte()
diff --git a/client/go/internal/vespa/document/feeder.go b/client/go/internal/vespa/document/feeder.go
index 8bdd5bca5ba..9e6768d0eb4 100644
--- a/client/go/internal/vespa/document/feeder.go
+++ b/client/go/internal/vespa/document/feeder.go
@@ -17,8 +17,6 @@ const (
// StatusTransportFailure indicates that there was failure in the transport layer error while sending the document
// operation to Vespa.
StatusTransportFailure
- // StatusError is a catch-all status for any other error that might occur.
- StatusError
)
// Result represents the result of a feeding operation.
@@ -32,8 +30,9 @@ type Result struct {
Stats Stats
}
-// Success returns whether status s is considered a success.
-func (s Status) Success() bool { return s == StatusSuccess || s == StatusConditionNotMet }
+func (r Result) Success() bool {
+ return r.Err == nil && (r.Status == StatusSuccess || r.Status == StatusConditionNotMet)
+}
// Stats represents feeding operation statistics.
type Stats struct {
diff --git a/client/go/internal/vespa/document/http.go b/client/go/internal/vespa/document/http.go
index 4dadcd1d05c..588330a0574 100644
--- a/client/go/internal/vespa/document/http.go
+++ b/client/go/internal/vespa/document/http.go
@@ -5,10 +5,12 @@ import (
"encoding/json"
"fmt"
"io"
+ "math"
"net/http"
"net/url"
"strconv"
"strings"
+ "sync/atomic"
"time"
"github.com/vespa-engine/vespa/client/go/internal/util"
@@ -16,9 +18,10 @@ import (
// Client represents a HTTP client for the /document/v1/ API.
type Client struct {
- options ClientOptions
- httpClient util.HTTPClient
- now func() time.Time
+ options ClientOptions
+ httpClients []countingHTTPClient
+ now func() time.Time
+ sendCount int32
}
// ClientOptions specifices the configuration options of a feed client.
@@ -29,6 +32,18 @@ type ClientOptions struct {
TraceLevel *int
}
+type countingHTTPClient struct {
+ client util.HTTPClient
+ inflight int64
+}
+
+func (c *countingHTTPClient) addInflight(n int64) { atomic.AddInt64(&c.inflight, n) }
+
+func (c *countingHTTPClient) Do(req *http.Request, timeout time.Duration) (*http.Response, error) {
+ defer c.addInflight(-1)
+ return c.client.Do(req, timeout)
+}
+
type countingReader struct {
reader io.Reader
bytesRead int64
@@ -40,13 +55,19 @@ func (r *countingReader) Read(p []byte) (int, error) {
return n, err
}
-func NewClient(options ClientOptions, httpClient util.HTTPClient) *Client {
- c := &Client{
- options: options,
- httpClient: httpClient,
- now: time.Now,
+func NewClient(options ClientOptions, httpClients []util.HTTPClient) *Client {
+ if len(httpClients) < 1 {
+ panic("need at least one HTTP client")
+ }
+ countingClients := make([]countingHTTPClient, 0, len(httpClients))
+ for _, client := range httpClients {
+ countingClients = append(countingClients, countingHTTPClient{client: client})
+ }
+ return &Client{
+ options: options,
+ httpClients: countingClients,
+ now: time.Now,
}
- return c
}
func (c *Client) queryParams() url.Values {
@@ -109,45 +130,56 @@ func (c *Client) feedURL(d Document, queryParams url.Values) (string, *url.URL,
return httpMethod, u, nil
}
-// Send given document the URL configured in this client.
+func (c *Client) leastBusyClient() *countingHTTPClient {
+ leastBusy := c.httpClients[0]
+ min := int64(math.MaxInt64)
+ next := atomic.AddInt32(&c.sendCount, 1)
+ start := int(next) % len(c.httpClients)
+ for i := range c.httpClients {
+ j := (i + start) % len(c.httpClients)
+ client := c.httpClients[j]
+ inflight := atomic.LoadInt64(&client.inflight)
+ if inflight < min {
+ leastBusy = client
+ min = inflight
+ }
+ }
+ leastBusy.addInflight(1)
+ return &leastBusy
+}
+
+// Send given document to the endpoint configured in this client.
func (c *Client) Send(document Document) Result {
start := c.now()
- result := Result{Id: document.Id}
- result.Stats.Requests = 1
+ result := Result{Id: document.Id, Stats: Stats{Requests: 1}}
method, url, err := c.feedURL(document, c.queryParams())
if err != nil {
- result.Stats.Errors = 1
- result.Err = err
- return result
+ return resultWithErr(result, err)
}
req, err := http.NewRequest(method, url.String(), bytes.NewReader(document.Body))
if err != nil {
- result.Stats.Errors = 1
- result.Status = StatusError
- result.Err = err
- return result
+ return resultWithErr(result, err)
}
- resp, err := c.httpClient.Do(req, 190*time.Second)
+ resp, err := c.leastBusyClient().Do(req, 190*time.Second)
if err != nil {
- result.Stats.Errors = 1
- result.Status = StatusTransportFailure
- result.Err = err
- return result
+ return resultWithErr(result, err)
}
defer resp.Body.Close()
- result.Stats.Responses = 1
- result.Stats.ResponsesByCode = map[int]int64{
- resp.StatusCode: 1,
- }
- result.Stats.BytesSent = int64(len(document.Body))
elapsed := c.now().Sub(start)
- result.Stats.TotalLatency = elapsed
- result.Stats.MinLatency = elapsed
- result.Stats.MaxLatency = elapsed
- return c.resultWithResponse(resp, result)
+ return c.resultWithResponse(resp, result, document, elapsed)
+}
+
+func resultWithErr(result Result, err error) Result {
+ result.Stats.Errors++
+ result.Status = StatusTransportFailure
+ result.Err = err
+ return result
}
-func (c *Client) resultWithResponse(resp *http.Response, result Result) Result {
+func (c *Client) resultWithResponse(resp *http.Response, result Result, document Document, elapsed time.Duration) Result {
+ result.HTTPStatus = resp.StatusCode
+ result.Stats.Responses++
+ result.Stats.ResponsesByCode = map[int]int64{resp.StatusCode: 1}
switch resp.StatusCode {
case 200:
result.Status = StatusSuccess
@@ -165,14 +197,18 @@ func (c *Client) resultWithResponse(resp *http.Response, result Result) Result {
cr := countingReader{reader: resp.Body}
jsonDec := json.NewDecoder(&cr)
if err := jsonDec.Decode(&body); err != nil {
- result.Status = StatusError
+ result.Status = StatusVespaFailure
result.Err = fmt.Errorf("failed to decode json response: %w", err)
}
result.Message = body.Message
result.Trace = string(body.Trace)
+ result.Stats.BytesSent = int64(len(document.Body))
result.Stats.BytesRecv = cr.bytesRead
- if !result.Status.Success() {
- result.Stats.Errors = 1
+ if !result.Success() {
+ result.Stats.Errors++
}
+ result.Stats.TotalLatency = elapsed
+ result.Stats.MinLatency = elapsed
+ result.Stats.MaxLatency = elapsed
return result
}
diff --git a/client/go/internal/vespa/document/http_test.go b/client/go/internal/vespa/document/http_test.go
index 311668fa16e..43eaf1bfdf9 100644
--- a/client/go/internal/vespa/document/http_test.go
+++ b/client/go/internal/vespa/document/http_test.go
@@ -11,6 +11,7 @@ import (
"time"
"github.com/vespa-engine/vespa/client/go/internal/mock"
+ "github.com/vespa-engine/vespa/client/go/internal/util"
)
type manualClock struct {
@@ -25,6 +26,37 @@ func (c *manualClock) now() time.Time {
func (c *manualClock) advance(d time.Duration) { c.t = c.t.Add(d) }
+type mockHTTPClient struct {
+ id int
+ *mock.HTTPClient
+}
+
+func TestLeastBusyClient(t *testing.T) {
+ httpClient := mock.HTTPClient{}
+ var httpClients []util.HTTPClient
+ for i := 0; i < 4; i++ {
+ httpClients = append(httpClients, &mockHTTPClient{i, &httpClient})
+ }
+ client := NewClient(ClientOptions{}, httpClients)
+ client.httpClients[0].addInflight(1)
+ client.httpClients[1].addInflight(1)
+ assertLeastBusy(t, 2, client)
+ assertLeastBusy(t, 2, client)
+ assertLeastBusy(t, 3, client)
+ client.httpClients[3].addInflight(1)
+ client.httpClients[1].addInflight(-1)
+ assertLeastBusy(t, 1, client)
+}
+
+func assertLeastBusy(t *testing.T, id int, client *Client) {
+ t.Helper()
+ leastBusy := client.leastBusyClient()
+ got := leastBusy.client.(*mockHTTPClient).id
+ if got != id {
+ t.Errorf("got client.id=%d, want %d", got, id)
+ }
+}
+
func TestClientSend(t *testing.T) {
docs := []Document{
{Create: true, Id: mustParseId("id:ns:type::doc1"), Operation: OperationUpdate, Body: []byte(`{"fields":{"foo": "123"}}`)},
@@ -35,21 +67,43 @@ func TestClientSend(t *testing.T) {
client := NewClient(ClientOptions{
BaseURL: "https://example.com:1337",
Timeout: time.Duration(5 * time.Second),
- }, &httpClient)
+ }, []util.HTTPClient{&httpClient})
clock := manualClock{t: time.Now(), tick: time.Second}
client.now = clock.now
var stats Stats
for i, doc := range docs {
+ wantRes := Result{
+ Id: doc.Id,
+ Stats: Stats{
+ Requests: 1,
+ Responses: 1,
+ TotalLatency: time.Second,
+ MinLatency: time.Second,
+ MaxLatency: time.Second,
+ BytesSent: 25,
+ },
+ }
if i < 2 {
httpClient.NextResponseString(200, `{"message":"All good!"}`)
+ wantRes.Status = StatusSuccess
+ wantRes.HTTPStatus = 200
+ wantRes.Message = "All good!"
+ wantRes.Stats.ResponsesByCode = map[int]int64{200: 1}
+ wantRes.Stats.BytesRecv = 23
} else {
httpClient.NextResponseString(502, `{"message":"Good bye, cruel world!"}`)
+ wantRes.Status = StatusVespaFailure
+ wantRes.HTTPStatus = 502
+ wantRes.Message = "Good bye, cruel world!"
+ wantRes.Stats.ResponsesByCode = map[int]int64{502: 1}
+ wantRes.Stats.Errors = 1
+ wantRes.Stats.BytesRecv = 36
}
res := client.Send(doc)
- stats.Add(res.Stats)
- if res.Err != nil {
- t.Fatalf("got unexpected error %q", res.Err)
+ if !reflect.DeepEqual(res, wantRes) {
+ t.Fatalf("got result %+v, want %+v", res, wantRes)
}
+ stats.Add(res.Stats)
r := httpClient.LastRequest
if r.Method != http.MethodPut {
t.Errorf("got r.Method = %q, want %q", r.Method, http.MethodPut)
@@ -176,7 +230,7 @@ func TestClientFeedURL(t *testing.T) {
httpClient := mock.HTTPClient{}
client := NewClient(ClientOptions{
BaseURL: "https://example.com",
- }, &httpClient)
+ }, []util.HTTPClient{&httpClient})
for i, tt := range tests {
moreParams := url.Values{}
moreParams.Set("foo", "ba/r")
diff --git a/client/go/internal/vespa/document/throttler.go b/client/go/internal/vespa/document/throttler.go
index 69bb7c8d7ac..5b0aab6174e 100644
--- a/client/go/internal/vespa/document/throttler.go
+++ b/client/go/internal/vespa/document/throttler.go
@@ -7,13 +7,7 @@ import (
"time"
)
-const (
- throttlerWeight = 0.7
- // TODO(mpolden): Multiply this by connections per endpoint, and number of endpoints when this becomes configurable
- // for local target
- throttlerMinInflight = 16
- throttlerMaxInflight = 256 * throttlerMinInflight // 4096 max streams per connection on the server side
-)
+const throttlerWeight = 0.7
type Throttler interface {
// Sent notifies the the throttler that a document has been sent.
@@ -27,29 +21,38 @@ type Throttler interface {
}
type dynamicThrottler struct {
- ok int64
+ minInflight int64
+ maxInflight int64
targetInflight int64
targetTimesTen int64
throughputs []float64
+ ok int64
sent int64
start time.Time
now func() time.Time
}
-func newThrottler(nowFunc func() time.Time) *dynamicThrottler {
+func newThrottler(connections int, nowFunc func() time.Time) *dynamicThrottler {
+ var (
+ minInflight = 16 * int64(connections)
+ maxInflight = 256 * minInflight // 4096 max streams per connection on the server side
+ )
return &dynamicThrottler{
+ minInflight: minInflight,
+ maxInflight: maxInflight,
+ targetInflight: 8 * minInflight,
+ targetTimesTen: 10 * maxInflight,
+
throughputs: make([]float64, 128),
- start: nowFunc(),
- now: nowFunc,
- targetInflight: 8 * throttlerMinInflight,
- targetTimesTen: 10 * throttlerMaxInflight,
+ start: nowFunc(),
+ now: nowFunc,
}
}
-func NewThrottler() Throttler { return newThrottler(time.Now) }
+func NewThrottler(connections int) Throttler { return newThrottler(connections, time.Now) }
func (t *dynamicThrottler) Sent() {
currentInflight := atomic.LoadInt64(&t.targetInflight)
@@ -64,7 +67,7 @@ func (t *dynamicThrottler) Sent() {
currentThroughput := float64(atomic.SwapInt64(&t.ok, 0)) / float64(elapsed)
// Use buckets for throughput over inflight, along the log-scale, in [minInflight, maxInflight).
- index := int(float64(len(t.throughputs)) * math.Log(max(1, min(255, float64(currentInflight)/throttlerMinInflight))) / math.Log(256))
+ index := int(float64(len(t.throughputs)) * math.Log(max(1, min(255, float64(currentInflight)/float64(t.minInflight)))) / math.Log(256))
t.throughputs[index] = currentThroughput
// Loop over throughput measurements and pick the one which optimises throughput and latency.
@@ -74,7 +77,7 @@ func (t *dynamicThrottler) Sent() {
if t.throughputs[i] == 0 {
continue // Skip unknown values
}
- inflight := float64(throttlerMinInflight) * math.Pow(256, (float64(i)+0.5)/float64(len(t.throughputs)))
+ inflight := float64(t.minInflight) * math.Pow(256, (float64(i)+0.5)/float64(len(t.throughputs)))
objective := t.throughputs[i] * math.Pow(inflight, throttlerWeight-1) // Optimise throughput (weight), but also latency (1 - weight)
if objective > maxObjective {
maxObjective = objective
@@ -82,7 +85,7 @@ func (t *dynamicThrottler) Sent() {
}
}
target := int64((rand.Float64()*0.20 + 0.92) * choice) // Random walk, skewed towards increase
- atomic.StoreInt64(&t.targetInflight, max(throttlerMinInflight, min(throttlerMaxInflight, target)))
+ atomic.StoreInt64(&t.targetInflight, max(t.minInflight, min(t.maxInflight, target)))
}
func (t *dynamicThrottler) Success() {
@@ -91,11 +94,11 @@ func (t *dynamicThrottler) Success() {
}
func (t *dynamicThrottler) Throttled(inflight int64) {
- atomic.StoreInt64(&t.targetTimesTen, max(inflight*5, throttlerMinInflight*10))
+ atomic.StoreInt64(&t.targetTimesTen, max(inflight*5, t.minInflight*10))
}
func (t *dynamicThrottler) TargetInflight() int64 {
- staticTargetInflight := min(throttlerMaxInflight, atomic.LoadInt64(&t.targetTimesTen)/10)
+ staticTargetInflight := min(t.maxInflight, atomic.LoadInt64(&t.targetTimesTen)/10)
targetInflight := atomic.LoadInt64(&t.targetInflight)
return min(staticTargetInflight, targetInflight)
}
diff --git a/client/go/internal/vespa/document/throttler_test.go b/client/go/internal/vespa/document/throttler_test.go
index 2fd1e73a45a..a22f059207f 100644
--- a/client/go/internal/vespa/document/throttler_test.go
+++ b/client/go/internal/vespa/document/throttler_test.go
@@ -7,15 +7,15 @@ import (
func TestThrottler(t *testing.T) {
clock := &manualClock{tick: time.Second}
- tr := newThrottler(clock.now)
+ tr := newThrottler(8, clock.now)
for i := 0; i < 100; i++ {
tr.Sent()
}
- if got, want := tr.TargetInflight(), int64(128); got != want {
+ if got, want := tr.TargetInflight(), int64(1024); got != want {
t.Errorf("got TargetInflight() = %d, but want %d", got, want)
}
tr.Throttled(5)
- if got, want := tr.TargetInflight(), int64(16); got != want {
+ if got, want := tr.TargetInflight(), int64(128); got != want {
t.Errorf("got TargetInflight() = %d, but want %d", got, want)
}
}
diff --git a/client/go/internal/vespa/target.go b/client/go/internal/vespa/target.go
index 51861eb12ab..bc936623bcb 100644
--- a/client/go/internal/vespa/target.go
+++ b/client/go/internal/vespa/target.go
@@ -74,7 +74,7 @@ type Target interface {
// TLSOptions configures the client certificate to use for cloud API or service requests.
type TLSOptions struct {
- KeyPair *tls.Certificate
+ KeyPair []tls.Certificate
CertificateFile string
PrivateKeyFile string
AthenzDomain string
@@ -93,7 +93,7 @@ type LogOptions struct {
// Do sends request to this service. Any required authentication happens automatically.
func (s *Service) Do(request *http.Request, timeout time.Duration) (*http.Response, error) {
if s.TLSOptions.AthenzDomain != "" && s.TLSOptions.KeyPair != nil {
- accessToken, err := s.zts.AccessToken(s.TLSOptions.AthenzDomain, *s.TLSOptions.KeyPair)
+ accessToken, err := s.zts.AccessToken(s.TLSOptions.AthenzDomain, s.TLSOptions.KeyPair[0])
if err != nil {
return nil, err
}
@@ -105,6 +105,8 @@ func (s *Service) Do(request *http.Request, timeout time.Duration) (*http.Respon
return s.httpClient.Do(request, timeout)
}
+func (s *Service) Client() util.HTTPClient { return s.httpClient }
+
// Wait polls the health check of this service until it succeeds or timeout passes.
func (s *Service) Wait(timeout time.Duration) (int, error) {
url := s.BaseURL
@@ -139,18 +141,18 @@ type requestFunc func() *http.Request
// waitForOK queries url and returns its status code. If the url returns a non-200 status code, it is repeatedly queried
// until timeout elapses.
-func waitForOK(client util.HTTPClient, url string, certificate *tls.Certificate, timeout time.Duration) (int, error) {
+func waitForOK(client util.HTTPClient, url string, certificates []tls.Certificate, timeout time.Duration) (int, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return 0, err
}
okFunc := func(status int, response []byte) (bool, error) { return isOK(status), nil }
- return wait(client, okFunc, func() *http.Request { return req }, certificate, timeout)
+ return wait(client, okFunc, func() *http.Request { return req }, certificates, timeout)
}
-func wait(client util.HTTPClient, fn responseFunc, reqFn requestFunc, certificate *tls.Certificate, timeout time.Duration) (int, error) {
- if certificate != nil {
- util.SetCertificate(client, []tls.Certificate{*certificate})
+func wait(client util.HTTPClient, fn responseFunc, reqFn requestFunc, certificates []tls.Certificate, timeout time.Duration) (int, error) {
+ if certificates != nil {
+ util.SetCertificates(client, certificates)
}
var (
httpErr error
diff --git a/client/go/internal/vespa/target_cloud.go b/client/go/internal/vespa/target_cloud.go
index 2335d4f3432..1fb3edd78c5 100644
--- a/client/go/internal/vespa/target_cloud.go
+++ b/client/go/internal/vespa/target_cloud.go
@@ -161,7 +161,7 @@ func (t *cloudTarget) Service(name string, timeout time.Duration, runID int64, c
}
if service.TLSOptions.KeyPair != nil {
- util.SetCertificate(service.httpClient, []tls.Certificate{*service.TLSOptions.KeyPair})
+ util.SetCertificates(service.httpClient, service.TLSOptions.KeyPair)
}
return service, nil
}
@@ -175,7 +175,7 @@ func (t *cloudTarget) SignRequest(req *http.Request, keyID string) error {
return t.addAuth0AccessToken(req)
}
} else {
- if t.apiOptions.TLSOptions.KeyPair.Certificate == nil {
+ if t.apiOptions.TLSOptions.KeyPair == nil {
return fmt.Errorf("system %s requires a certificate for authentication", t.apiOptions.System.Name)
}
return nil
diff --git a/config-model/src/main/java/com/yahoo/schema/OnnxModel.java b/config-model/src/main/java/com/yahoo/schema/OnnxModel.java
index 272b668b5fb..90a27d1f036 100644
--- a/config-model/src/main/java/com/yahoo/schema/OnnxModel.java
+++ b/config-model/src/main/java/com/yahoo/schema/OnnxModel.java
@@ -1,15 +1,17 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.schema;
+import com.yahoo.searchlib.rankingexpression.Reference;
import com.yahoo.tensor.TensorType;
import com.yahoo.vespa.model.ml.OnnxModelInfo;
-import com.yahoo.searchlib.rankingexpression.Reference;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
/**
* A global ONNX model distributed using file distribution, similar to ranking constants.
@@ -21,6 +23,7 @@ public class OnnxModel extends DistributableResource {
private OnnxModelInfo modelInfo = null;
private final Map<String, String> inputMap = new HashMap<>();
private final Map<String, String> outputMap = new HashMap<>();
+ private final Set<String> initializers = new HashSet<>();
private String statelessExecutionMode = null;
private Integer statelessInterOpThreads = null;
@@ -101,11 +104,13 @@ public class OnnxModel extends DistributableResource {
for (String onnxName : modelInfo.getOutputs()) {
addOutputNameMapping(onnxName, OnnxModelInfo.asValidIdentifier(onnxName), false);
}
+ initializers.addAll(modelInfo.getInitializers());
this.modelInfo = modelInfo;
}
public Map<String, String> getInputMap() { return Collections.unmodifiableMap(inputMap); }
public Map<String, String> getOutputMap() { return Collections.unmodifiableMap(outputMap); }
+ public Set<String> getInitializers() { return Set.copyOf(initializers); }
public String getDefaultOutput() {
return modelInfo != null ? modelInfo.getDefaultOutput() : "";
diff --git a/config-model/src/main/java/com/yahoo/schema/expressiontransforms/InputRecorder.java b/config-model/src/main/java/com/yahoo/schema/expressiontransforms/InputRecorder.java
index af072c5b59a..7f578f07fe3 100644
--- a/config-model/src/main/java/com/yahoo/schema/expressiontransforms/InputRecorder.java
+++ b/config-model/src/main/java/com/yahoo/schema/expressiontransforms/InputRecorder.java
@@ -2,7 +2,6 @@
package com.yahoo.schema.expressiontransforms;
import com.yahoo.schema.FeatureNames;
-import com.yahoo.schema.RankProfile;
import com.yahoo.searchlib.rankingexpression.RankingExpression;
import com.yahoo.searchlib.rankingexpression.Reference;
import com.yahoo.searchlib.rankingexpression.parser.ParseException;
@@ -12,13 +11,12 @@ import com.yahoo.searchlib.rankingexpression.rule.ExpressionNode;
import com.yahoo.searchlib.rankingexpression.rule.ReferenceNode;
import com.yahoo.searchlib.rankingexpression.rule.TensorFunctionNode;
import com.yahoo.searchlib.rankingexpression.transform.ExpressionTransformer;
-import com.yahoo.tensor.functions.DynamicTensor;
import com.yahoo.tensor.functions.Generate;
-import com.yahoo.tensor.functions.Slice;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Set;
+import java.util.logging.Logger;
/**
* Analyzes expression to figure out what inputs it needs
@@ -27,6 +25,8 @@ import java.util.Set;
*/
public class InputRecorder extends ExpressionTransformer<InputRecorderContext> {
+ private static final Logger log = Logger.getLogger(InputRecorder.class.getName());
+
private final Set<String> neededInputs;
private final Set<String> handled = new HashSet<>();
@@ -120,7 +120,11 @@ public class InputRecorder extends ExpressionTransformer<InputRecorderContext> {
if (model == null) {
throw new IllegalArgumentException("missing onnx model: " + arg);
}
- for (String onnxInput : model.getInputMap().values()) {
+ model.getInputMap().forEach((onnxName, onnxInput) -> {
+ if (model.getInitializers().contains(onnxName)) {
+ log.fine(() -> "For input '%s': skipping name '%s' as it's an initializer".formatted(onnxInput, onnxName));
+ return;
+ }
var reader = new StringReader(onnxInput);
try {
var asExpression = new RankingExpression(reader);
@@ -128,7 +132,7 @@ public class InputRecorder extends ExpressionTransformer<InputRecorderContext> {
} catch (ParseException e) {
throw new IllegalArgumentException("illegal onnx input '" + onnxInput + "': " + e.getMessage());
}
- }
+ });
return;
}
neededInputs.add(feature.toString());
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java
index 0cc52edf3cc..b1eace947cc 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidator.java
@@ -2,11 +2,15 @@
package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ConfigChangeAction;
+import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.config.application.api.ValidationId;
+import com.yahoo.vespa.model.container.ApplicationContainer;
+import com.yahoo.vespa.model.container.ApplicationContainerCluster;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -19,16 +23,23 @@ public class ContentClusterRemovalValidator implements ChangeValidator {
@Override
public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, DeployState deployState) {
+ List<ConfigChangeAction> actions = new ArrayList<>();
for (String currentClusterId : current.getContentClusters().keySet()) {
ContentCluster nextCluster = next.getContentClusters().get(currentClusterId);
- if (nextCluster == null)
+ if (nextCluster == null) {
deployState.validationOverrides().invalid(ValidationId.contentClusterRemoval,
- "Content cluster '" + currentClusterId + "' is removed. " +
- "This will cause loss of all data in this cluster",
- deployState.now());
- }
+ "Content cluster '" + currentClusterId + "' is removed. " +
+ "This will cause loss of all data in this cluster",
+ deployState.now());
- return List.of();
+ // If we allow the removal, we must restart all containers to ensure mbus is OK.
+ for (ApplicationContainerCluster cluster : next.getContainerClusters().values()) {
+ actions.add(new VespaRestartAction(cluster.id(),
+ "Content cluster '" + currentClusterId + "' has been removed",
+ cluster.getContainers().stream().map(ApplicationContainer::getServiceInfo).toList()));
+ }
+ }
+ }
+ return actions;
}
-
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java b/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java
index 5e8bb85c29d..2b5dadf5512 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java
@@ -51,15 +51,18 @@ public class IdentityProvider extends SimpleComponent implements IdentityConfig.
builder.loadBalancerAddress(loadBalancerName.value());
builder.ztsUrl(ztsUrl != null ? ztsUrl.toString() : "");
builder.athenzDnsSuffix(athenzDnsSuffix != null ? athenzDnsSuffix : "");
- builder.nodeIdentityName("vespa.vespa.tenant"); // TODO Move to Oath configmodel amender
+ builder.nodeIdentityName(configServerDomain() + ".tenant"); // TODO Move to Oath configmodel amender
builder.configserverIdentityName(getConfigserverIdentityName());
}
// TODO Move to Oath configmodel amender
private String getConfigserverIdentityName() {
return String.format("%s.provider_%s_%s",
- zone.system() == SystemName.main ? "vespa.vespa" : "vespa.vespa.cd",
+ configServerDomain(),
zone.environment().value(),
zone.region().value());
}
+ private String configServerDomain() {
+ return zone.system() == SystemName.main ? "vespa.vespa" : "vespa.vespa.cd";
+ }
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/ml/OnnxModelInfo.java b/config-model/src/main/java/com/yahoo/vespa/model/ml/OnnxModelInfo.java
index 2742dc59fcd..7c89a349d7d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/ml/OnnxModelInfo.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/ml/OnnxModelInfo.java
@@ -42,13 +42,16 @@ public class OnnxModelInfo {
private final Map<String, OnnxTypeInfo> inputs;
private final Map<String, OnnxTypeInfo> outputs;
private final Map<String, TensorType> vespaTypes = new HashMap<>();
+ private final Set<String> initializers;
- private OnnxModelInfo(ApplicationPackage app, String path, Map<String, OnnxTypeInfo> inputs, Map<String, OnnxTypeInfo> outputs, String defaultOutput) {
+ private OnnxModelInfo(ApplicationPackage app, String path, Map<String, OnnxTypeInfo> inputs,
+ Map<String, OnnxTypeInfo> outputs, Set<String> initializers, String defaultOutput) {
this.app = app;
this.modelPath = path;
this.inputs = Collections.unmodifiableMap(inputs);
this.outputs = Collections.unmodifiableMap(outputs);
this.defaultOutput = defaultOutput;
+ this.initializers = Set.copyOf(initializers);
}
public String getModelPath() {
@@ -63,6 +66,8 @@ public class OnnxModelInfo {
return outputs.keySet();
}
+ public Set<String> getInitializers() { return initializers; }
+
public String getDefaultOutput() {
return defaultOutput;
}
@@ -208,6 +213,14 @@ public class OnnxModelInfo {
}
g.writeEndArray();
+ g.writeArrayFieldStart("initializers");
+ for (Onnx.TensorProto initializers : model.getGraph().getInitializerList()) {
+ g.writeStartObject();
+ g.writeStringField("name", initializers.getName());
+ g.writeEndObject();
+ }
+ g.writeEndArray();
+
g.writeEndObject();
g.close();
return out.toString();
@@ -218,6 +231,7 @@ public class OnnxModelInfo {
JsonNode root = m.readTree(json);
Map<String, OnnxTypeInfo> inputs = new HashMap<>();
Map<String, OnnxTypeInfo> outputs = new HashMap<>();
+ Set<String> initializers = new HashSet<>();
String defaultOutput = "";
String path = null;
@@ -233,7 +247,13 @@ public class OnnxModelInfo {
if (root.get("outputs").has(0)) {
defaultOutput = root.get("outputs").get(0).get("name").textValue();
}
- return new OnnxModelInfo(app, path, inputs, outputs, defaultOutput);
+ var initializerRoot = root.get("initializers");
+ if (initializerRoot != null) {
+ for (JsonNode initializer : initializerRoot) {
+ initializers.add(initializer.get("name").textValue());
+ }
+ }
+ return new OnnxModelInfo(app, path, inputs, outputs, initializers, defaultOutput);
}
static private void onnxTypeToJson(JsonGenerator g, Onnx.ValueInfoProto valueInfo) throws IOException {
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidatorTest.java
index 5c360a9343f..65dfce8ff6c 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/ContentClusterRemovalValidatorTest.java
@@ -1,14 +1,18 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.application.validation.change;
+import com.yahoo.collections.Pair;
import com.yahoo.config.application.api.ValidationId;
import com.yahoo.config.application.api.ValidationOverrides;
+import com.yahoo.config.model.api.ConfigChangeAction;
import com.yahoo.config.provision.Environment;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.application.validation.ValidationTester;
import com.yahoo.yolean.Exceptions;
import org.junit.jupiter.api.Test;
+import java.util.List;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
@@ -36,7 +40,12 @@ public class ContentClusterRemovalValidatorTest {
@Test
void testOverridingContentRemovalValidation() {
VespaModel previous = tester.deploy(null, getServices("contentClusterId"), Environment.prod, null).getFirst();
- tester.deploy(previous, getServices("newContentClusterId"), Environment.prod, removalOverride); // Allowed due to override
+ var result = tester.deploy(previous, getServices("newContentClusterId"), Environment.prod, removalOverride); // Allowed due to override
+ assertEquals(result.getFirst().getContainerClusters().values().stream()
+ .flatMap(cluster -> cluster.getContainers().stream())
+ .map(container -> container.getServiceInfo())
+ .toList(),
+ result.getSecond().stream().flatMap(action -> action.getServices().stream()).toList());
}
private static String getServices(String contentClusterId) {
diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/filedistribution/FileReferencesAndDownloadsMaintainer.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/filedistribution/FileReferencesAndDownloadsMaintainer.java
index 5d5775275c3..17025b10568 100644
--- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/filedistribution/FileReferencesAndDownloadsMaintainer.java
+++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/filedistribution/FileReferencesAndDownloadsMaintainer.java
@@ -23,7 +23,9 @@ import java.util.stream.Collectors;
import static java.nio.file.Files.readAttributes;
/**
- * Deletes file references and url downloads that have not been used for some time
+ * Deletes file references and url downloads that have not been used for some time.
+ * See {@link com.yahoo.vespa.config.proxy.filedistribution.RequestTracker} for how we track
+ * when a file reference or download was last used.
*
* @author hmusum
*/
@@ -32,7 +34,7 @@ class FileReferencesAndDownloadsMaintainer implements Runnable {
private static final Logger log = Logger.getLogger(FileReferencesAndDownloadsMaintainer.class.getName());
private static final File defaultUrlDownloadDir = UrlDownloadRpcServer.downloadDir;
private static final File defaultFileReferencesDownloadDir = FileDownloader.defaultDownloadDirectory;
- private static final Duration defaultDurationToKeepFiles = Duration.ofDays(14);
+ private static final Duration defaultDurationToKeepFiles = Duration.ofDays(21);
private static final Duration interval = Duration.ofMinutes(1);
private final ScheduledExecutorService executor =
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index f6988a6b566..955b1bc8f4f 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -534,7 +534,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
NestedTransaction transaction = new NestedTransaction();
Optional<ApplicationTransaction> applicationTransaction = hostProvisioner.map(provisioner -> provisioner.lock(applicationId))
.map(lock -> new ApplicationTransaction(lock, transaction));
- try (var applicationLock = tenantApplications.lock(applicationId)) {
+ try (@SuppressWarnings("unused") var applicationLock = tenantApplications.lock(applicationId)) {
Optional<Long> activeSession = tenantApplications.activeSessionOf(applicationId);
CompletionWaiter waiter;
if (activeSession.isPresent()) {
@@ -796,7 +796,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
NestedTransaction transaction = new NestedTransaction();
Optional<ApplicationTransaction> applicationTransaction = hostProvisioner.map(provisioner -> provisioner.lock(applicationId))
.map(lock -> new ApplicationTransaction(lock, transaction));
- try (var sessionLock = tenant.getApplicationRepo().lock(applicationId)) {
+ try (@SuppressWarnings("unused") var sessionLock = tenant.getApplicationRepo().lock(applicationId)) {
Optional<Session> activeSession = getActiveSession(applicationId);
var sessionZooKeeperClient = tenant.getSessionRepository().createSessionZooKeeperClient(session.getSessionId());
CompletionWaiter waiter = sessionZooKeeperClient.createActiveWaiter();
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
index 88e3134ccad..cddcb0f316d 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java
@@ -74,7 +74,7 @@ public class TenantApplications implements RequestHandler, HostValidator {
private final MetricUpdater tenantMetricUpdater;
private final Clock clock;
private final TenantFileSystemDirs tenantFileSystemDirs;
- private final ConfigserverConfig configserverConfig;
+ private final String serverId;
private final ListFlag<String> incompatibleVersions;
public TenantApplications(TenantName tenant, Curator curator, StripedExecutor<TenantName> zkWatcherExecutor,
@@ -95,7 +95,7 @@ public class TenantApplications implements RequestHandler, HostValidator {
this.hostRegistry = hostRegistry;
this.tenantFileSystemDirs = tenantFileSystemDirs;
this.clock = clock;
- this.configserverConfig = configserverConfig;
+ this.serverId = configserverConfig.serverId();
this.incompatibleVersions = PermanentFlags.INCOMPATIBLE_VERSIONS.bindTo(flagSource);
}
@@ -230,7 +230,7 @@ public class TenantApplications implements RequestHandler, HostValidator {
*/
public void activateApplication(ApplicationSet applicationSet, long activeSessionId) {
ApplicationId id = applicationSet.getId();
- try (Lock lock = lock(id)) {
+ try (@SuppressWarnings("unused") Lock lock = lock(id)) {
if ( ! exists(id))
return; // Application was deleted before activation.
if (applicationSet.getApplicationGeneration() != activeSessionId)
@@ -269,7 +269,7 @@ public class TenantApplications implements RequestHandler, HostValidator {
public void removeApplicationsExcept(Set<ApplicationId> applications) {
for (ApplicationId activeApplication : applicationMapper.listApplicationIds()) {
if ( ! applications.contains(activeApplication)) {
- try (var applicationLock = lock(activeApplication)){
+ try (@SuppressWarnings("unused") var applicationLock = lock(activeApplication)){
removeApplication(activeApplication);
}
}
@@ -404,11 +404,11 @@ public class TenantApplications implements RequestHandler, HostValidator {
public TenantFileSystemDirs getTenantFileSystemDirs() { return tenantFileSystemDirs; }
public CompletionWaiter createRemoveApplicationWaiter(ApplicationId applicationId) {
- return RemoveApplicationWaiter.createAndInitialize(curator, applicationId, configserverConfig.serverId());
+ return RemoveApplicationWaiter.createAndInitialize(curator, applicationId, serverId);
}
public CompletionWaiter getRemoveApplicationWaiter(ApplicationId applicationId) {
- return RemoveApplicationWaiter.create(curator, applicationId, configserverConfig.serverId());
+ return RemoveApplicationWaiter.create(curator, applicationId, serverId);
}
/**
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java
index 86c0c90ca12..62a1704b350 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java
@@ -97,8 +97,6 @@ public class ApplicationHandler extends HttpHandler {
if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/filedistributionstatus")) return filedistributionStatus(applicationId(path), request);
if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/logs")) return logs(applicationId(path), request);
if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/metrics/deployment")) return deploymentMetrics(applicationId(path));
- // TODO: Remove when all usage has migrated to .../metrics/searchnode
- if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/metrics/proton")) return searchNodeMetrics(applicationId(path));
if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/metrics/searchnode")) return searchNodeMetrics(applicationId(path));
if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/reindexing")) return getReindexingStatus(applicationId(path));
if (path.matches("/application/v2/tenant/{tenant}/application/{application}/environment/{ignore}/region/{ignore}/instance/{instance}/service/{service}/{hostname}/status/{*}")) return serviceStatusPage(applicationId(path), path.get("service"), path.get("hostname"), path.getRest(), request);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java
index 2948b82dd96..22ef6cc2547 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java
@@ -88,7 +88,7 @@ public class ApplicationPackageMaintainer extends ConfigServerMaintainer {
createLocalSessionIfMissing(applicationId, sessionId);
}
}
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
private static FileDownloader createFileDownloader(List<String> otherConfigServersInCluster,
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintainer.java
index dad687aae67..ef48c3bdb98 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintainer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintainer.java
@@ -46,9 +46,9 @@ public abstract class ConfigServerMaintainer extends Maintainer {
}
@Override
- public void completed(String job, double successFactor, long durationMs) {
+ public void completed(String job, double successFactorDeviation, long durationMs) {
var context = metric.createContext(Map.of("job", job));
- metric.set("maintenance.successFactor", successFactor, context);
+ metric.set("maintenance.successFactorDeviation", successFactorDeviation, context);
metric.set("maintenance.duration", durationMs, context);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java
index a9672455d09..e81c9b6bcbd 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java
@@ -77,7 +77,7 @@ public class ReindexingMaintainer extends ConfigServerMaintainer {
}
});
}
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
private Supplier<Long> lazyGeneration(Application application) {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
index 728f3e8510f..2ad04fdd572 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java
@@ -12,8 +12,8 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
import com.yahoo.text.Utf8;
import com.yahoo.vespa.config.ConfigKey;
-import com.yahoo.vespa.config.server.ConfigServerDB;
import com.yahoo.vespa.config.server.ConfigActivationListener;
+import com.yahoo.vespa.config.server.ConfigServerDB;
import com.yahoo.vespa.config.server.ServerCache;
import com.yahoo.vespa.config.server.deploy.TenantFileSystemDirs;
import com.yahoo.vespa.config.server.host.HostRegistry;
@@ -26,7 +26,6 @@ import com.yahoo.vespa.config.server.tenant.TestTenantRepository;
import com.yahoo.vespa.curator.CompletionTimeoutException;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.mock.MockCurator;
-import com.yahoo.vespa.curator.mock.MockCuratorFramework;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.flags.PermanentFlags;
import com.yahoo.vespa.model.VespaModel;
@@ -37,22 +36,17 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.xml.sax.SAXException;
-
import java.io.File;
import java.io.IOException;
import java.time.Clock;
import java.time.Duration;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
-import static com.yahoo.vespa.config.server.application.TenantApplications.RemoveApplicationWaiter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -195,7 +189,6 @@ public class TenantApplicationsTest {
public static class MockConfigActivationListener implements ConfigActivationListener {
public final AtomicInteger activated = new AtomicInteger(0);
final AtomicInteger removed = new AtomicInteger(0);
- final Map<String, Collection<String>> tenantHosts = new LinkedHashMap<>();
@Override
public void configActivated(ApplicationSet application) {
@@ -247,22 +240,22 @@ public class TenantApplicationsTest {
@Test
public void testRemoveApplication2of3Respond() throws InterruptedException {
- Curator curator = new MockCurator3ConfigServers();
- Thread t1 = setupWaiter(curator);
- notifyCompletion(curator, 2);
+ TenantApplications applications = createZKAppRepo(new InMemoryFlagSource());
+ Thread t1 = setupWaiter(applications);
+ notifyCompletion(applications, 2);
t1.join();
}
@Test
public void testRemoveApplicationAllRespond() throws InterruptedException {
- Curator curator = new MockCurator3ConfigServers();
- Thread t1 = setupWaiter(curator);
- notifyCompletion(curator, 3);
+ TenantApplications applications = createZKAppRepo(new InMemoryFlagSource());
+ Thread t1 = setupWaiter(applications);
+ notifyCompletion(applications, 3);
t1.join();
}
- private Thread setupWaiter(Curator curator) {
- Curator.CompletionWaiter waiter = RemoveApplicationWaiter.createAndInitialize(curator, createApplicationId(), "cfg1", Duration.ofSeconds(1));
+ private Thread setupWaiter(TenantApplications applications) {
+ Curator.CompletionWaiter waiter = applications.getRemoveApplicationWaiter(createApplicationId());
Thread t1 = new Thread(() -> {
try {
waiter.awaitCompletion(Duration.ofSeconds(120));
@@ -274,10 +267,10 @@ public class TenantApplicationsTest {
return t1;
}
- private void notifyCompletion(Curator curator, int respondentCount) {
+ private void notifyCompletion(TenantApplications applications, int respondentCount) {
IntStream.range(0, respondentCount)
- .forEach(i -> RemoveApplicationWaiter.create(curator, createApplicationId(), "cfg" + i, Duration.ofSeconds(1))
- .notifyCompletion());
+ .forEach(i -> applications.createRemoveApplicationWaiter(createApplicationId())
+ .notifyCompletion());
}
private TenantApplications createZKAppRepo() {
@@ -332,12 +325,4 @@ public class TenantApplicationsTest {
flagSource);
}
- private static class MockCurator3ConfigServers extends Curator {
-
- public MockCurator3ConfigServers() {
- super("host1:2181,host2:2181,host3:2181", "host1:2181,host2:2181,host3:2181", (retryPolicy) -> new MockCuratorFramework(true, false));
- }
-
- }
-
}
diff --git a/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java b/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java
index 88a37ea5a02..92ce6abb319 100644
--- a/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java
+++ b/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java
@@ -6,11 +6,11 @@ import com.yahoo.search.Query;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import static com.yahoo.text.Lowercase.toLowerCase;
@@ -32,6 +32,16 @@ public class IndexFacts {
private Map<String, List<String>> clusterByDocument;
+ private static class DocumentTypeListOffset {
+ public final int offset;
+ public final SearchDefinition searchDefinition;
+
+ public DocumentTypeListOffset(int offset, SearchDefinition searchDefinition) {
+ this.offset = offset;
+ this.searchDefinition = searchDefinition;
+ }
+ }
+
/** A Map of all known search definitions indexed by name */
private Map<String, SearchDefinition> searchDefinitions = new LinkedHashMap<>();
@@ -100,32 +110,34 @@ public class IndexFacts {
private boolean isIndexFromDocumentTypes(String indexName, List<String> documentTypes) {
if ( ! isInitialized()) return true;
- if (documentTypes.isEmpty()) return unionSearchDefinition.getIndex(indexName) != null;
+ if (documentTypes.isEmpty()) {
+ return unionSearchDefinition.getIndex(indexName) != null;
+ }
- for (String docName : documentTypes) {
- SearchDefinition sd = searchDefinitions.get(docName);
- if (sd != null) {
- Index index = sd.getIndex(indexName);
- if (index != null) return true;
+ DocumentTypeListOffset sd = chooseSearchDefinition(documentTypes, 0);
+ while (sd != null) {
+ Index index = sd.searchDefinition.getIndex(indexName);
+ if (index != null) {
+ return true;
}
+ sd = chooseSearchDefinition(documentTypes, sd.offset);
}
+
return false;
}
private String getCanonicNameFromDocumentTypes(String indexName, List<String> documentTypes) {
if (!isInitialized()) return indexName;
- String lowerCased = toLowerCase(indexName);
if (documentTypes.isEmpty()) {
- Index index = unionSearchDefinition.getIndexByLowerCase(lowerCased);
+ Index index = unionSearchDefinition.getIndexByLowerCase(toLowerCase(indexName));
return index == null ? indexName : index.getName();
}
- for (String docName : documentTypes) {
- SearchDefinition sd = searchDefinitions.get(docName);
- if (sd != null) {
- Index index = sd.getIndexByLowerCase(lowerCased);
- if (index != null) return index.getName();
- }
+ DocumentTypeListOffset sd = chooseSearchDefinition(documentTypes, 0);
+ while (sd != null) {
+ Index index = sd.searchDefinition.getIndexByLowerCase(toLowerCase(indexName));
+ if (index != null) return index.getName();
+ sd = chooseSearchDefinition(documentTypes, sd.offset);
}
return indexName;
}
@@ -146,12 +158,13 @@ public class IndexFacts {
return index;
}
- for (String docName : documentTypes) {
- SearchDefinition sd = searchDefinitions.get(docName);
- if (sd != null) {
- Index index = sd.getIndex(canonicName);
- if (index != null) return index;
- }
+ DocumentTypeListOffset sd = chooseSearchDefinition(documentTypes, 0);
+
+ while (sd != null) {
+ Index index = sd.searchDefinition.getIndex(canonicName);
+
+ if (index != null) return index;
+ sd = chooseSearchDefinition(documentTypes, sd.offset);
}
return Index.nullIndex;
}
@@ -174,7 +187,7 @@ public class IndexFacts {
* Given a search list which is a mixture of document types and cluster
* names, and a restrict list which is a list of document types, return a
* set of all valid document types for this combination. Most use-cases for
- * fetching index settings will involve calling this method with the
+ * fetching index settings will involve calling this method with the the
* incoming query's {@link com.yahoo.search.query.Model#getSources()} and
* {@link com.yahoo.search.query.Model#getRestrict()} as input parameters
* before calling any other method of this class.
@@ -183,20 +196,20 @@ public class IndexFacts {
* @param restrict the restrict list for a query
* @return a (possibly empty) set of valid document types
*/
- private Set<String> resolveDocumentTypes(Collection<String> sources, Set<String> restrict,
+ private Set<String> resolveDocumentTypes(Collection<String> sources, Collection<String> restrict,
Set<String> candidateDocumentTypes) {
sources = emptyCollectionIfNull(sources);
- restrict = emptySetIfNull(restrict);
+ restrict = emptyCollectionIfNull(restrict);
if (sources.isEmpty()) {
if ( ! restrict.isEmpty()) {
- return Set.copyOf(restrict);
+ return new TreeSet<>(restrict);
} else {
return candidateDocumentTypes;
}
}
- Set<String> toSearch = new HashSet<>();
+ Set<String> toSearch = new TreeSet<>();
for (String source : sources) { // source: a document type or a cluster containing them
List<String> clusterDocTypes = clusters.get(source);
if (clusterDocTypes == null) { // source was a document type
@@ -222,8 +235,21 @@ public class IndexFacts {
private Collection<String> emptyCollectionIfNull(Collection<String> collection) {
return collection == null ? List.of() : collection;
}
- private Set<String> emptySetIfNull(Set<String> collection) {
- return collection == null ? Set.of() : collection;
+
+ /**
+ * Chooses the correct search definition, default if in doubt.
+ *
+ * @return the search definition to use
+ */
+ private DocumentTypeListOffset chooseSearchDefinition(List<String> documentTypes, int index) {
+ while (index < documentTypes.size()) {
+ String docName = documentTypes.get(index++);
+ SearchDefinition sd = searchDefinitions.get(docName);
+ if (sd != null) {
+ return new DocumentTypeListOffset(index, sd);
+ }
+ }
+ return null;
}
/**
@@ -253,6 +279,10 @@ public class IndexFacts {
return frozen;
}
+ private void ensureNotFrozen() {
+ if (frozen) throw new IllegalStateException("Tried to modify frozen IndexFacts instance.");
+ }
+
public String getDefaultPosition(String sdName) {
SearchDefinition sd;
if (sdName == null) {
@@ -270,16 +300,12 @@ public class IndexFacts {
return new Session(query);
}
- public Session newSession() {
- return new Session(Set.of(), Set.of());
- }
-
- public Session newSession(Collection<String> sources, Set<String> restrict) {
+ public Session newSession(Collection<String> sources, Collection<String> restrict) {
return new Session(sources, restrict);
}
public Session newSession(Collection<String> sources,
- Set<String> restrict,
+ Collection<String> restrict,
Set<String> candidateDocumentTypes) {
return new Session(sources, restrict, candidateDocumentTypes);
}
@@ -297,12 +323,12 @@ public class IndexFacts {
documentTypes = List.copyOf(resolveDocumentTypes(query));
}
- private Session(Collection<String> sources, Set<String> restrict) {
+ private Session(Collection<String> sources, Collection<String> restrict) {
// Assumption: Search definition name equals document name.
documentTypes = List.copyOf(resolveDocumentTypes(sources, restrict, searchDefinitions.keySet()));
}
- private Session(Collection<String> sources, Set<String> restrict, Set<String> candidateDocumentTypes) {
+ private Session(Collection<String> sources, Collection<String> restrict, Set<String> candidateDocumentTypes) {
documentTypes = List.copyOf(resolveDocumentTypes(sources, restrict, candidateDocumentTypes));
}
diff --git a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
index f0e3e3f3e44..46332d632fe 100644
--- a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
+++ b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
@@ -1,8 +1,8 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.prelude.cluster;
-import com.yahoo.component.ComponentId;
import com.yahoo.component.annotation.Inject;
+import com.yahoo.component.ComponentId;
import com.yahoo.component.chain.dependencies.After;
import com.yahoo.component.provider.ComponentRegistry;
import com.yahoo.container.QrSearchersConfig;
@@ -28,6 +28,10 @@ import com.yahoo.vespa.streamingvisitors.VdsStreamingSearcher;
import com.yahoo.yolean.Exceptions;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -53,7 +57,8 @@ public class ClusterSearcher extends Searcher {
private final String searchClusterName;
- private final SchemaResolver schemaResolver;
+ // The set of document types contained in this search cluster
+ private final Set<String> schemas;
private final long maxQueryTimeout; // in milliseconds
private final long maxQueryCacheTimeout; // in milliseconds
@@ -79,7 +84,7 @@ public class ClusterSearcher extends Searcher {
searchClusterName = clusterConfig.clusterName();
QrSearchersConfig.Searchcluster searchClusterConfig = getSearchClusterConfigFromClusterName(qrsConfig, searchClusterName);
this.globalPhaseRanker = searchClusterConfig.globalphase() ? globalPhaseRanker : null;
- this.schemaResolver = new SchemaResolver(documentDbConfig);
+ schemas = new LinkedHashSet<>();
maxQueryTimeout = ParameterParser.asMilliSeconds(clusterConfig.maxQueryTimeout(), DEFAULT_MAX_QUERY_TIMEOUT);
maxQueryCacheTimeout = ParameterParser.asMilliSeconds(clusterConfig.maxQueryCacheTimeout(), DEFAULT_MAX_QUERY_CACHE_TIMEOUT);
@@ -88,6 +93,9 @@ public class ClusterSearcher extends Searcher {
.com().yahoo().prelude().fastsearch().FastSearcher().docsum()
.defaultclass());
+ for (DocumentdbInfoConfig.Documentdb docDb : documentDbConfig.documentdb())
+ schemas.add(docDb.name());
+
String uniqueServerId = UUID.randomUUID().toString();
if (searchClusterConfig.indexingmode() == STREAMING) {
server = vdsCluster(uniqueServerId, searchClusterIndex,
@@ -149,7 +157,7 @@ public class ClusterSearcher extends Searcher {
/** Do not use, for internal testing purposes only. **/
ClusterSearcher(Set<String> schemas, VespaBackEndSearcher searcher, Executor executor) {
- this.schemaResolver = new SchemaResolver(schemas);
+ this.schemas = schemas;
searchClusterName = "testScenario";
maxQueryTimeout = DEFAULT_MAX_QUERY_TIMEOUT;
maxQueryCacheTimeout = DEFAULT_MAX_QUERY_CACHE_TIMEOUT;
@@ -221,9 +229,8 @@ public class ClusterSearcher extends Searcher {
}
private Result doSearch(Searcher searcher, Query query, Execution execution) {
- var schemas = schemaResolver.resolve(query, execution);
if (schemas.size() > 1) {
- return searchMultipleDocumentTypes(searcher, query, execution, schemas);
+ return searchMultipleDocumentTypes(searcher, query, execution);
} else {
String docType = schemas.iterator().next();
query.getModel().setRestrict(docType);
@@ -259,7 +266,8 @@ public class ClusterSearcher extends Searcher {
}
}
- private Result searchMultipleDocumentTypes(Searcher searcher, Query query, Execution execution, Set<String> schemas) {
+ private Result searchMultipleDocumentTypes(Searcher searcher, Query query, Execution execution) {
+ Set<String> schemas = resolveSchemas(query, execution.context().getIndexFacts());
List<Query> queries = createQueries(query, schemas);
if (queries.size() == 1) {
return perSchemaSearch(searcher, queries.get(0), execution);
@@ -293,7 +301,25 @@ public class ClusterSearcher extends Searcher {
}
Set<String> resolveSchemas(Query query, IndexFacts indexFacts) {
- return schemaResolver.resolve(query, indexFacts);
+ Set<String> restrict = query.getModel().getRestrict();
+ if (restrict == null || restrict.isEmpty()) {
+ Set<String> sources = query.getModel().getSources();
+ return (sources == null || sources.isEmpty())
+ ? schemas
+ : new HashSet<>(indexFacts.newSession(sources, Collections.emptyList(), schemas).documentTypes());
+ } else {
+ return filterValidDocumentTypes(restrict);
+ }
+ }
+
+ private Set<String> filterValidDocumentTypes(Collection<String> restrict) {
+ Set<String> retval = new LinkedHashSet<>();
+ for (String docType : restrict) {
+ if (docType != null && schemas.contains(docType)) {
+ retval.add(docType);
+ }
+ }
+ return retval;
}
private List<Query> createQueries(Query query, Set<String> docTypes) {
diff --git a/container-search/src/main/java/com/yahoo/prelude/cluster/SchemaResolver.java b/container-search/src/main/java/com/yahoo/prelude/cluster/SchemaResolver.java
deleted file mode 100644
index 3a2125d1d38..00000000000
--- a/container-search/src/main/java/com/yahoo/prelude/cluster/SchemaResolver.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-package com.yahoo.prelude.cluster;
-
-import com.yahoo.prelude.IndexFacts;
-import com.yahoo.prelude.fastsearch.DocumentdbInfoConfig;
-import com.yahoo.search.Query;
-import com.yahoo.search.searchchain.Execution;
-
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-/**
- * Resolves schemas from query and execution context
- *
- * @author bjorncs
- */
-class SchemaResolver {
-
- private final Set<String> schemas;
-
- SchemaResolver(DocumentdbInfoConfig cfg) {
- this(cfg.documentdb().stream().map(DocumentdbInfoConfig.Documentdb::name).toList());
- }
-
- SchemaResolver(Collection<String> schemas) {
- this.schemas = new LinkedHashSet<>(schemas);
- }
-
- Set<String> resolve(Query query, Execution execution) {
- return resolve(query, execution.context().getIndexFacts());
- }
-
- Set<String> resolve(Query query, IndexFacts indexFacts) {
- if (schemas.size() == 1) return Set.of(schemas.iterator().next());
- var restrict = query.getModel().getRestrict();
- if (restrict == null || restrict.isEmpty()) {
- Set<String> sources = query.getModel().getSources();
- return (sources == null || sources.isEmpty())
- ? schemas
- : new LinkedHashSet<>(indexFacts.newSession(sources, Set.of(), schemas).documentTypes());
- } else {
- return filterValidDocumentTypes(restrict);
- }
- }
-
- private Set<String> filterValidDocumentTypes(Collection<String> restrict) {
- Set<String> retval = new LinkedHashSet<>();
- for (String docType : restrict) {
- if (docType != null && schemas.contains(docType)) {
- retval.add(docType);
- }
- }
- return retval;
- }
-
-}
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java
index 2bd408220cd..e3b2278475b 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/CustomParser.java
@@ -6,6 +6,7 @@ import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.query.Item;
import com.yahoo.search.query.parser.Parser;
+import java.util.Collections;
import java.util.Set;
/**
@@ -22,7 +23,7 @@ public interface CustomParser extends Parser {
Set<String> toSearch, IndexFacts indexFacts, String defaultIndexName) {
if (indexFacts == null)
indexFacts = new IndexFacts();
- return parse(queryToParse, filterToParse, parsingLanguage, indexFacts.newSession(toSearch, Set.of()), defaultIndexName);
+ return parse(queryToParse, filterToParse, parsingLanguage, indexFacts.newSession(toSearch, Collections.emptySet()), defaultIndexName);
}
Item parse(String queryToParse, String filterToParse, Language parsingLanguage,
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java
index 9952ec64d13..c1d415b8e27 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/Tokenizer.java
@@ -8,6 +8,7 @@ import com.yahoo.prelude.Index;
import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.query.Substring;
+import java.util.Collections;
import java.util.List;
import static com.yahoo.prelude.query.parser.Token.Kind.*;
@@ -62,7 +63,7 @@ public final class Tokenizer {
* @return a read-only list of tokens. This list can only be used by this thread
*/
public List<Token> tokenize(String string) {
- return tokenize(string, new IndexFacts().newSession());
+ return tokenize(string, new IndexFacts().newSession(Collections.emptySet(), Collections.emptySet()));
}
/**
@@ -170,10 +171,13 @@ public final class Tokenizer {
// this is a heuristic to check whether we probably have reached the end of an URL element
for (int i = tokens.size() - 1; i >= 0; --i) {
switch (tokens.get(i).kind) {
- case COLON -> { if (i == indexLastExplicitlyChangedAt) return false; }
- case SPACE -> { return true; }
- default -> { }
- // do nothing
+ case COLON:
+ if (i == indexLastExplicitlyChangedAt) return false;
+ break;
+ case SPACE:
+ return true;
+ default:
+ // do nothing
}
}
// really not sure whether we should choose false instead, on cause of the guard at
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java
index 3a6be1521e2..1ff5574ec03 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java
@@ -13,6 +13,7 @@ import com.yahoo.prelude.query.parser.Tokenizer;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import static com.yahoo.prelude.query.parser.Token.Kind.COLON;
@@ -28,9 +29,7 @@ import static com.yahoo.prelude.query.parser.Token.Kind.SPACE;
import static com.yahoo.prelude.query.parser.Token.Kind.STAR;
import static com.yahoo.prelude.query.parser.Token.Kind.UNDERSCORE;
import static com.yahoo.prelude.query.parser.Token.Kind.WORD;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
/**
* Tests the tokenizer
@@ -284,7 +283,7 @@ public class TokenizerTestCase {
sd.addIndex(index2);
IndexFacts facts = new IndexFacts(new IndexModel(sd));
- IndexFacts.Session session = facts.newSession();
+ IndexFacts.Session session = facts.newSession(Collections.emptySet(), Collections.emptySet());
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
List<?> tokens = tokenizer.tokenize("normal a:b (normal testexact1:/,%#%&+-+ ) testexact2:ho_/&%&/()/aa*::*& b:c", "default", session);
// tokenizer.print();
@@ -329,7 +328,7 @@ public class TokenizerTestCase {
IndexFacts facts = new IndexFacts(new IndexModel(sd));
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- IndexFacts.Session session = facts.newSession();
+ IndexFacts.Session session = facts.newSession(Collections.emptySet(), Collections.emptySet());
List<?> tokens = tokenizer.tokenize("normal a:b (normal testexact1:/,%#%&+-+ ) testexact2:ho_/&%&/()/aa*::*&", session);
assertEquals(new Token(WORD, "normal"), tokens.get(0));
assertEquals(new Token(SPACE, " "), tokens.get(1));
@@ -366,7 +365,7 @@ public class TokenizerTestCase {
IndexFacts facts = new IndexFacts(new IndexModel(sd));
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- IndexFacts.Session session = facts.newSession();
+ IndexFacts.Session session = facts.newSession(Collections.emptySet(), Collections.emptySet());
List<?> tokens = tokenizer.tokenize("normal a:b (normal testexact1:/,%#%&+-+ ) testexact2:ho_/&%&/()/aa*::*", session);
assertEquals(new Token(WORD, "normal"), tokens.get(0));
assertEquals(new Token(SPACE, " "), tokens.get(1));
@@ -403,7 +402,7 @@ public class TokenizerTestCase {
IndexFacts facts = new IndexFacts(new IndexModel(sd));
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- IndexFacts.Session session = facts.newSession();
+ IndexFacts.Session session = facts.newSession(Collections.emptySet(), Collections.emptySet());
List<?> tokens = tokenizer.tokenize("normal a:b (normal testexact1:!/%#%&+-+ ) testexact2:ho_/&%&/()/aa*::*&b:", session);
assertEquals(new Token(WORD, "normal"), tokens.get(0));
assertEquals(new Token(SPACE, " "), tokens.get(1));
@@ -440,7 +439,7 @@ public class TokenizerTestCase {
sd.addIndex(index2);
IndexFacts indexFacts = new IndexFacts(new IndexModel(sd));
- IndexFacts.Session facts = indexFacts.newSession();
+ IndexFacts.Session facts = indexFacts.newSession(Collections.emptySet(), Collections.emptySet());
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
List<?> tokens = tokenizer.tokenize("normal a:b (normal testexact1:foo) testexact2:bar", facts);
diff --git a/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java b/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java
index dbcb393c922..e6c5a18c9da 100644
--- a/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java
@@ -15,12 +15,8 @@ import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
/**
* Tests using synthetic index names for IndexFacts class.
@@ -184,7 +180,7 @@ public class IndexFactsTestCase {
query.getModel().getSources().add("one");
query.getModel().getRestrict().add("two");
- IndexFacts.Session indexFacts = createIndexFacts().newSession(List.of("clusterOne"), Set.of());
+ IndexFacts.Session indexFacts = createIndexFacts().newSession(List.of("clusterOne"), List.of());
assertTrue(indexFacts.isIndex("a"));
assertFalse(indexFacts.isIndex("b"));
assertTrue(indexFacts.isIndex("d"));
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java
index 1eb68c14353..80b52e0c7a4 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java
@@ -31,7 +31,8 @@ import static java.util.Comparator.comparing;
*/
public class Endpoint {
- private static final String OATH_DNS_SUFFIX = ".vespa.oath.cloud";
+ private static final String MAIN_OATH_DNS_SUFFIX = ".vespa.oath.cloud";
+ private static final String CD_OATH_DNS_SUFFIX = ".cd.vespa.oath.cloud";
private static final String PUBLIC_DNS_SUFFIX = ".vespa-app.cloud";
private static final String PUBLIC_CD_DNS_SUFFIX = ".cd.vespa-app.cloud";
@@ -243,18 +244,13 @@ public class Endpoint {
/** Returns the DNS suffix used for endpoints in given system */
private static String dnsSuffix(SystemName system) {
- switch (system) {
- case cd, main -> {
- return OATH_DNS_SUFFIX;
- }
- case Public -> {
- return PUBLIC_DNS_SUFFIX;
- }
- case PublicCd -> {
- return PUBLIC_CD_DNS_SUFFIX;
- }
+ return switch (system) {
+ case cd -> CD_OATH_DNS_SUFFIX;
+ case main -> MAIN_OATH_DNS_SUFFIX;
+ case Public -> PUBLIC_DNS_SUFFIX;
+ case PublicCd -> PUBLIC_CD_DNS_SUFFIX;
default -> throw new IllegalArgumentException("No DNS suffix declared for system " + system);
- }
+ };
}
/** Returns the DNS suffix used for internal names (i.e. names not exposed to tenants) in given system */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLog.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLog.java
index aa6e3b0c44d..cbd0f685d80 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLog.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLog.java
@@ -49,7 +49,7 @@ public record AuditLog(List<Entry> entries) {
public record Entry(Instant at, String principal, Method method, String resource, Optional<String> data,
Client client) implements Comparable<Entry> {
- private final static int maxDataLength = 1024;
+ final static int maxDataLength = 1024;
private final static Comparator<Entry> comparator = Comparator.comparing(Entry::at).reversed();
public Entry(Instant at, Client client, String principal, Method method, String resource, byte[] data) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLogger.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLogger.java
index 033cd0a52c9..13b3d9d170f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLogger.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/auditlog/AuditLogger.java
@@ -4,11 +4,12 @@ package com.yahoo.vespa.hosted.controller.auditlog;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.jdisc.http.HttpHeaders;
import com.yahoo.transaction.Mutex;
+import com.yahoo.vespa.hosted.controller.auditlog.AuditLog.Entry;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
import java.net.URI;
import java.security.Principal;
import java.time.Clock;
@@ -17,6 +18,9 @@ import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
+import static com.yahoo.yolean.Exceptions.uncheck;
+import static java.util.Objects.requireNonNullElse;
+
/**
* This provides read and write operations for the audit log.
*
@@ -58,14 +62,8 @@ public class AuditLogger {
"misconfiguration and should not happen");
}
- byte[] data = new byte[0];
- try {
- if (request.getData() != null) {
- data = request.getData().readAllBytes();
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ InputStream requestData = requireNonNullElse(request.getData(), InputStream.nullInputStream());
+ byte[] data = uncheck(() -> requestData.readNBytes(Entry.maxDataLength));
AuditLog.Entry.Client client = parseClient(request);
Instant now = clock.instant();
@@ -80,7 +78,9 @@ public class AuditLogger {
}
// Create a new input stream to allow callers to consume request body
- return new HttpRequest(request.getJDiscRequest(), new ByteArrayInputStream(data), request.propertyMap());
+ return new HttpRequest(request.getJDiscRequest(),
+ new SequenceInputStream(new ByteArrayInputStream(data), requestData),
+ request.propertyMap());
}
private static AuditLog.Entry.Client parseClient(HttpRequest request) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
index 050b77a391e..ecd24b3577f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
@@ -303,7 +303,7 @@ public class DeploymentStatus {
fallbackPlatform(change, job));
if (step.completedAt(change, firstProductionJobWithDeploymentInCloud).isEmpty()) {
JobType typeWithZone = job.type().isSystemTest() ? JobType.systemTest(zones, cloud) : JobType.stagingTest(zones, cloud);
- jobs.merge(job, List.of(new Job(typeWithZone, versions, step.readyAt(change), change)), DeploymentStatus::union);
+ jobs.merge(job, List.of(new Job(typeWithZone, versions, step.readyAt(change, firstProductionJobWithDeploymentInCloud), change)), DeploymentStatus::union);
}
});
});
@@ -679,7 +679,7 @@ public class DeploymentStatus {
.asList().isEmpty())
testJobs.merge(testJob, List.of(new Job(testJob.type(),
productionJob.versions(),
- jobSteps().get(testJob).readyAt(productionJob.change),
+ jobSteps().get(testJob).readyAt(productionJob.change, Optional.of(job)),
productionJob.change)),
DeploymentStatus::union);
});
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java
index 02e1818932e..cbdfcf70123 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java
@@ -79,7 +79,7 @@ public class ApplicationOwnershipConfirmer extends ControllerMaintainer {
log.log(Level.INFO, "Exception caught when attempting to file an issue for '" + application.id() + "': " + Exceptions.toMessageString(e));
}
});
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
private boolean isInCurrentShard(TenantAndApplicationId id) {
@@ -122,7 +122,7 @@ public class ApplicationOwnershipConfirmer extends ControllerMaintainer {
log.log(Level.INFO, "Exception caught when attempting to escalate issue with id '" + issueId + "': " + Exceptions.toMessageString(e));
}
});
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
private double updateConfirmedApplicationOwners() {
@@ -149,7 +149,7 @@ public class ApplicationOwnershipConfirmer extends ControllerMaintainer {
log.log(Level.INFO, "Exception caught when attempting to find confirmed owner of issue with id '" + issueId + "': " + Exceptions.toMessageString(e));
}
});
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
private ApplicationList applications() {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveUriUpdater.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveUriUpdater.java
index 518027f8099..c4f3c611cc5 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveUriUpdater.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArchiveUriUpdater.java
@@ -98,7 +98,7 @@ public class ArchiveUriUpdater extends ControllerMaintainer {
}
}
- return asSuccessFactor(tenantsByZone.size(), failures);
+ return asSuccessFactorDeviation(tenantsByZone.size(), failures);
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArtifactExpirer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArtifactExpirer.java
index 25c4121c271..32d06286820 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArtifactExpirer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ArtifactExpirer.java
@@ -3,7 +3,6 @@ package com.yahoo.vespa.hosted.controller.maintenance;
import com.yahoo.component.Version;
import com.yahoo.config.provision.CloudName;
-import com.yahoo.config.provision.SystemName;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.api.integration.artifact.Artifact;
import com.yahoo.vespa.hosted.controller.api.integration.artifact.ArtifactRegistry;
@@ -13,12 +12,9 @@ import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
import java.time.Duration;
import java.time.Instant;
import java.util.Comparator;
-import java.util.EnumSet;
import java.util.List;
-import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
-import java.util.stream.Collectors;
/**
* Periodically expire unused artifacts, e.g. container images and RPMs.
@@ -32,7 +28,7 @@ public class ArtifactExpirer extends ControllerMaintainer {
private static final Duration MIN_AGE = Duration.ofDays(14);
public ArtifactExpirer(Controller controller, Duration interval) {
- super(controller, interval, null, expiringSystems());
+ super(controller, interval);
}
@Override
@@ -56,10 +52,10 @@ public class ArtifactExpirer extends ControllerMaintainer {
log.log(Level.INFO, "Expiring " + artifactsToExpire.size() + " artifacts in " + cloudName + ": " + artifactsToExpire);
artifactRegistry.deleteAll(artifactsToExpire);
}
- return 1;
+ return 0;
} catch (RuntimeException e) {
log.log(Level.WARNING, "Failed to expire artifacts in " + cloudName + ". Will retry in " + interval(), e);
- return 0;
+ return 1;
}
}
@@ -77,11 +73,4 @@ public class ArtifactExpirer extends ControllerMaintainer {
return true;
}
- /** Returns systems where artifacts can be expired */
- private static Set<SystemName> expiringSystems() {
- // Run only in public and main. Public systems have distinct container registries, while main and CD have
- // shared registries.
- return EnumSet.of(SystemName.Public, SystemName.PublicCd, SystemName.main);
- }
-
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdater.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdater.java
index 32e6ad0d557..fe1930a19ea 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdater.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdater.java
@@ -42,11 +42,13 @@ public class BcpGroupUpdater extends ControllerMaintainer {
private final ApplicationController applications;
private final NodeRepository nodeRepository;
+ private final Double successFactorBaseline;
- public BcpGroupUpdater(Controller controller, Duration duration) {
- super(controller, duration);
+ public BcpGroupUpdater(Controller controller, Duration duration, Double successFactorBaseline) {
+ super(controller, duration, successFactorBaseline);
this.applications = controller.applications();
this.nodeRepository = controller.serviceRegistry().configServer().nodeRepository();
+ this.successFactorBaseline = successFactorBaseline;
}
@Override
@@ -58,7 +60,7 @@ public class BcpGroupUpdater extends ControllerMaintainer {
for (var application : applications.asList()) {
for (var instance : application.instances().values()) {
for (var deployment : instance.productionDeployments().values()) {
- if (shuttingDown()) return 1.0;
+ if (shuttingDown()) return 0.0;
try {
attempts++;
var bcpGroups = BcpGroup.groupsFrom(instance, application.deploymentSpec());
@@ -75,12 +77,12 @@ public class BcpGroupUpdater extends ControllerMaintainer {
}
}
}
- double successFactor = asSuccessFactor(attempts, failures);
- if ( successFactor == 0 )
+ double successFactorDeviation = asSuccessFactorDeviation(attempts, failures);
+ if ( successFactorDeviation == -successFactorBaseline )
log.log(Level.WARNING, "Could not update traffic share on any applications", lastException);
- else if ( successFactor < 0.9 )
+ else if ( successFactorDeviation < -0.1 )
log.log(Level.FINE, "Could not update traffic share on all applications", lastException);
- return successFactor;
+ return successFactorDeviation;
}
/** Adds deployment traffic share to the given patch. */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingDatabaseMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingDatabaseMaintainer.java
index a7ebaec7c09..b40078eef51 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingDatabaseMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingDatabaseMaintainer.java
@@ -19,6 +19,6 @@ public class BillingDatabaseMaintainer extends ControllerMaintainer {
@Override
protected double maintain() {
controller().serviceRegistry().billingDatabase().maintain();
- return 1;
+ return 0.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudDatabaseMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudDatabaseMaintainer.java
index 914707aa318..68fd5c8bafe 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudDatabaseMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudDatabaseMaintainer.java
@@ -19,8 +19,8 @@ public class CloudDatabaseMaintainer extends ControllerMaintainer {
controller().serviceRegistry().billingController().updateCache(tenants);
} catch (Exception e) {
log.warning("Could not update cloud database cache: " + Exceptions.toMessageString(e));
- return 0.0;
+ return 1.0;
}
- return 1.0;
+ return 0.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java
index 6ecad482cd2..f9c93a87c44 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java
@@ -64,7 +64,7 @@ public class ContactInformationMaintainer extends ControllerMaintainer {
interval());
}
}
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainer.java
index c861d522818..f21803283eb 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainer.java
@@ -12,7 +12,6 @@ import java.util.EnumSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.logging.Logger;
/**
* A maintainer is some job which runs at a fixed interval to perform some maintenance task in the controller.
@@ -26,13 +25,22 @@ public abstract class ControllerMaintainer extends Maintainer {
/** The systems in which this maintainer should run */
private final Set<SystemName> activeSystems;
+
public ControllerMaintainer(Controller controller, Duration interval) {
- this(controller, interval, null, EnumSet.allOf(SystemName.class));
+ this(controller, interval, null, EnumSet.allOf(SystemName.class), 1.0);
+ }
+
+ public ControllerMaintainer(Controller controller, Duration interval, Double successFactorBaseline) {
+ this(controller, interval, null, EnumSet.allOf(SystemName.class), successFactorBaseline);
}
public ControllerMaintainer(Controller controller, Duration interval, String name, Set<SystemName> activeSystems) {
+ this(controller, interval, name, activeSystems, 1.0);
+ }
+
+ public ControllerMaintainer(Controller controller, Duration interval, String name, Set<SystemName> activeSystems, Double successFactorBaseline) {
super(name, interval, controller.clock(), controller.jobControl(),
- new ControllerJobMetrics(controller.metric()), controller.curator().cluster(), true);
+ new ControllerJobMetrics(controller.metric()), controller.curator().cluster(), true, successFactorBaseline);
this.controller = controller;
this.activeSystems = Set.copyOf(Objects.requireNonNull(activeSystems));
}
@@ -54,8 +62,8 @@ public abstract class ControllerMaintainer extends Maintainer {
}
@Override
- public void completed(String job, double successFactor, long durationMs) {
- metric.set("maintenance.successFactor", successFactor, metric.createContext(Map.of("job", job)));
+ public void completed(String job, double successFactorDeviation, long durationMs) {
+ metric.set("maintenance.successFactorDeviation", successFactorDeviation, metric.createContext(Map.of("job", job)));
metric.set("maintenance.duration", durationMs, metric.createContext(Map.of("job", job)));
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
index 05159b38ec6..7f48a1115c5 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
@@ -40,6 +40,7 @@ public class ControllerMaintenance extends AbstractComponent {
@SuppressWarnings("unused") // instantiated by Dependency Injection
public ControllerMaintenance(Controller controller, Metric metric, UserManagement userManagement, AthenzClientFactory athenzClientFactory) {
Intervals intervals = new Intervals(controller.system());
+ SuccessFactorBaseline successFactorBaseline = new SuccessFactorBaseline(controller.system());
upgrader = new Upgrader(controller, intervals.defaultInterval);
osUpgradeScheduler = new OsUpgradeScheduler(controller, intervals.osUpgradeScheduler);
maintainers.add(upgrader);
@@ -68,7 +69,7 @@ public class ControllerMaintenance extends AbstractComponent {
maintainers.add(new HostInfoUpdater(controller, intervals.hostInfoUpdater));
maintainers.add(new ReindexingTriggerer(controller, intervals.reindexingTriggerer));
maintainers.add(new EndpointCertificateMaintainer(controller, intervals.endpointCertificateMaintainer));
- maintainers.add(new BcpGroupUpdater(controller, intervals.trafficFractionUpdater));
+ maintainers.add(new BcpGroupUpdater(controller, intervals.trafficFractionUpdater, successFactorBaseline.trafficFractionUpdater));
maintainers.add(new ArchiveUriUpdater(controller, intervals.archiveUriUpdater));
maintainers.add(new ArchiveAccessMaintainer(controller, metric, intervals.archiveAccessMaintainer));
maintainers.add(new TenantRoleMaintainer(controller, intervals.tenantRoleMaintainer));
@@ -189,4 +190,15 @@ public class ControllerMaintenance extends AbstractComponent {
}
+ private static class SuccessFactorBaseline {
+
+ private final Double defaultSuccessFactorBaseline;
+ private final Double trafficFractionUpdater;
+
+ public SuccessFactorBaseline(SystemName system) {
+ Objects.requireNonNull(system);
+ this.defaultSuccessFactorBaseline = 1.0;
+ this.trafficFractionUpdater = system.isCd() ? 0.5 : 0.7;
+ }
+ }
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java
index 403b5aed1ce..668893d5a7e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainer.java
@@ -34,7 +34,7 @@ public class CostReportMaintainer extends ControllerMaintainer {
protected double maintain() {
var csv = CostCalculator.resourceShareByPropertyToCsv(nodeRepository, controller(), clock, consumer.fixedAllocations());
consumer.consume(csv);
- return 1.0;
+ return 0.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentExpirer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentExpirer.java
index 97f3f955a20..c22cb1efdb3 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentExpirer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentExpirer.java
@@ -5,8 +5,6 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.Instance;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobId;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.yolean.Exceptions;
@@ -47,7 +45,7 @@ public class DeploymentExpirer extends ControllerMaintainer {
}
}
}
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
/** Returns whether given deployment has expired according to its TTL */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentInfoMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentInfoMaintainer.java
index f6029eade37..d8d89177a9e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentInfoMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentInfoMaintainer.java
@@ -38,7 +38,7 @@ public class DeploymentInfoMaintainer extends ControllerMaintainer {
}
}
}
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
private Collection<DeploymentId> instanceDeployments(Instance instance) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java
index 6b058537c2d..c352fb053dc 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java
@@ -77,7 +77,7 @@ public class DeploymentIssueReporter extends ControllerMaintainer {
fileDeploymentIssueFor(application);
else
store(application.id(), null);
- return 1.0;
+ return 0.0;
}
/**
@@ -87,24 +87,24 @@ public class DeploymentIssueReporter extends ControllerMaintainer {
*/
private double maintainPlatformIssue(List<Application> applications) {
if (controller().system() == SystemName.cd)
- return 1.0;
+ return 0.0;
VersionStatus versionStatus = controller().readVersionStatus();
Version systemVersion = controller().systemVersion(versionStatus);
if (versionStatus.version(systemVersion).confidence() != broken)
- return 1.0;
+ return 0.0;
DeploymentStatusList statuses = controller().jobController().deploymentStatuses(ApplicationList.from(applications));
if (statuses.failingUpgradeToVersionSince(systemVersion, controller().clock().instant().minus(upgradeGracePeriod)).isEmpty())
- return 1.0;
+ return 0.0;
List<ApplicationId> failingApplications = statuses.failingUpgradeToVersionSince(systemVersion, controller().clock().instant())
.mapToList(status -> status.application().id().defaultInstance());
// TODO jonmv: Send only tenant and application, here and elsewhere in this.
deploymentIssues.fileUnlessOpen(failingApplications, systemVersion);
- return 1.0;
+ return 0.0;
}
private Tenant ownerOf(TenantAndApplicationId applicationId) {
@@ -145,7 +145,7 @@ public class DeploymentIssueReporter extends ControllerMaintainer {
log.log(Level.INFO, "Exception caught when attempting to escalate issue with id '" + issueId + "': " + Exceptions.toMessageString(e));
}
}));
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
private void store(TenantAndApplicationId id, IssueId issueId) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java
index fa917d2eb4e..427ee7c4b06 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java
@@ -96,7 +96,7 @@ public class DeploymentMetricsMaintainer extends ControllerMaintainer {
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
static DeploymentMetrics updateDeploymentMetrics(DeploymentMetrics current, List<ClusterMetrics> metrics) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java
index 934a1b4fa2f..8a3a2a11e09 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentUpgrader.java
@@ -78,7 +78,7 @@ public class DeploymentUpgrader extends ControllerMaintainer {
": " + Exceptions.toMessageString(e) + ". Retrying in " +
interval());
}
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
/** Returns whether query and feed metrics are ~zero, or currently platform has been deployed for a week. */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EnclaveAccessMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EnclaveAccessMaintainer.java
index 7af96d10f2f..5218da91c46 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EnclaveAccessMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EnclaveAccessMaintainer.java
@@ -26,7 +26,7 @@ public class EnclaveAccessMaintainer extends ControllerMaintainer {
return controller().serviceRegistry().enclaveAccessService().allowAccessFor(externalAccounts());
} catch (RuntimeException e) {
logger.log(WARNING, "Failed sharing resources with enclave", e);
- return 0;
+ return 1.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
index 0b96d8adc1a..713782eb7b9 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
@@ -75,10 +75,10 @@ public class EndpointCertificateMaintainer extends ControllerMaintainer {
deleteOrReportUnmanagedCertificates();
} catch (Exception e) {
log.log(Level.SEVERE, "Exception caught while maintaining endpoint certificates", e);
- return 0.0;
+ return 1.0;
}
- return 1.0;
+ return 0.0;
}
private void updateRefreshedCertificates() {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/HostInfoUpdater.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/HostInfoUpdater.java
index 1f21c688540..31236f4fcda 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/HostInfoUpdater.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/HostInfoUpdater.java
@@ -73,7 +73,7 @@ public class HostInfoUpdater extends ControllerMaintainer {
LOG.info("Updated information for " + hostsUpdated + " hosts(s)");
}
}
- return 1.0;
+ return 0.0;
}
private static Optional<String> modelNameOf(NodeEntity nodeEntity) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/InfrastructureUpgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/InfrastructureUpgrader.java
index b051590ac5a..68c79fdca7e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/InfrastructureUpgrader.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/InfrastructureUpgrader.java
@@ -50,7 +50,7 @@ public abstract class InfrastructureUpgrader<TARGET extends VersionTarget> exten
@Override
protected double maintain() {
return target().map(target -> upgradeAll(target, managedApplications))
- .orElse(1.0);
+ .orElse(0.0);
}
/** Deploy a list of system applications until they converge on the given version */
@@ -81,7 +81,7 @@ public abstract class InfrastructureUpgrader<TARGET extends VersionTarget> exten
break;
}
}
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
/** Returns whether all applications have converged to the target version in zone */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java
index 294d5bad42d..67188eb5e3a 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java
@@ -90,7 +90,7 @@ public class MetricsReporter extends ControllerMaintainer {
reportBrokenSystemVersion(versionStatus);
reportTenantMetrics();
reportZmsQuotaMetrics();
- return 1.0;
+ return 0.0;
}
private void reportBrokenSystemVersion(VersionStatus versionStatus) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java
index f930e64fc5a..f0d218ae6cf 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgradeScheduler.java
@@ -40,7 +40,7 @@ public class OsUpgradeScheduler extends ControllerMaintainer {
if (!change.get().scheduleAt(now)) continue;
controller().upgradeOsIn(cloud, change.get().version(), false);
}
- return 1.0;
+ return 0.0;
}
/** Returns the wanted change for cloud at given instant, if any */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsVersionStatusUpdater.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsVersionStatusUpdater.java
index 119540eaa68..c643df6af68 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsVersionStatusUpdater.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsVersionStatusUpdater.java
@@ -22,12 +22,12 @@ public class OsVersionStatusUpdater extends ControllerMaintainer {
try {
OsVersionStatus newStatus = OsVersionStatus.compute(controller());
controller().updateOsVersionStatus(newStatus);
- return 1.0;
+ return 0.0;
} catch (Exception e) {
log.log(Level.WARNING, "Failed to compute OS version status: " + Exceptions.toMessageString(e) +
". Retrying in " + interval());
}
- return 0.0;
+ return 1.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java
index 400673bfd0c..945b6d32a30 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java
@@ -53,11 +53,11 @@ public class ReindexingTriggerer extends ControllerMaintainer {
controller().applications().reindex(id, deployment.zone(), List.of(), List.of(), true, speed,
"bakground reindexing, to account for changes in built-in linguistics components");
});
- return 1.0;
+ return 0.0;
}
catch (RuntimeException e) {
log.log(Level.WARNING, "Failed to trigger reindexing: " + Exceptions.toMessageString(e));
- return 0.0;
+ return 1.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
index 3f20c2eac8f..52206d41c00 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
@@ -98,13 +98,13 @@ public class ResourceMeterMaintainer extends ControllerMaintainer {
} catch (Exception e) {
log.log(Level.WARNING, "Failed to collect resource snapshots. Retrying in " + interval() + ". Error: " +
Exceptions.toMessageString(e));
- return 0.0;
+ return 1.0;
}
if (systemName.isPublic()) reportResourceSnapshots(resourceSnapshots);
if (systemName.isPublic()) reportAllScalingEvents();
updateDeploymentCost(resourceSnapshots);
- return 1.0;
+ return 0.0;
}
void updateDeploymentCost(Collection<ResourceSnapshot> resourceSnapshots) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceTagMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceTagMaintainer.java
index 18ed154fcf1..59871f716e0 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceTagMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceTagMaintainer.java
@@ -43,7 +43,7 @@ public class ResourceTagMaintainer extends ControllerMaintainer {
if (taggedResources > 0)
log.log(Level.INFO, "Tagged " + taggedResources + " resources in " + zone.getId());
});
- return 1.0;
+ return 0.0;
}
private Map<HostName, ApplicationId> getTenantOfParentHosts(ZoneId zoneId) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainer.java
index 74bb89e4105..aaf730cc158 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RetriggerMaintainer.java
@@ -47,9 +47,9 @@ public class RetriggerMaintainer extends ControllerMaintainer {
controller().curator().writeRetriggerEntries(remaining);
} catch (Exception e) {
logger.log(Level.WARNING, "Exception while triggering jobs", e);
- return 0.0;
+ return 1.0;
}
- return 1.0;
+ return 0.0;
}
/** Returns true if a job is ready to run, i.e. is currently not running */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleCleanupMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleCleanupMaintainer.java
index f29df1bc0d5..e3a3415e170 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleCleanupMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleCleanupMaintainer.java
@@ -26,6 +26,6 @@ public class TenantRoleCleanupMaintainer extends ControllerMaintainer {
controller().serviceRegistry().tenantSecretService().cleanupSecretStores(deletedTenants);
}
- return 1.0;
+ return 0.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java
index bd121871c7c..c7b236880fd 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java
@@ -37,7 +37,7 @@ public class TenantRoleMaintainer extends ControllerMaintainer {
controller().tenants().updateLastTenantRolesMaintained(t.name(), updated);
});
- return 1.0;
+ return 0.0;
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
index 82b3141e503..edcfcc317a7 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java
@@ -64,7 +64,7 @@ public class Upgrader extends ControllerMaintainer {
for (UpgradePolicy policy : UpgradePolicy.values())
updateTargets(versionStatus, deploymentStatuses, policy);
- return 1.0;
+ return 0.0;
}
private DeploymentStatusList deploymentStatuses(VersionStatus versionStatus) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/UserManagementMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/UserManagementMaintainer.java
index 03987efab8b..7c4645a6e48 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/UserManagementMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/UserManagementMaintainer.java
@@ -11,6 +11,7 @@ import java.util.Optional;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+
/**
* Maintains user management resources.
* For now, ensures there's no discrepnacy between expected tenant/application roles and auth0/athenz roles
@@ -46,7 +47,7 @@ public class UserManagementMaintainer extends ControllerMaintainer {
});
}
- return 1.0;
+ return 0.0;
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java
index da0fa890960..9271f870390 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java
@@ -90,7 +90,7 @@ public class VcmrMaintainer extends ControllerMaintainer {
}
});
updateMetrics();
- return 1.0;
+ return 0.0;
}
/**
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdater.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdater.java
index 154455c5198..1c4d13aa16d 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdater.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VersionStatusUpdater.java
@@ -39,12 +39,12 @@ public class VersionStatusUpdater extends ControllerMaintainer {
controller().serviceRegistry().systemMonitor().reportSystemVersion(version.versionNumber(),
convert(version.confidence()));
});
- return 1.0;
+ return 0.0;
} catch (Exception e) {
log.log(Level.WARNING, "Failed to compute version status: " + Exceptions.toMessageString(e) +
". Retrying in " + interval());
}
- return 0.0;
+ return 1.0;
}
static SystemMonitor.Confidence convert(VespaVersion.Confidence confidence) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
index e9947f3d565..45c00848407 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java
@@ -41,8 +41,8 @@ public record VespaVersion(Version version,
.not().upgradingTo(statistics.version());
InstanceList failingOnThis = all.matching(instance -> statistics.failingUpgrades().stream().anyMatch(run -> run.id().application().equals(instance)));
- // 'broken' if any canary fails
- if ( ! failingOnThis.with(UpgradePolicy.canary).isEmpty())
+ // 'broken' if any canary fails, and no non-canary is upgraded
+ if ( ! failingOnThis.with(UpgradePolicy.canary).isEmpty() && productionOnThis.not().with(UpgradePolicy.canary).isEmpty())
return Confidence.broken;
// 'broken' if 6 non-canary was broken by this, and that is at least 5% of all
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java
index a76d2eca521..ca31ceebc17 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java
@@ -126,7 +126,7 @@ public class EndpointTest {
Endpoint.of(instance1).target(cluster, prodZone).on(Port.tls()).in(SystemName.main),
// Prod endpoint in CD
- "https://cd.a1.t1.us-north-1.vespa.oath.cloud/",
+ "https://cd.a1.t1.us-north-1.cd.vespa.oath.cloud/",
Endpoint.of(instance1).target(cluster, prodZone).on(Port.tls()).in(SystemName.cd),
// Test endpoint in main
@@ -300,7 +300,7 @@ public class EndpointTest {
.routingMethod(RoutingMethod.exclusive)
.on(Port.tls())
.in(SystemName.main),
- "cd.a2.t2.us-east-3-r.vespa.oath.cloud",
+ "cd.a2.t2.us-east-3-r.cd.vespa.oath.cloud",
Endpoint.of(app2)
.targetApplication(EndpointId.defaultId(), ClusterSpec.Id.from("qrs"),
Map.of(new DeploymentId(app2.instance("i1"), ZoneId.from("prod", "us-east-3")), 1))
@@ -335,7 +335,7 @@ public class EndpointTest {
.routingMethod(RoutingMethod.exclusive)
.on(Port.tls())
.in(SystemName.main),
- "https://cd.a2.t2.a.vespa.oath.cloud/",
+ "https://cd.a2.t2.a.cd.vespa.oath.cloud/",
Endpoint.of(app2)
.targetApplication(EndpointId.defaultId(), ClusterSpec.Id.from("qrs"),
Map.of(new DeploymentId(app2.instance("i1"), ZoneId.from("prod", "us-east-3")), 1))
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdaterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdaterTest.java
index 5deba19c5ea..b8b05bfcfc1 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdaterTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BcpGroupUpdaterTest.java
@@ -45,7 +45,7 @@ public class BcpGroupUpdaterTest {
tester.controllerTester().upgradeSystem(Version.fromString("7.1"));
var context = tester.newDeploymentContext();
var deploymentMetricsMaintainer = new DeploymentMetricsMaintainer(tester.controller(), Duration.ofDays(1));
- var updater = new BcpGroupUpdater(tester.controller(), Duration.ofDays(1));
+ var updater = new BcpGroupUpdater(tester.controller(), Duration.ofDays(1), 1.0);
ZoneId prod1 = ZoneId.from("prod", "ap-northeast-1");
ZoneId prod2 = ZoneId.from("prod", "us-east-3");
ZoneId prod3 = ZoneId.from("prod", "us-west-1");
@@ -57,7 +57,7 @@ public class BcpGroupUpdaterTest {
setQpsMetric(50.0, context.application().id().defaultInstance(), prod1, tester);
setBcpMetrics(1.5, 0.1, 0.45, context.instanceId(), prod1, "cluster1", tester);
deploymentMetricsMaintainer.maintain();
- assertEquals(1.0, updater.maintain(), 0.0000001);
+ assertEquals(0.0, updater.maintain(), 0.0000001);
assertTrafficFraction(1.0, 1.0, context.instanceId(), prod1, tester);
assertNoBcpGroupInfo(context.instanceId(), prod1, "cluster1", tester, "No other regions in group");
@@ -67,7 +67,7 @@ public class BcpGroupUpdaterTest {
setQpsMetric(20.0, context.application().id().defaultInstance(), prod2, tester);
setBcpMetrics(100.0, 0.1, 0.45, context.instanceId(), prod1, "cluster1", tester);
deploymentMetricsMaintainer.maintain();
- assertEquals(1.0, updater.maintain(), 0.0000001);
+ assertEquals(0.0, updater.maintain(), 0.0000001);
assertTrafficFraction(0.75, 1.0, context.instanceId(), prod1, tester);
assertTrafficFraction(0.25, 1.0, context.instanceId(), prod2, tester);
assertNoBcpGroupInfo(context.instanceId(), prod1, "cluster1", tester,
@@ -75,7 +75,7 @@ public class BcpGroupUpdaterTest {
assertBcpGroupInfo(100.0, 0.1, 0.45,
context.instanceId(), prod2, "cluster1", tester);
setBcpMetrics(50.0, 0.2, 0.5, context.instanceId(), prod2, "cluster1", tester);
- assertEquals(1.0, updater.maintain(), 0.0000001);
+ assertEquals(0.0, updater.maintain(), 0.0000001);
assertBcpGroupInfo(50.0, 0.2, 0.5,
context.instanceId(), prod1, "cluster1", tester);
@@ -85,7 +85,7 @@ public class BcpGroupUpdaterTest {
setQpsMetric(45.0, context.application().id().defaultInstance(), prod2, tester);
setQpsMetric(02.0, context.application().id().defaultInstance(), prod3, tester);
deploymentMetricsMaintainer.maintain();
- assertEquals(1.0, updater.maintain(), 0.0000001);
+ assertEquals(0.0, updater.maintain(), 0.0000001);
assertTrafficFraction(0.53, 0.53 + (double)45/2 / 100, context.instanceId(), prod1, tester);
assertTrafficFraction(0.45, 0.45 + (double)53/2 / 100, context.instanceId(), prod2, tester);
assertTrafficFraction(0.02, 0.02 + (double)53/2 / 100, context.instanceId(), prod3, tester);
@@ -129,7 +129,7 @@ public class BcpGroupUpdaterTest {
locked -> tester.controller().applications().store(locked.with(deploymentSpec)));
var deploymentMetricsMaintainer = new DeploymentMetricsMaintainer(tester.controller(), Duration.ofDays(1));
- var updater = new BcpGroupUpdater(tester.controller(), Duration.ofDays(1));
+ var updater = new BcpGroupUpdater(tester.controller(), Duration.ofDays(1), 1.0);
ZoneId ap1 = ZoneId.from("prod", "ap-northeast-1");
ZoneId ap2 = ZoneId.from("prod", "ap-southeast-1");
@@ -150,7 +150,7 @@ public class BcpGroupUpdaterTest {
setQpsMetric(40.0, context.application().id().defaultInstance(), eu1, tester);
deploymentMetricsMaintainer.maintain();
- assertEquals(1.0, updater.maintain(), 0.0000001);
+ assertEquals(0.0, updater.maintain(), 0.0000001);
assertTrafficFraction(0.5, 0.5, context.instanceId(), ap1, tester);
assertTrafficFraction(0.0, 0.5, context.instanceId(), ap2, tester);
assertTrafficFraction(0.1, 0.1, context.instanceId(), us1, tester);
@@ -197,7 +197,7 @@ public class BcpGroupUpdaterTest {
locked -> tester.controller().applications().store(locked.with(deploymentSpec)));
var deploymentMetricsMaintainer = new DeploymentMetricsMaintainer(tester.controller(), Duration.ofDays(1));
- var updater = new BcpGroupUpdater(tester.controller(), Duration.ofDays(1));
+ var updater = new BcpGroupUpdater(tester.controller(), Duration.ofDays(1), 1.0);
ZoneId ap1 = ZoneId.from("prod", "ap-northeast-1");
ZoneId ap2 = ZoneId.from("prod", "ap-southeast-1");
@@ -221,7 +221,7 @@ public class BcpGroupUpdaterTest {
setQpsMetric(60.0, context.application().id().defaultInstance(), eu1, tester);
deploymentMetricsMaintainer.maintain();
- assertEquals(1.0, updater.maintain(), 0.0000001);
+ assertEquals(0.0, updater.maintain(), 0.0000001);
assertTrafficFraction(0.10, 0.10 + 50 / 200.0 / 1.5, context.instanceId(), ap1, tester);
assertTrafficFraction(0.25, 0.25 + 30 / 200.0 / 1.5, context.instanceId(), ap2, tester);
assertTrafficFraction(0.00, 0.00 + 40 / 200.0 / 2.5, context.instanceId(), us1, tester);
@@ -242,7 +242,7 @@ public class BcpGroupUpdaterTest {
setBcpMetrics(300, 0.3, 0.3, context.instanceId(), us3, "cluster2", tester);
setBcpMetrics(100, 0.1, 0.1, context.instanceId(), eu1, "cluster2", tester);
- assertEquals(1.0, updater.maintain(), 0.0000001);
+ assertEquals(0.0, updater.maintain(), 0.0000001);
assertNoBcpGroupInfo(context.instanceId(), ap1, "cluster1", tester, "No info in ap");
assertNoBcpGroupInfo(context.instanceId(), ap2, "cluster1", tester, "No info in ap");
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainerTest.java
index 63e2c99cb6e..6452edc9e61 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintainerTest.java
@@ -38,14 +38,14 @@ public class ControllerMaintainerTest {
void records_metric() {
TestControllerMaintainer maintainer = new TestControllerMaintainer(tester.controller(), SystemName.main, new AtomicInteger());
maintainer.run();
- assertEquals(1.0, successFactorMetric(), 0.0000001);
+ assertEquals(0.0, successFactorDeviationMetric(), 0.0000001);
maintainer.success = false;
maintainer.run();
maintainer.run();
- assertEquals(0.0, successFactorMetric(), 0.0000001);
+ assertEquals(1.0, successFactorDeviationMetric(), 0.0000001);
maintainer.success = true;
maintainer.run();
- assertEquals(1.0, successFactorMetric(), 0.0000001);
+ assertEquals(0.0, successFactorDeviationMetric(), 0.0000001);
}
private long consecutiveFailuresMetric() {
@@ -54,10 +54,10 @@ public class ControllerMaintainerTest {
"maintenance.consecutiveFailures").get().longValue();
}
- private long successFactorMetric() {
+ private long successFactorDeviationMetric() {
MetricsMock metrics = (MetricsMock) tester.controller().metric();
return metrics.getMetric((context) -> "TestControllerMaintainer".equals(context.get("job")),
- "maintenance.successFactor").get().longValue();
+ "maintenance.successFactorDeviation").get().longValue();
}
private static class TestControllerMaintainer extends ControllerMaintainer {
@@ -73,7 +73,7 @@ public class ControllerMaintainerTest {
@Override
protected double maintain() {
executions.incrementAndGet();
- return success ? 1.0 : 0.0;
+ return success ? 0.0 : 1.0;
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java
index 934e15ad623..49cf8c634ba 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java
@@ -49,7 +49,7 @@ public class EndpointCertificateMaintainerTest {
@Test
void old_and_unused_cert_is_deleted() {
tester.curator().writeEndpointCertificateMetadata(ApplicationId.defaultId(), exampleMetadata);
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
assertTrue(tester.curator().readEndpointCertificateMetadata(ApplicationId.defaultId()).isEmpty());
}
@@ -57,7 +57,7 @@ public class EndpointCertificateMaintainerTest {
void unused_but_recently_used_cert_is_not_deleted() {
EndpointCertificateMetadata recentlyRequestedCert = exampleMetadata.withLastRequested(tester.clock().instant().minusSeconds(3600).getEpochSecond());
tester.curator().writeEndpointCertificateMetadata(ApplicationId.defaultId(), recentlyRequestedCert);
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
assertEquals(Optional.of(recentlyRequestedCert), tester.curator().readEndpointCertificateMetadata(ApplicationId.defaultId()));
}
@@ -69,7 +69,7 @@ public class EndpointCertificateMaintainerTest {
secretStore.setSecret(exampleMetadata.keyName(), "foo", 1);
secretStore.setSecret(exampleMetadata.certName(), "bar", 1);
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
var updatedCert = Optional.of(recentlyRequestedCert.withLastRefreshed(tester.clock().instant().getEpochSecond()).withVersion(1));
@@ -90,7 +90,7 @@ public class EndpointCertificateMaintainerTest {
deploymentContext.submit(applicationPackage).runJob(systemTest).runJob(stagingTest).runJob(productionUsWest1);
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
var metadata = tester.curator().readEndpointCertificateMetadata(appId).orElseThrow();
tester.controller().serviceRegistry().endpointCertificateProvider().certificateDetails(metadata.rootRequestId()); // cert should not be deleted, the app is deployed!
}
@@ -110,7 +110,7 @@ public class EndpointCertificateMaintainerTest {
var originalMetadata = tester.curator().readEndpointCertificateMetadata(appId).orElseThrow();
// cert should not be deleted, the app is deployed!
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
assertEquals(tester.curator().readEndpointCertificateMetadata(appId), Optional.of(originalMetadata));
tester.controller().serviceRegistry().endpointCertificateProvider().certificateDetails(originalMetadata.rootRequestId());
@@ -121,7 +121,7 @@ public class EndpointCertificateMaintainerTest {
tester.controller().serviceRegistry().endpointCertificateProvider().requestCaSignedCertificate(appId, originalMetadata.requestedDnsSans(), Optional.of(originalMetadata));
// We should now pick up the new key and cert version + uuid, but not force trigger deployment yet
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
deploymentContext.assertNotRunning(productionUsWest1);
var updatedMetadata = tester.curator().readEndpointCertificateMetadata(appId).orElseThrow();
assertNotEquals(originalMetadata.leafRequestId().orElseThrow(), updatedMetadata.leafRequestId().orElseThrow());
@@ -130,7 +130,7 @@ public class EndpointCertificateMaintainerTest {
// after another 4 days, we should force trigger deployment if it hasn't already happened
tester.clock().advance(Duration.ofDays(4).plusSeconds(1));
deploymentContext.assertNotRunning(productionUsWest1);
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
deploymentContext.assertRunning(productionUsWest1);
}
@@ -156,7 +156,7 @@ public class EndpointCertificateMaintainerTest {
ApplicationId unknown = ApplicationId.fromSerializedForm("applicationid:is:unknown");
endpointCertificateProvider.requestCaSignedCertificate(unknown, List.of("a", "b", "c"), Optional.empty()); // Unknown to controller!
- assertEquals(1.0, maintainer.maintain(), 0.0000001);
+ assertEquals(0.0, maintainer.maintain(), 0.0000001);
assertTrue(endpointCertificateProvider.dnsNamesOf(unknown).isEmpty());
assertTrue(endpointCertificateProvider.listCertificates().isEmpty());
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java
index 43ad01fc5c2..168a1345c39 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java
@@ -18,7 +18,6 @@ import org.junit.jupiter.api.Test;
import java.net.URI;
import java.util.List;
import java.util.Set;
-import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -155,7 +154,7 @@ public class RotationRepositoryTest {
var application2 = tester.newDeploymentContext("tenant2", "app2", "default");
application2.submit(applicationPackage).deploy();
assertEquals(List.of(new RotationId("foo-1")), rotationIds(application2.instance().rotations()));
- assertEquals("https://cd.app2.tenant2.global.vespa.oath.cloud/",
+ assertEquals("https://cd.app2.tenant2.global.cd.vespa.oath.cloud/",
tester.controller().routing().readDeclaredEndpointsOf(application2.instanceId()).primary().get().url().toString());
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
index f08e92a515d..7afa5c7f44a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/versions/VersionStatusTest.java
@@ -349,6 +349,13 @@ public class VersionStatusTest {
assertEquals(Confidence.high, confidence(tester.controller(), version0), "Confidence remains unchanged for version0: High");
assertEquals(VespaVersion.Confidence.high, confidence(tester.controller(), version2), "90% of defaults deployed successfully: High");
+ // Canary failing a new revision does not affect confidence
+ canary0.submit(canaryPolicy).failDeployment(systemTest);
+ tester.controllerTester().computeVersionStatus();
+ assertEquals(Confidence.high, confidence(tester.controller(), version0), "Confidence remains unchanged for version0: High");
+ assertEquals(VespaVersion.Confidence.high, confidence(tester.controller(), version2), "90% of defaults deployed successfully: High");
+ canary0.deploy();
+
// A new version is released, all canaries upgrade successfully, but enough "default" apps fail to mark version
// as broken
Version version3 = new Version("6.5");
diff --git a/default_build_settings.cmake b/default_build_settings.cmake
index c82bb91accc..2785a98a396 100644
--- a/default_build_settings.cmake
+++ b/default_build_settings.cmake
@@ -4,11 +4,11 @@ include(VespaExtendedDefaultBuildSettings OPTIONAL)
function(setup_vespa_default_build_settings_darwin)
message("-- Setting up default build settings for darwin")
- set(DEFAULT_EXTRA_LINK_DIRECTORY "${VESPA_DEPS_PREFIX}/lib" "/usr/local/opt/bison/lib" "/usr/local/opt/flex/lib" "/usr/local/opt/icu4c/lib" "/usr/local/opt/openssl@1.1/lib" "/usr/local/opt/openblas/lib")
- list(APPEND DEFAULT_EXTRA_LINK_DIRECTORY "/usr/local/lib")
+ set(DEFAULT_EXTRA_LINK_DIRECTORY "${VESPA_DEPS_PREFIX}/lib" "${VESPA_HOMEBREW_PREFIX}/opt/bison/lib" "${VESPA_HOMEBREW_PREFIX}/opt/flex/lib" "${VESPA_HOMEBREW_PREFIX}/opt/icu4c/lib" "${VESPA_HOMEBREW_PREFIX}/opt/openssl@1.1/lib" "${VESPA_HOMEBREW_PREFIX}/opt/openblas/lib")
+ list(APPEND DEFAULT_EXTRA_LINK_DIRECTORY "${VESPA_HOMEBREW_PREFIX}/lib")
set(DEFAULT_EXTRA_LINK_DIRECTORY "${DEFAULT_EXTRA_LINK_DIRECTORY}" PARENT_SCOPE)
- set(DEFAULT_EXTRA_INCLUDE_DIRECTORY "${VESPA_DEPS_PREFIX}/include" "/usr/local/opt/flex/include" "/usr/local/opt/icu4c/include" "/usr/local/opt/openssl@1.1/include" "/usr/local/opt/openblas/include")
- list(APPEND DEFAULT_EXTRA_INCLUDE_DIRECTORY "/usr/local/include")
+ set(DEFAULT_EXTRA_INCLUDE_DIRECTORY "${VESPA_DEPS_PREFIX}/include" "${VESPA_HOMEBREW_PREFIX}/opt/flex/include" "${VESPA_HOMEBREW_PREFIX}/opt/icu4c/include" "${VESPA_HOMEBREW_PREFIX}/opt/openssl@1.1/include" "${VESPA_HOMEBREW_PREFIX}/opt/openblas/include")
+ list(APPEND DEFAULT_EXTRA_INCLUDE_DIRECTORY "${VESPA_HOMEBREW_PREFIX}/include")
set(DEFAULT_EXTRA_INCLUDE_DIRECTORY "${DEFAULT_EXTRA_INCLUDE_DIRECTORY}" PARENT_SCOPE)
endfunction()
@@ -84,7 +84,7 @@ endfunction()
function(vespa_use_default_cmake_prefix_path)
set(DEFAULT_CMAKE_PREFIX_PATH ${VESPA_DEPS_PREFIX})
if (APPLE)
- list(APPEND DEFAULT_CMAKE_PREFIX_PATH "/usr/local/opt/bison" "/usr/local/opt/flex" "/usr/local/opt/openssl@1.1" "/usr/local/opt/openblas" "/usr/local/opt/icu4c")
+ list(APPEND DEFAULT_CMAKE_PREFIX_PATH "${VESPA_HOMEBREW_PREFIX}/opt/bison" "${VESPA_HOMEBREW_PREFIX}/opt/flex" "${VESPA_HOMEBREW_PREFIX}/opt/openssl@1.1" "${VESPA_HOMEBREW_PREFIX}/opt/openblas" "${VESPA_HOMEBREW_PREFIX}/opt/icu4c")
endif()
message("-- DEFAULT_CMAKE_PREFIX_PATH is ${DEFAULT_CMAKE_PREFIX_PATH}")
if(NOT DEFINED CMAKE_PREFIX_PATH)
@@ -203,8 +203,8 @@ function(vespa_use_default_cxx_compiler)
unset(DEFAULT_CMAKE_CXX_COMPILER)
if(NOT DEFINED VESPA_COMPILER_VARIANT OR VESPA_COMPILER_VARIANT STREQUAL "gcc")
if(APPLE)
- set(DEFAULT_CMAKE_C_COMPILER "/usr/local/bin/gcc-12")
- set(DEFAULT_CMAKE_CXX_COMPILER "/usr/local/bin/g++-12")
+ set(DEFAULT_CMAKE_C_COMPILER "${VESPA_HOMEBREW_PREFIX}/bin/gcc-12")
+ set(DEFAULT_CMAKE_CXX_COMPILER "${VESPA_HOMEBREW_PREFIX}/bin/g++-12")
elseif(VESPA_OS_DISTRO_COMBINED STREQUAL "amzn 2")
set(DEFAULT_CMAKE_C_COMPILER "/usr/bin/gcc10-gcc")
set(DEFAULT_CMAKE_CXX_COMPILER "/usr/bin/gcc10-g++")
@@ -215,8 +215,8 @@ function(vespa_use_default_cxx_compiler)
endif()
elseif(VESPA_COMPILER_VARIANT STREQUAL "clang")
if(APPLE)
- set(DEFAULT_CMAKE_C_COMPILER, "/usr/local/opt/llvm/bin/clang")
- set(DEFAULT_CMAKE_CXX_COMPILER "/usr/local/opt/llvm/bin/clang++")
+ set(DEFAULT_CMAKE_C_COMPILER, "${VESPA_HOMEBREW_PREFIX}/opt/llvm/bin/clang")
+ set(DEFAULT_CMAKE_CXX_COMPILER "${VESPA_HOMEBREW_PREFIX}/opt/llvm/bin/clang++")
elseif(EXISTS "/usr/bin/clang" AND EXISTS "/usr/bin/clang++")
set(DEFAULT_CMAKE_C_COMPILER "/usr/bin/clang")
set(DEFAULT_CMAKE_CXX_COMPILER "/usr/bin/clang++")
diff --git a/document/src/vespa/document/select/parse_utils.cpp b/document/src/vespa/document/select/parse_utils.cpp
index 95461442349..4c116d5bff4 100644
--- a/document/src/vespa/document/select/parse_utils.cpp
+++ b/document/src/vespa/document/select/parse_utils.cpp
@@ -24,7 +24,7 @@ parse_i64(const char* str, size_t len, int64_t& out) {
}
bool
parse_double(const char* str, size_t len, double& out) {
-#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
+#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000
// Temporary workaround that also handles underflow (cf. issue 3081)
// until libc++ supports std::from_chars for double
char *str_end = const_cast<char*>(str) + len;
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
index 299d8c5d1e3..f24e9b9b7a5 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
@@ -57,7 +57,7 @@ public class Flags {
public static final UnboundBooleanFlag DROP_CACHES = defineFeatureFlag(
"drop-caches", false,
- List.of("hakonhall", "baldersheim"), "2023-03-06", "2023-04-05",
+ List.of("hakonhall", "baldersheim"), "2023-03-06", "2023-06-05",
"Drop caches on tenant hosts",
"Takes effect on next tick",
ZONE_ID,
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
index 336edf74e8f..dea0dbd3623 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
@@ -347,6 +347,12 @@ public class PermanentFlags {
"Takes effect immediately",
TENANT_ID);
+ public static final UnboundIntFlag KEEP_FILE_REFERENCES_ON_TENANT_NODES = defineIntFlag(
+ "keep-file-references-on-tenant-nodes", 14,
+ "How many days to keep file references on tenant nodes (based on last modification time)",
+ "Takes effect on restart of Docker container",
+ ZONE_ID, APPLICATION_ID
+ );
private PermanentFlags() {}
diff --git a/functions.cmake b/functions.cmake
index 7fa0b0db954..7f217867314 100644
--- a/functions.cmake
+++ b/functions.cmake
@@ -746,6 +746,14 @@ function(vespa_detect_build_platform)
elseif(APPLE)
set(OS_DISTRO "darwin")
set(OS_DISTRO_VERSION ${CMAKE_SYSTEM_VERSION})
+ if(EXISTS "/opt/homebrew/bin/brew")
+ set(VESPA_HOMEBREW_PREFIX "/opt/homebrew")
+ elseif(EXISTS "/usr/local/bin/brew")
+ set(VESPA_HOMEBREW_PREFIX "/usr/local")
+ else()
+ message(FATAL_ERROR "-- Cannot determine homebrew prefix")
+ endif()
+ set(VESPA_HOMEBREW_PREFIX ${VESPA_HOMEBREW_PREFIX} PARENT_SCOPE)
endif()
if(OS_DISTRO)
set(VESPA_OS_DISTRO ${OS_DISTRO} PARENT_SCOPE)
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/CoreDumpMetadata.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/CoreDumpMetadata.java
index 7367a254b4a..eceb83a6cba 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/CoreDumpMetadata.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/CoreDumpMetadata.java
@@ -12,6 +12,9 @@ import java.util.Optional;
* @author hakonhall
*/
public class CoreDumpMetadata {
+ public enum Type { CORE_DUMP, JVM_HEAP, OOM }
+
+ private Type type;
private String binPath;
private List<String> backtrace;
private List<String> backtraceAllThreads;
@@ -24,30 +27,33 @@ public class CoreDumpMetadata {
public CoreDumpMetadata() {}
- public Optional<String> binPath() { return Optional.ofNullable(binPath); };
- public Optional<List<String>> backtrace() { return Optional.ofNullable(backtrace); };
- public Optional<List<String>> backtraceAllThreads() { return Optional.ofNullable(backtraceAllThreads); };
- public Optional<Path> coredumpPath() { return Optional.ofNullable(coreDumpPath); };
+ public Optional<Type> type() { return Optional.ofNullable(type); }
+ public Optional<String> binPath() { return Optional.ofNullable(binPath); }
+ public Optional<List<String>> backtrace() { return Optional.ofNullable(backtrace); }
+ public Optional<List<String>> backtraceAllThreads() { return Optional.ofNullable(backtraceAllThreads); }
+ public Optional<Path> coredumpPath() { return Optional.ofNullable(coreDumpPath); }
public Optional<String> decryptionToken() { return Optional.ofNullable(decryptionToken); }
- public Optional<String> kernelVersion() { return Optional.ofNullable(kernelVersion); };
- public Optional<String> cpuMicrocodeVersion() { return Optional.ofNullable(cpuMicrocodeVersion); };
- public Optional<DockerImage> dockerImage() { return Optional.ofNullable(dockerImage); };
- public Optional<String> vespaVersion() { return Optional.ofNullable(vespaVersion); };
+ public Optional<String> kernelVersion() { return Optional.ofNullable(kernelVersion); }
+ public Optional<String> cpuMicrocodeVersion() { return Optional.ofNullable(cpuMicrocodeVersion); }
+ public Optional<DockerImage> dockerImage() { return Optional.ofNullable(dockerImage); }
+ public Optional<String> vespaVersion() { return Optional.ofNullable(vespaVersion); }
- public CoreDumpMetadata setBinPath(String binPath) { this.binPath = binPath; return this; };
- public CoreDumpMetadata setBacktrace(List<String> backtrace) { this.backtrace = backtrace; return this; };
- public CoreDumpMetadata setBacktraceAllThreads(List<String> backtraceAllThreads) { this.backtraceAllThreads = backtraceAllThreads; return this; };
- public CoreDumpMetadata setCoreDumpPath(Path coreDumpPath) { this.coreDumpPath = coreDumpPath; return this; };
+ public CoreDumpMetadata setType(Type type) { this.type = type; return this; }
+ public CoreDumpMetadata setBinPath(String binPath) { this.binPath = binPath; return this; }
+ public CoreDumpMetadata setBacktrace(List<String> backtrace) { this.backtrace = backtrace; return this; }
+ public CoreDumpMetadata setBacktraceAllThreads(List<String> backtraceAllThreads) { this.backtraceAllThreads = backtraceAllThreads; return this; }
+ public CoreDumpMetadata setCoreDumpPath(Path coreDumpPath) { this.coreDumpPath = coreDumpPath; return this; }
public CoreDumpMetadata setDecryptionToken(String decryptionToken) { this.decryptionToken = decryptionToken; return this; }
- public CoreDumpMetadata setKernelVersion(String kernelVersion) { this.kernelVersion = kernelVersion; return this; };
- public CoreDumpMetadata setCpuMicrocodeVersion(String cpuMicrocodeVersion) { this.cpuMicrocodeVersion = cpuMicrocodeVersion; return this; };
- public CoreDumpMetadata setDockerImage(DockerImage dockerImage) { this.dockerImage = dockerImage; return this; };
- public CoreDumpMetadata setVespaVersion(String vespaVersion) { this.vespaVersion = vespaVersion; return this; };
+ public CoreDumpMetadata setKernelVersion(String kernelVersion) { this.kernelVersion = kernelVersion; return this; }
+ public CoreDumpMetadata setCpuMicrocodeVersion(String cpuMicrocodeVersion) { this.cpuMicrocodeVersion = cpuMicrocodeVersion; return this; }
+ public CoreDumpMetadata setDockerImage(DockerImage dockerImage) { this.dockerImage = dockerImage; return this; }
+ public CoreDumpMetadata setVespaVersion(String vespaVersion) { this.vespaVersion = vespaVersion; return this; }
@Override
public String toString() {
return "CoreDumpMetadata{" +
- "binPath=" + binPath +
+ "type=" + type +
+ ", binPath=" + binPath +
", backtrace=" + backtrace +
", backtraceAllThreads=" + backtraceAllThreads +
", coreDumpPath=" + coreDumpPath +
@@ -64,7 +70,8 @@ public class CoreDumpMetadata {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CoreDumpMetadata metadata = (CoreDumpMetadata) o;
- return Objects.equals(binPath, metadata.binPath) &&
+ return type == metadata.type &&
+ Objects.equals(binPath, metadata.binPath) &&
Objects.equals(backtrace, metadata.backtrace) &&
Objects.equals(backtraceAllThreads, metadata.backtraceAllThreads) &&
Objects.equals(coreDumpPath, metadata.coreDumpPath) &&
@@ -77,7 +84,7 @@ public class CoreDumpMetadata {
@Override
public int hashCode() {
- return Objects.hash(binPath, backtrace, backtraceAllThreads, coreDumpPath, decryptionToken, kernelVersion,
+ return Objects.hash(type, binPath, backtrace, backtraceAllThreads, coreDumpPath, decryptionToken, kernelVersion,
cpuMicrocodeVersion, dockerImage, vespaVersion);
}
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/bindings/ReportCoreDumpRequest.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/bindings/ReportCoreDumpRequest.java
index 27cf28b8e1e..cf717aff787 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/bindings/ReportCoreDumpRequest.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/cores/bindings/ReportCoreDumpRequest.java
@@ -31,6 +31,7 @@ public class ReportCoreDumpRequest {
public List<String> backtrace;
public List<String> backtrace_all_threads;
+ public String type;
public String bin_path;
public String coredump_path;
public String cpu_microcode_version;
@@ -44,6 +45,7 @@ public class ReportCoreDumpRequest {
/** Fill this from metadata and return this. */
@JsonIgnore
public ReportCoreDumpRequest fillFrom(CoreDumpMetadata metadata) {
+ metadata.type().ifPresent(type -> this.type = type.name());
metadata.binPath().ifPresent(binPath -> this.bin_path = binPath);
metadata.backtrace().ifPresent(backtrace -> this.backtrace = List.copyOf(backtrace));
metadata.backtraceAllThreads().ifPresent(backtraceAllThreads -> this.backtrace_all_threads = List.copyOf(backtraceAllThreads));
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollector.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollector.java
index 28773767d24..4761b6da421 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollector.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollector.java
@@ -99,14 +99,15 @@ public class CoreCollector {
var metadata = new CoreDumpMetadata();
if (JAVA_HEAP_DUMP_PATTERN.matcher(coredumpPath.getFileName().toString()).find()) {
- metadata.setBinPath("java")
+ metadata.setType(CoreDumpMetadata.Type.JVM_HEAP)
+ .setBinPath("java")
.setBacktrace(List.of("Heap dump, no backtrace available"));
return metadata;
}
try {
String binPath = readBinPath(context, coredumpPath);
- metadata.setBinPath(binPath);
+ metadata.setType(CoreDumpMetadata.Type.CORE_DUMP).setBinPath(binPath);
if (Path.of(binPath).getFileName().toString().equals("java")) {
metadata.setBacktraceAllThreads(readJstack(context, coredumpPath, binPath));
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
index c7d34a12f43..9662d4184df 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
@@ -91,7 +91,7 @@ public class SystemCtl {
public String getServiceProperty(TaskContext context, String unit, String property) {
return newCommandLine(context)
.add("systemctl", "show", "--property", property, "--value", unit + ".service")
- .execute()
+ .executeSilently()
.getOutput();
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollectorTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollectorTest.java
index 4fa18c71da0..2ca9e084d96 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollectorTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/coredump/CoreCollectorTest.java
@@ -143,6 +143,7 @@ public class CoreCollectorTest {
String.join("\n", GDB_BACKTRACE));
var expected = new CoreDumpMetadata().setBinPath(TEST_BIN_PATH)
+ .setType(CoreDumpMetadata.Type.CORE_DUMP)
.setBacktrace(GDB_BACKTRACE)
.setBacktraceAllThreads(GDB_BACKTRACE);
assertEquals(expected, coreCollector.collect(context, TEST_CORE_PATH));
@@ -156,7 +157,7 @@ public class CoreCollectorTest {
mockExec(new String[]{GDB_PATH_RHEL8 + " -n -ex set print frame-arguments none -ex bt -batch /usr/bin/program /tmp/core.1234"},
"", "Failure");
- var expected = new CoreDumpMetadata().setBinPath(TEST_BIN_PATH);
+ var expected = new CoreDumpMetadata().setBinPath(TEST_BIN_PATH).setType(CoreDumpMetadata.Type.CORE_DUMP);
assertEquals(expected, coreCollector.collect(context, TEST_CORE_PATH));
}
@@ -174,6 +175,7 @@ public class CoreCollectorTest {
jstack);
var expected = new CoreDumpMetadata().setBinPath(jdkPath)
+ .setType(CoreDumpMetadata.Type.CORE_DUMP)
.setBacktraceAllThreads(List.of(jstack));
assertEquals(expected, coreCollector.collect(context, TEST_CORE_PATH));
}
@@ -181,6 +183,7 @@ public class CoreCollectorTest {
@Test
void metadata_for_java_heap_dump() {
var expected = new CoreDumpMetadata().setBinPath("java")
+ .setType(CoreDumpMetadata.Type.JVM_HEAP)
.setBacktrace(List.of("Heap dump, no backtrace available"));
assertEquals(expected, coreCollector.collect(context, context.paths().of("/dump_java_pid123.hprof")));
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
index 4c9fab748d1..856d6e07156 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java
@@ -59,7 +59,7 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer {
failures++;
}
}
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
/**
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DiskReplacer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DiskReplacer.java
index acd5cb61d81..6f2eb726e91 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DiskReplacer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/DiskReplacer.java
@@ -51,6 +51,6 @@ public class DiskReplacer extends NodeRepositoryMaintainer {
log.log(Level.WARNING, "Failed to rebuild " + host.hostname() + ", will retry in " + interval(), e);
}
}
- return this.asSuccessFactor(nodes.size(), failures);
+ return this.asSuccessFactorDeviation(nodes.size(), failures);
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java
index 83dadddf76c..a4bc3a1aea5 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostCapacityMaintainer.java
@@ -113,7 +113,7 @@ public class HostCapacityMaintainer extends NodeRepositoryMaintainer {
}
success++;
}
- return asSuccessFactor(attempts, attempts - success);
+ return asSuccessFactorDeviation(attempts, attempts - success);
}
/**
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostDeprovisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostDeprovisioner.java
index 7ecfc8f7926..0fa16f22061 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostDeprovisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostDeprovisioner.java
@@ -53,7 +53,7 @@ public class HostDeprovisioner extends NodeRepositoryMaintainer {
log.log(Level.WARNING, "Failed to deprovision " + host.hostname() + ", will retry in " + interval(), e);
}
}
- return asSuccessFactor(hosts.size(), failures);
+ return asSuccessFactorDeviation(hosts.size(), failures);
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostResumeProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostResumeProvisioner.java
index 86c5a926900..3c77725298d 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostResumeProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostResumeProvisioner.java
@@ -63,7 +63,7 @@ public class HostResumeProvisioner extends NodeRepositoryMaintainer {
}
}
}
- return asSuccessFactor(hosts.size(), failures);
+ return asSuccessFactorDeviation(hosts.size(), failures);
}
private void setIpConfig(Node host, NodeList children, HostIpConfig hostIpConfig) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java
index f864ab18920..baa2e596b36 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/LoadBalancerExpirer.java
@@ -94,7 +94,7 @@ public class LoadBalancerExpirer extends NodeRepositoryMaintainer {
.collect(Collectors.joining(", ")),
interval()));
}
- return asSuccessFactor(attempts.get(), failed.size());
+ return asSuccessFactorDeviation(attempts.get(), failed.size());
}
/** Remove reals from inactive load balancers */
@@ -131,7 +131,7 @@ public class LoadBalancerExpirer extends NodeRepositoryMaintainer {
interval()),
lastException.get());
}
- return asSuccessFactor(attempts.get(), failed.size());
+ return asSuccessFactorDeviation(attempts.get(), failed.size());
}
/** Patch load balancers matching given filter, while holding lock */
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java
index afea08711fa..f9ff2f08375 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailer.java
@@ -97,7 +97,7 @@ public class NodeFailer extends NodeRepositoryMaintainer {
metric.set(throttlingActiveMetric, throttlingActive, null);
metric.set(throttledHostFailuresMetric, throttledHostFailures, null);
metric.set(throttledNodeFailuresMetric, throttledNodeFailures, null);
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
private Collection<FailingNode> findActiveFailingNodes() {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java
index 781debe26a0..979a2771082 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java
@@ -77,7 +77,7 @@ public class NodeHealthTracker extends NodeRepositoryMaintainer {
failures.add(1);
}
});
- return asSuccessFactor(attempts.get(), failures.get());
+ return asSuccessFactorDeviation(attempts.get(), failures.get());
}
/**
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainer.java
index b299369db1a..e28dac1c915 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainer.java
@@ -55,10 +55,10 @@ public class NodeMetricsDbMaintainer extends NodeRepositoryMaintainer {
nodeRepository().metricsDb().gc();
- return asSuccessFactor(attempts, failures.get());
+ return asSuccessFactorDeviation(attempts, failures.get());
}
catch (InterruptedException e) {
- return asSuccessFactor(attempts, failures.get());
+ return asSuccessFactorDeviation(attempts, failures.get());
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintainer.java
index 3c00e3b708d..b8d37c7eb5c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintainer.java
@@ -59,7 +59,7 @@ public abstract class NodeRepositoryMaintainer extends Maintainer {
@Override
public void completed(String job, double successFactor, long duration) {
var context = metric.createContext(Map.of("job", job));
- metric.set("maintenance.successFactor", successFactor, context);
+ metric.set("maintenance.successFactorDeviation", successFactor, context);
metric.set("maintenance.duration", duration, context);
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java
index af368934188..4071559d841 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java
@@ -48,7 +48,7 @@ public class ScalingSuggestionsMaintainer extends NodeRepositoryMaintainer {
failures++;
}
}
- return asSuccessFactor(attempts, failures);
+ return asSuccessFactorDeviation(attempts, failures);
}
private Applications applications() {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java
index 04f64b070b3..890d190c24e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java
@@ -109,7 +109,7 @@ public class LoadBalancerProvisioner {
public void activate(Set<ClusterSpec> clusters, NodeList newActive, ApplicationTransaction transaction) {
Map<ClusterSpec.Id, ZoneEndpoint> activatingClusters = clusters.stream()
// .collect(Collectors.toMap(ClusterSpec::id, ClusterSpec::zoneEndpoint));
- // TODO: this dies with combined clusters Ü
+ // TODO: this dies with combined clusters
.collect(groupingBy(LoadBalancerProvisioner::effectiveId,
reducing(ZoneEndpoint.defaultEndpoint,
ClusterSpec::zoneEndpoint,
@@ -193,14 +193,13 @@ public class LoadBalancerProvisioner {
Optional<LoadBalancer> loadBalancer = db.readLoadBalancer(id);
LoadBalancer newLoadBalancer;
LoadBalancer.State fromState = loadBalancer.map(LoadBalancer::state).orElse(null);
- if ( loadBalancer.isPresent()
- && ( ! inAccount(cloudAccount, loadBalancer.get())
- || ! hasCorrectVisibility(loadBalancer.get(), zoneEndpoint))) {
- // We have a load balancer, but with the wrong account or visibility.
- // Load balancer must be removed before we can provision a new one with the wanted visibility
- newLoadBalancer = loadBalancer.get().with(LoadBalancer.State.removable, now);
- }
- else {
+ boolean recreateLoadBalancer = loadBalancer.isPresent() && (!inAccount(cloudAccount, loadBalancer.get())
+ || !hasCorrectVisibility(loadBalancer.get(), zoneEndpoint));
+ if (recreateLoadBalancer) {
+ // We have a load balancer, but with the wrong account or visibility.
+ // Load balancer must be removed before we can provision a new one with the wanted visibility
+ newLoadBalancer = loadBalancer.get().with(LoadBalancer.State.removable, now);
+ } else {
Optional<LoadBalancerInstance> instance = provisionInstance(id, loadBalancer, zoneEndpoint, cloudAccount);
newLoadBalancer = loadBalancer.isEmpty() ? new LoadBalancer(id, instance, LoadBalancer.State.reserved, now)
: loadBalancer.get().with(instance);
@@ -211,8 +210,8 @@ public class LoadBalancerProvisioner {
}
private static boolean hasCorrectVisibility(LoadBalancer newLoadBalancer, ZoneEndpoint zoneEndpoint) {
- return newLoadBalancer.instance().isEmpty()
- || newLoadBalancer.instance().get().settings().isPublicEndpoint() == zoneEndpoint.isPublicEndpoint();
+ return newLoadBalancer.instance().isEmpty() ||
+ newLoadBalancer.instance().get().settings().isPublicEndpoint() == zoneEndpoint.isPublicEndpoint();
}
private void activate(ApplicationTransaction transaction, ClusterSpec.Id cluster, ZoneEndpoint settings, NodeList nodes) {
@@ -320,14 +319,6 @@ public class LoadBalancerProvisioner {
return loadBalancer.instance().isEmpty() || loadBalancer.instance().get().cloudAccount().equals(cloudAccount);
}
- /** Returns whether load balancer has given reals, and settings if specified */
- private static boolean isUpToDate(LoadBalancer loadBalancer, Set<Real> reals, ZoneEndpoint zoneEndpoint) {
- if (loadBalancer.instance().isEmpty())
- throw new IllegalStateException("Expected a load balancer instance to be present, for " + loadBalancer.id());
- return loadBalancer.instance().get().reals().equals(reals)
- && loadBalancer.instance().get().settings().equals(zoneEndpoint);
- }
-
/** Find IP addresses reachable by the load balancer service */
private Set<String> reachableIpAddresses(Node node) {
Set<String> reachable = new LinkedHashSet<>(node.ipConfig().primary());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainerTest.java
index c7c6e770fe3..611594cc72e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeMetricsDbMaintainerTest.java
@@ -44,7 +44,7 @@ public class NodeMetricsDbMaintainerTest {
fetcher,
Duration.ofHours(1),
new TestMetric());
- assertEquals(maintainer.maintain(), 1.0, 0.0000001);
+ assertEquals(maintainer.maintain(), 0.0, 0.0000001);
List<NodeTimeseries> timeseriesList = tester.nodeRepository().metricsDb().getNodeTimeseries(Duration.ofDays(1),
Set.of("host-1.yahoo.com", "host-2.yahoo.com"));
assertEquals(2, timeseriesList.size());
diff --git a/searchcore/src/tests/proton/common/attribute_updater/attribute_updater_test.cpp b/searchcore/src/tests/proton/common/attribute_updater/attribute_updater_test.cpp
index 392dcc256c8..892be2c874f 100644
--- a/searchcore/src/tests/proton/common/attribute_updater/attribute_updater_test.cpp
+++ b/searchcore/src/tests/proton/common/attribute_updater/attribute_updater_test.cpp
@@ -264,7 +264,8 @@ TEST_F("require that array attributes are updated", Fixture)
{
CollectionType ct(CollectionType::ARRAY);
{
- auto vec = AttributeBuilder("in1/aint", Config(BasicType::INT32, ct)).fill_array({{32}, {32}, {32}, {32}, {32}}).get();
+ using IL = AttributeBuilder::IntList;
+ auto vec = AttributeBuilder("in1/aint", Config(BasicType::INT32, ct)).fill_array({IL{32}, {32}, {32}, {32}, {32}}).get();
auto first = std::make_unique<IntFieldValue>(32);
auto second = std::make_unique<IntFieldValue>(64);
auto assign = std::make_unique<ArrayFieldValue>(f.docType->getField("aint").getDataType());
@@ -279,7 +280,8 @@ TEST_F("require that array attributes are updated", Fixture)
EXPECT_TRUE(check(vec, 5, std::vector<WeightedInt>{WeightedInt(32)}));
}
{
- auto vec = AttributeBuilder("in1/afloat", Config(BasicType::FLOAT, ct)).fill_array({{55.5}, {55.5}, {55.5}, {55.5}, {55.5}}).get();
+ using DL = AttributeBuilder::DoubleList;
+ auto vec = AttributeBuilder("in1/afloat", Config(BasicType::FLOAT, ct)).fill_array({DL{55.5}, {55.5}, {55.5}, {55.5}, {55.5}}).get();
auto first = std::make_unique<FloatFieldValue>(55.5f);
auto second = std::make_unique<FloatFieldValue>(77.7f);
auto assign = std::make_unique<ArrayFieldValue>(f.docType->getField("afloat").getDataType());
diff --git a/searchlib/src/tests/attribute/attribute_test.cpp b/searchlib/src/tests/attribute/attribute_test.cpp
index 7eb43faac18..d2d3ccaad23 100644
--- a/searchlib/src/tests/attribute/attribute_test.cpp
+++ b/searchlib/src/tests/attribute/attribute_test.cpp
@@ -912,8 +912,8 @@ AttributeTest::testSingle()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("sv-post-int32", cfg);
ptr->updateStat(true);
- EXPECT_EQ(339020u, ptr->getStatus().getAllocated());
- EXPECT_EQ(101852u, ptr->getStatus().getUsed());
+ EXPECT_EQ(338972u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(101492u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<IntegerAttribute, AttributeVector::largeint_t, int32_t>(ptr, values);
}
@@ -934,8 +934,8 @@ AttributeTest::testSingle()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("sv-post-float", cfg);
ptr->updateStat(true);
- EXPECT_EQ(339020, ptr->getStatus().getAllocated());
- EXPECT_EQ(101852u, ptr->getStatus().getUsed());
+ EXPECT_EQ(338972u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(101492u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<FloatingPointAttribute, double, float>(ptr, values);
}
@@ -947,8 +947,8 @@ AttributeTest::testSingle()
{
AttributePtr ptr = createAttribute("sv-string", Config(BasicType::STRING, CollectionType::SINGLE));
ptr->updateStat(true);
- EXPECT_EQ(117256u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(53240u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(116528u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(52760u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<StringAttribute, string, string>(ptr, values);
}
@@ -957,8 +957,8 @@ AttributeTest::testSingle()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("sv-fs-string", cfg);
ptr->updateStat(true);
- EXPECT_EQ(345624u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(105176u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(344848u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(104408u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testSingle<StringAttribute, string, string>(ptr, values);
}
@@ -1089,8 +1089,8 @@ AttributeTest::testArray()
{
AttributePtr ptr = createAttribute("a-int32", Config(BasicType::INT32, CollectionType::ARRAY));
ptr->updateStat(true);
- EXPECT_EQ(512056u, ptr->getStatus().getAllocated());
- EXPECT_EQ(504392u, ptr->getStatus().getUsed());
+ EXPECT_EQ(487480u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(479720u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values);
}
@@ -1099,8 +1099,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("flags", cfg);
ptr->updateStat(true);
- EXPECT_EQ(512056u, ptr->getStatus().getAllocated());
- EXPECT_EQ(504392u, ptr->getStatus().getUsed());
+ EXPECT_EQ(487480u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(479720u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values);
}
@@ -1109,8 +1109,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("a-fs-int32", cfg);
ptr->updateStat(true);
- EXPECT_EQ(868788u, ptr->getStatus().getAllocated());
- EXPECT_EQ(606264u, ptr->getStatus().getUsed());
+ EXPECT_EQ(844116u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(581232u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values);
}
@@ -1128,8 +1128,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("a-fs-float", cfg);
ptr->updateStat(true);
- EXPECT_EQ(868788u, ptr->getStatus().getAllocated());
- EXPECT_EQ(606264u, ptr->getStatus().getUsed());
+ EXPECT_EQ(844116u, ptr->getStatus().getAllocated());
+ EXPECT_EQ(581232u, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<FloatingPointAttribute, double>(ptr, values);
}
@@ -1140,8 +1140,8 @@ AttributeTest::testArray()
{
AttributePtr ptr = createAttribute("a-string", Config(BasicType::STRING, CollectionType::ARRAY));
ptr->updateStat(true);
- EXPECT_EQ(625088u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(557632u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(599784u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(532480u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<StringAttribute, string>(ptr, values);
}
@@ -1150,8 +1150,8 @@ AttributeTest::testArray()
cfg.setFastSearch(true);
AttributePtr ptr = createAttribute("afs-string", cfg);
ptr->updateStat(true);
- EXPECT_EQ(875392u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
- EXPECT_EQ(609588u + sizeof_large_string_entry, ptr->getStatus().getUsed());
+ EXPECT_EQ(849992u + sizeof_large_string_entry, ptr->getStatus().getAllocated());
+ EXPECT_EQ(584148u + sizeof_large_string_entry, ptr->getStatus().getUsed());
addDocs(ptr, numDocs);
testArray<StringAttribute, string>(ptr, values);
}
@@ -2334,6 +2334,10 @@ AttributeTest::test_paged_attribute(const vespalib::string& name, const vespalib
size_t rounded_size = vespalib::round_up_to_page_size(1);
size_t lid_mapping_size = 1200;
size_t sv_maxlid = 1200;
+ if (rounded_size == 16_Ki) {
+ lid_mapping_size = 4200;
+ sv_maxlid = 1300;
+ }
if (rounded_size == 64_Ki) {
lid_mapping_size = 17000;
sv_maxlid = 1500;
diff --git a/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp b/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp
index 8f056323733..3f775e99891 100644
--- a/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp
+++ b/searchlib/src/tests/attribute/extendattributes/extendattribute.cpp
@@ -1,9 +1,25 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/gtest/gtest.h>
+#include <vespa/eval/eval/fast_value.h>
+#include <vespa/eval/eval/tensor_spec.h>
+#include <vespa/eval/eval/value.h>
+#include <vespa/eval/eval/value_codec.h>
+#include <vespa/searchcommon/attribute/config.h>
#include <vespa/searchlib/attribute/extendableattributes.h>
#include <vespa/searchlib/attribute/single_raw_ext_attribute.h>
+#include <vespa/searchlib/tensor/tensor_ext_attribute.h>
+#include <vespa/searchlib/tensor/vector_bundle.h>
+#include <vespa/vespalib/stllike/asciistream.h>
+using search::attribute::Config;
+using search::attribute::BasicType;
+using search::attribute::CollectionType;
using search::attribute::SingleRawExtAttribute;
+using search::tensor::TensorExtAttribute;
+using vespalib::eval::FastValueBuilderFactory;
+using vespalib::eval::TensorSpec;
+using vespalib::eval::Value;
+using vespalib::eval::ValueType;
namespace search {
@@ -15,8 +31,46 @@ std::vector<char> as_vector(vespalib::ConstArrayRef<char> value) {
return {value.data(), value.data() + value.size()};
}
+std::vector<double> as_vector(vespalib::ConstArrayRef<double> value) {
+ return {value.data(), value.data() + value.size()};
+}
+
+vespalib::string vec_2d_spec("tensor(x[2])");
+vespalib::string vec_mixed_2d_spec("tensor(a{},x[2])");
+
+TensorSpec
+vec_2d(double x0, double x1)
+{
+ return TensorSpec(vec_2d_spec).add({{"x", 0}}, x0).add({{"x", 1}}, x1);
+}
+
+TensorSpec
+vec_mixed_2d(std::vector<std::vector<double>> val)
+{
+ TensorSpec spec(vec_mixed_2d_spec);
+ for (uint32_t a = 0; a < val.size(); ++a) {
+ vespalib::asciistream a_stream;
+ a_stream << a;
+ vespalib::string a_as_string = a_stream.str();
+ for (uint32_t x = 0; x < val[a].size(); ++x) {
+ spec.add({{"a", a_as_string.c_str()},{"x", x}}, val[a][x]);
+ }
+ }
+ return spec;
+}
+
+void add_doc(AttributeVector& attr, uint32_t exp_docid)
+{
+ uint32_t docid(0);
+ EXPECT_EQ(exp_docid, attr.getNumDocs());
+ attr.addDoc(docid);
+ EXPECT_EQ(exp_docid, docid);
+ EXPECT_EQ(exp_docid + 1, attr.getNumDocs());
+}
+
class ExtendAttributeTest : public ::testing::Test
{
+ std::vector<std::unique_ptr<Value>> _tensors;
protected:
ExtendAttributeTest() = default;
~ExtendAttributeTest() override = default;
@@ -27,16 +81,22 @@ protected:
template <typename Attribute>
void testExtendString(Attribute & attr);
void testExtendRaw(AttributeVector& attr);
+ void testExtendTensor(AttributeVector& attr);
+ const Value& create_tensor(const TensorSpec &spec);
};
+const Value&
+ExtendAttributeTest::create_tensor(const TensorSpec &spec)
+{
+ auto value = value_from_spec(spec, FastValueBuilderFactory::get());
+ _tensors.emplace_back(std::move(value));
+ return *_tensors.back();
+}
+
template <typename Attribute>
void ExtendAttributeTest::testExtendInteger(Attribute & attr)
{
- uint32_t docId(0);
- EXPECT_EQ(attr.getNumDocs(), 0u);
- attr.addDoc(docId);
- EXPECT_EQ(docId, 0u);
- EXPECT_EQ(attr.getNumDocs(), 1u);
+ add_doc(attr, 0);
attr.add(1, 10);
EXPECT_EQ(attr.getInt(0), 1);
attr.add(2, 20);
@@ -51,9 +111,7 @@ void ExtendAttributeTest::testExtendInteger(Attribute & attr)
EXPECT_EQ(v[1].getWeight(), 20);
}
}
- attr.addDoc(docId);
- EXPECT_EQ(docId, 1u);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
attr.add(3, 30);
EXPECT_EQ(attr.getInt(1), 3);
if (attr.hasMultiValue()) {
@@ -69,11 +127,7 @@ void ExtendAttributeTest::testExtendInteger(Attribute & attr)
template <typename Attribute>
void ExtendAttributeTest::testExtendFloat(Attribute & attr)
{
- uint32_t docId(0);
- EXPECT_EQ(attr.getNumDocs(), 0u);
- attr.addDoc(docId);
- EXPECT_EQ(docId, 0u);
- EXPECT_EQ(attr.getNumDocs(), 1u);
+ add_doc(attr, 0);
attr.add(1.7, 10);
EXPECT_EQ(attr.getInt(0), 1);
EXPECT_EQ(attr.getFloat(0), 1.7);
@@ -89,9 +143,7 @@ void ExtendAttributeTest::testExtendFloat(Attribute & attr)
EXPECT_EQ(v[1].getWeight(), 20);
}
}
- attr.addDoc(docId);
- EXPECT_EQ(docId, 1u);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
attr.add(3.6, 30);
EXPECT_EQ(attr.getFloat(1), 3.6);
if (attr.hasMultiValue()) {
@@ -107,11 +159,7 @@ void ExtendAttributeTest::testExtendFloat(Attribute & attr)
template <typename Attribute>
void ExtendAttributeTest::testExtendString(Attribute & attr)
{
- uint32_t docId(0);
- EXPECT_EQ(attr.getNumDocs(), 0u);
- attr.addDoc(docId);
- EXPECT_EQ(docId, 0u);
- EXPECT_EQ(attr.getNumDocs(), 1u);
+ add_doc(attr, 0);
attr.add("1.7", 10);
auto buf = attr.get_raw(0);
EXPECT_EQ(std::string(buf.data(), buf.size()), "1.7");
@@ -128,9 +176,7 @@ void ExtendAttributeTest::testExtendString(Attribute & attr)
EXPECT_EQ(v[1].getWeight(), 20);
}
}
- attr.addDoc(docId);
- EXPECT_EQ(docId, 1u);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
attr.add("3.6", 30);
buf = attr.get_raw(1);
EXPECT_EQ(std::string(buf.data(), buf.size()), "3.6");
@@ -150,41 +196,77 @@ void ExtendAttributeTest::testExtendRaw(AttributeVector& attr)
std::vector<char> zeros{10, 0, 0, 11};
auto* ext_attr = attr.getExtendInterface();
EXPECT_NE(nullptr, ext_attr);
- uint32_t docId(0);
- EXPECT_EQ(0u, attr.getNumDocs());
- attr.addDoc(docId);
- EXPECT_EQ(0u, docId);
- EXPECT_EQ(1u, attr.getNumDocs());
+ add_doc(attr, 0);
ext_attr->add(as_vector("1.7"));
auto buf = attr.get_raw(0);
EXPECT_EQ(as_vector("1.7"), as_vector(buf));
ext_attr->add(vespalib::ConstArrayRef<char>(as_vector("2.3")));
buf = attr.get_raw(0);
EXPECT_EQ(as_vector("2.3"), as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(1u, docId);
- EXPECT_EQ(attr.getNumDocs(), 2u);
+ add_doc(attr, 1);
ext_attr->add(as_vector("3.6"));
buf = attr.get_raw(1);
EXPECT_EQ(as_vector("3.6"), as_vector(buf));
buf = attr.get_raw(0);
EXPECT_EQ(as_vector("2.3"), as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(2u, docId);
+ add_doc(attr, 2);
ext_attr->add(zeros);
buf = attr.get_raw(2);
EXPECT_EQ(zeros, as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(3u, docId);
+ add_doc(attr, 3);
buf = attr.get_raw(3);
EXPECT_EQ(empty, as_vector(buf));
- attr.addDoc(docId);
- EXPECT_EQ(4u, docId);
+ add_doc(attr, 4);
ext_attr->add(empty);
buf = attr.get_raw(4);
EXPECT_EQ(empty, as_vector(buf));
}
+void ExtendAttributeTest::testExtendTensor(AttributeVector& attr)
+{
+ std::vector<double> empty_cells{0.0, 0.0};
+ std::vector<double> spec0_dense_cells{1.0, 2.0};
+ std::vector<double> spec0_mixed_cells0{3.0, 4.0};
+ std::vector<double> spec0_mixed_cells1{5.0, 6.0};
+ bool dense = attr.getConfig().tensorType().is_dense();
+ auto* ext_attr = attr.getExtendInterface();
+ EXPECT_NE(nullptr, ext_attr);
+ auto* tensor_attr = attr.asTensorAttribute();
+ EXPECT_NE(nullptr, tensor_attr);
+ add_doc(attr, 0);
+ TensorSpec spec0 = dense ? vec_2d(1.0, 2.0) : vec_mixed_2d({{3.0, 4.0}, {5.0, 6.0}});
+ EXPECT_TRUE(ext_attr->add(create_tensor(spec0)));
+ auto tensor = tensor_attr->getTensor(0);
+ EXPECT_NE(nullptr, tensor.get());
+ EXPECT_EQ(spec0, TensorSpec::from_value(*tensor));
+ EXPECT_EQ(dense, tensor_attr->supports_extract_cells_ref());
+ if (dense) {
+ EXPECT_EQ(spec0_dense_cells, as_vector(tensor_attr->extract_cells_ref(0).typify<double>()));
+ }
+ EXPECT_TRUE(tensor_attr->supports_get_tensor_ref());
+ EXPECT_EQ(spec0, TensorSpec::from_value(tensor_attr->get_tensor_ref(0)));
+ EXPECT_FALSE(tensor_attr->supports_get_serialized_tensor_ref());
+ auto vectors = tensor_attr->get_vectors(0);
+ if (dense) {
+ EXPECT_EQ(1, vectors.subspaces());
+ EXPECT_EQ(spec0_dense_cells, as_vector(vectors.cells(0).typify<double>()));
+ EXPECT_EQ(spec0_dense_cells, as_vector(tensor_attr->get_vector(0, 0).typify<double>()));
+ EXPECT_EQ(empty_cells, as_vector(tensor_attr->get_vector(0, 1).typify<double>()));
+ } else {
+ EXPECT_EQ(2, vectors.subspaces());
+ EXPECT_EQ(spec0_mixed_cells0, as_vector(vectors.cells(0).typify<double>()));
+ EXPECT_EQ(spec0_mixed_cells1, as_vector(vectors.cells(1).typify<double>()));
+ EXPECT_EQ(spec0_mixed_cells0, as_vector(tensor_attr->get_vector(0, 0).typify<double>()));
+ EXPECT_EQ(spec0_mixed_cells1, as_vector(tensor_attr->get_vector(0, 1).typify<double>()));
+ EXPECT_EQ(empty_cells, as_vector(tensor_attr->get_vector(0, 2).typify<double>()));
+ }
+ add_doc(attr, 1);
+ vectors = tensor_attr->get_vectors(1);
+ EXPECT_EQ(0, vectors.subspaces());
+ EXPECT_EQ(empty_cells, as_vector(tensor_attr->get_vector(1, 0).typify<double>()));
+ EXPECT_EQ(nullptr, tensor_attr->getTensor(1).get());
+}
+
TEST_F(ExtendAttributeTest, single_integer_ext_attribute)
{
SingleIntegerExtAttribute siattr("si1");
@@ -255,6 +337,24 @@ TEST_F(ExtendAttributeTest, single_raw_ext_attribute)
testExtendRaw(srattr);
}
+TEST_F(ExtendAttributeTest, tensor_ext_attribute_dense)
+{
+ Config cfg(BasicType::TENSOR, CollectionType::SINGLE);
+ cfg.setTensorType(ValueType::from_spec(vec_2d_spec));
+ TensorExtAttribute tattr("td1", cfg);
+ EXPECT_TRUE(! tattr.hasMultiValue());
+ testExtendTensor(tattr);
+}
+
+TEST_F(ExtendAttributeTest, tensor_ext_attribute_mixed)
+{
+ Config cfg(BasicType::TENSOR, CollectionType::SINGLE);
+ cfg.setTensorType(ValueType::from_spec(vec_mixed_2d_spec));
+ TensorExtAttribute tattr("tm1", cfg);
+ EXPECT_TRUE(! tattr.hasMultiValue());
+ testExtendTensor(tattr);
+}
+
}
GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp b/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp
index df2a5ea2ac9..17e852c8b92 100644
--- a/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp
+++ b/searchlib/src/tests/attribute/multi_value_mapping/multi_value_mapping_test.cpp
@@ -22,11 +22,11 @@ using vespalib::datastore::CompactionStrategy;
using vespalib::alloc::test::MemoryAllocatorObserver;
using AllocStats = MemoryAllocatorObserver::Stats;
-template <typename EntryT>
+template <typename ElemT>
void
-assertArray(const std::vector<EntryT> &exp, vespalib::ConstArrayRef<EntryT> values)
+assertArray(const std::vector<ElemT> &exp, vespalib::ConstArrayRef<ElemT> values)
{
- EXPECT_EQ(exp, std::vector<EntryT>(values.cbegin(), values.cend()));
+ EXPECT_EQ(exp, std::vector<ElemT>(values.cbegin(), values.cend()));
}
template <class MvMapping>
@@ -69,10 +69,10 @@ public:
constexpr float ALLOC_GROW_FACTOR = 0.2;
-template <typename EntryT>
+template <typename ElemT>
class MappingTestBase : public ::testing::Test {
protected:
- using MvMapping = search::attribute::MultiValueMapping<EntryT>;
+ using MvMapping = search::attribute::MultiValueMapping<ElemT>;
using AttributeType = MyAttribute<MvMapping>;
AllocStats _stats;
std::unique_ptr<MvMapping> _mvMapping;
@@ -82,8 +82,8 @@ protected:
using generation_t = vespalib::GenerationHandler::generation_t;
public:
- using ArrayRef = vespalib::ArrayRef<EntryT>;
- using ConstArrayRef = vespalib::ConstArrayRef<EntryT>;
+ using ArrayRef = vespalib::ArrayRef<ElemT>;
+ using ConstArrayRef = vespalib::ConstArrayRef<ElemT>;
MappingTestBase()
: _stats(),
_mvMapping(),
@@ -99,9 +99,9 @@ public:
_attr = std::make_unique<AttributeType>(*_mvMapping);
_maxSmallArraySize = maxSmallArraySize;
}
- void setup(uint32_t maxSmallArraySize, size_t minArrays, size_t maxArrays, size_t numArraysForNewBuffer, bool enable_free_lists = true) {
+ void setup(uint32_t maxSmallArraySize, size_t min_entries, size_t max_entries, size_t num_entries_for_new_buffer, bool enable_free_lists = true) {
ArrayStoreConfig config(maxSmallArraySize,
- ArrayStoreConfig::AllocSpec(minArrays, maxArrays, numArraysForNewBuffer, ALLOC_GROW_FACTOR));
+ ArrayStoreConfig::AllocSpec(min_entries, max_entries, num_entries_for_new_buffer, ALLOC_GROW_FACTOR));
config.enable_free_lists(enable_free_lists);
_mvMapping = std::make_unique<MvMapping>(config, vespalib::GrowStrategy(), std::make_unique<MemoryAllocatorObserver>(_stats));
_attr = std::make_unique<AttributeType>(*_mvMapping);
@@ -109,12 +109,12 @@ public:
}
~MappingTestBase() { }
- void set(uint32_t docId, const std::vector<EntryT> &values) { _mvMapping->set(docId, values); }
+ void set(uint32_t docId, const std::vector<ElemT> &values) { _mvMapping->set(docId, values); }
ConstArrayRef get(uint32_t docId) { return _mvMapping->get(docId); }
ArrayRef get_writable(uint32_t docId) { return _mvMapping->get_writable(docId); }
- void assertGet(uint32_t docId, const std::vector<EntryT> &exp) {
+ void assertGet(uint32_t docId, const std::vector<ElemT> &exp) {
ConstArrayRef act = get(docId);
- EXPECT_EQ(exp, std::vector<EntryT>(act.cbegin(), act.cend()));
+ EXPECT_EQ(exp, std::vector<ElemT>(act.cbegin(), act.cend()));
}
void assign_generation(generation_t current_gen) { _mvMapping->assign_generation(current_gen); }
void reclaim_memory(generation_t oldest_used_gen) { _mvMapping->reclaim_memory(oldest_used_gen); }
diff --git a/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp b/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp
index b57a2f42ea7..69478c09a25 100644
--- a/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp
+++ b/searchlib/src/tests/memoryindex/field_index/field_index_test.cpp
@@ -1032,14 +1032,14 @@ TEST_F(BasicInverterTest, require_that_inversion_is_working)
auto beforeStats = getFeatureStoreMemStats(_fic);
LOG(info,
- "Before feature compaction: allocElems=%zu, usedElems=%zu"
- ", deadElems=%zu, holdElems=%zu"
+ "Before feature compaction: alloc_entries=%zu, used_entries=%zu"
+ ", dead_entries=%zu, hold_entries=%zu"
", freeBuffers=%u, activeBuffers=%u"
", holdBuffers=%u",
- beforeStats._allocElems,
- beforeStats._usedElems,
- beforeStats._deadElems,
- beforeStats._holdElems,
+ beforeStats._alloc_entries,
+ beforeStats._used_entries,
+ beforeStats._dead_entries,
+ beforeStats._hold_entries,
beforeStats._freeBuffers,
beforeStats._activeBuffers,
beforeStats._holdBuffers);
@@ -1052,14 +1052,14 @@ TEST_F(BasicInverterTest, require_that_inversion_is_working)
myCommit(_fic, *_pushThreads);
auto duringStats = getFeatureStoreMemStats(_fic);
LOG(info,
- "During feature compaction: allocElems=%zu, usedElems=%zu"
- ", deadElems=%zu, holdElems=%zu"
+ "During feature compaction: alloc_entries=%zu, used_entries=%zu"
+ ", dead_entries=%zu, hold_entries=%zu"
", freeBuffers=%u, activeBuffers=%u"
", holdBuffers=%u",
- duringStats._allocElems,
- duringStats._usedElems,
- duringStats._deadElems,
- duringStats._holdElems,
+ duringStats._alloc_entries,
+ duringStats._used_entries,
+ duringStats._dead_entries,
+ duringStats._hold_entries,
duringStats._freeBuffers,
duringStats._activeBuffers,
duringStats._holdBuffers);
@@ -1067,14 +1067,14 @@ TEST_F(BasicInverterTest, require_that_inversion_is_working)
myCommit(_fic, *_pushThreads);
auto afterStats = getFeatureStoreMemStats(_fic);
LOG(info,
- "After feature compaction: allocElems=%zu, usedElems=%zu"
- ", deadElems=%zu, holdElems=%zu"
+ "After feature compaction: alloc_entries=%zu, used_entries=%zu"
+ ", dead_entries=%zu, hold_entries=%zu"
", freeBuffers=%u, activeBuffers=%u"
", holdBuffers=%u",
- afterStats._allocElems,
- afterStats._usedElems,
- afterStats._deadElems,
- afterStats._holdElems,
+ afterStats._alloc_entries,
+ afterStats._used_entries,
+ afterStats._dead_entries,
+ afterStats._hold_entries,
afterStats._freeBuffers,
afterStats._activeBuffers,
afterStats._holdBuffers);
diff --git a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
index 8073fb8d232..e3b9cf9702d 100644
--- a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
+++ b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
@@ -462,8 +462,8 @@ TEST(MemoryIndexTest, require_that_num_docs_and_doc_id_limit_is_returned)
TEST(MemoryIndexTest, require_that_we_understand_the_memory_footprint)
{
- constexpr size_t BASE_ALLOCATED = 361032u;
- constexpr size_t BASE_USED = 151188u;
+ constexpr size_t BASE_ALLOCATED = 360936u;
+ constexpr size_t BASE_USED = 150804u;
{
MySetup setup;
Index index(setup);
diff --git a/searchlib/src/tests/predicate/document_features_store_test.cpp b/searchlib/src/tests/predicate/document_features_store_test.cpp
index 4ac4bdc32f0..d30df9dba6e 100644
--- a/searchlib/src/tests/predicate/document_features_store_test.cpp
+++ b/searchlib/src/tests/predicate/document_features_store_test.cpp
@@ -165,17 +165,17 @@ TEST("require that both features and ranges are removed by 'remove'") {
TEST("require that both features and ranges counts towards memory usage") {
DocumentFeaturesStore features_store(10);
- EXPECT_EQUAL(50136u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50064u, features_store.getMemoryUsage().usedBytes());
PredicateTreeAnnotations annotations;
annotations.features.push_back(PredicateHash::hash64("foo=100-199"));
features_store.insert(annotations, doc_id);
- EXPECT_EQUAL(50144u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50072u, features_store.getMemoryUsage().usedBytes());
annotations.features.clear();
annotations.range_features.push_back({"foo", 100, 199});
features_store.insert(annotations, doc_id + 1);
- EXPECT_EQUAL(50240u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50168u, features_store.getMemoryUsage().usedBytes());
}
TEST("require that DocumentFeaturesStore can be serialized") {
@@ -205,17 +205,17 @@ TEST("require that serialization cleans up wordstore") {
PredicateTreeAnnotations annotations;
annotations.range_features.push_back({"foo", 100, 199});
features_store.insert(annotations, doc_id);
- EXPECT_EQUAL(50232u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50160u, features_store.getMemoryUsage().usedBytes());
annotations.range_features.push_back({"bar", 100, 199});
features_store.insert(annotations, doc_id + 1);
- EXPECT_EQUAL(50620u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50548u, features_store.getMemoryUsage().usedBytes());
features_store.remove(doc_id + 1);
- EXPECT_EQUAL(50572u, features_store.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50500u, features_store.getMemoryUsage().usedBytes());
vespalib::DataBuffer buffer;
features_store.serialize(buffer);
DocumentFeaturesStore features_store2(buffer);
- EXPECT_EQUAL(50232u, features_store2.getMemoryUsage().usedBytes());
+ EXPECT_EQUAL(50160u, features_store2.getMemoryUsage().usedBytes());
}
diff --git a/searchlib/src/vespa/searchlib/attribute/attributevector.h b/searchlib/src/vespa/searchlib/attribute/attributevector.h
index 3d14622ca02..e40785911ea 100644
--- a/searchlib/src/vespa/searchlib/attribute/attributevector.h
+++ b/searchlib/src/vespa/searchlib/attribute/attributevector.h
@@ -38,6 +38,8 @@ namespace vespalib::alloc {
class Alloc;
}
+namespace vespalib::eval { struct Value; }
+
namespace search {
template <typename T> class ComponentGuard;
@@ -86,6 +88,7 @@ public:
virtual bool add(double, int32_t = 1) { return false; }
virtual bool add(const char *, int32_t = 1) { return false; }
virtual bool add(vespalib::ConstArrayRef<char>, int32_t = 1) { return false; }
+ virtual bool add(const vespalib::eval::Value&, int32_t = 1) { return false; }
virtual ~IExtendAttribute() = default;
};
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h
index bd624e9f388..4fce64aa762 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.h
@@ -12,18 +12,18 @@ namespace search::attribute {
/**
* Class for mapping from document id to an array of values.
*/
-template <typename EntryT, typename RefT = vespalib::datastore::EntryRefT<19> >
+template <typename ElemT, typename RefT = vespalib::datastore::EntryRefT<19> >
class MultiValueMapping : public MultiValueMappingBase
{
public:
- using MultiValueType = EntryT;
+ using MultiValueType = ElemT;
using RefType = RefT;
- using ReadView = MultiValueMappingReadView<EntryT, RefT>;
+ using ReadView = MultiValueMappingReadView<ElemT, RefT>;
private:
- using ArrayRef = vespalib::ArrayRef<EntryT>;
- using ArrayStore = vespalib::datastore::ArrayStore<EntryT, RefT>;
+ using ArrayRef = vespalib::ArrayRef<ElemT>;
+ using ArrayStore = vespalib::datastore::ArrayStore<ElemT, RefT>;
using generation_t = vespalib::GenerationHandler::generation_t;
- using ConstArrayRef = vespalib::ConstArrayRef<EntryT>;
+ using ConstArrayRef = vespalib::ConstArrayRef<ElemT>;
ArrayStore _store;
public:
@@ -73,7 +73,7 @@ public:
static vespalib::datastore::ArrayStoreConfig optimizedConfigForHugePage(size_t maxSmallArraySize,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor,
bool enable_free_lists);
};
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp
index b486fa60265..ab68bea58cc 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping.hpp
@@ -7,8 +7,8 @@
namespace search::attribute {
-template <typename EntryT, typename RefT>
-MultiValueMapping<EntryT,RefT>::MultiValueMapping(const vespalib::datastore::ArrayStoreConfig &storeCfg,
+template <typename ElemT, typename RefT>
+MultiValueMapping<ElemT,RefT>::MultiValueMapping(const vespalib::datastore::ArrayStoreConfig &storeCfg,
const vespalib::GrowStrategy &gs,
std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator)
: MultiValueMappingBase(gs, ArrayStore::getGenerationHolderLocation(_store), memory_allocator),
@@ -16,12 +16,12 @@ MultiValueMapping<EntryT,RefT>::MultiValueMapping(const vespalib::datastore::Arr
{
}
-template <typename EntryT, typename RefT>
-MultiValueMapping<EntryT,RefT>::~MultiValueMapping() = default;
+template <typename ElemT, typename RefT>
+MultiValueMapping<ElemT,RefT>::~MultiValueMapping() = default;
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
void
-MultiValueMapping<EntryT,RefT>::set(uint32_t docId, ConstArrayRef values)
+MultiValueMapping<ElemT,RefT>::set(uint32_t docId, ConstArrayRef values)
{
_indices.ensure_size(docId + 1);
EntryRef oldRef(_indices[docId].load_relaxed());
@@ -31,18 +31,18 @@ MultiValueMapping<EntryT,RefT>::set(uint32_t docId, ConstArrayRef values)
_store.remove(oldRef);
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::MemoryUsage
-MultiValueMapping<EntryT,RefT>::update_stat(const CompactionStrategy& compaction_strategy)
+MultiValueMapping<ElemT,RefT>::update_stat(const CompactionStrategy& compaction_strategy)
{
auto retval = _store.update_stat(compaction_strategy);
retval.merge(_indices.getMemoryUsage());
return retval;
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
void
-MultiValueMapping<EntryT,RefT>::compact_worst(const CompactionStrategy& compaction_strategy)
+MultiValueMapping<ElemT,RefT>::compact_worst(const CompactionStrategy& compaction_strategy)
{
vespalib::datastore::ICompactionContext::UP compactionContext(_store.compact_worst(compaction_strategy));
if (compactionContext) {
@@ -50,29 +50,29 @@ MultiValueMapping<EntryT,RefT>::compact_worst(const CompactionStrategy& compacti
}
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::MemoryUsage
-MultiValueMapping<EntryT,RefT>::getArrayStoreMemoryUsage() const
+MultiValueMapping<ElemT,RefT>::getArrayStoreMemoryUsage() const
{
return _store.getMemoryUsage();
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::AddressSpace
-MultiValueMapping<EntryT, RefT>::getAddressSpaceUsage() const {
+MultiValueMapping<ElemT, RefT>::getAddressSpaceUsage() const {
return _store.addressSpaceUsage();
}
-template <typename EntryT, typename RefT>
+template <typename ElemT, typename RefT>
vespalib::datastore::ArrayStoreConfig
-MultiValueMapping<EntryT, RefT>::optimizedConfigForHugePage(size_t maxSmallArraySize,
+MultiValueMapping<ElemT, RefT>::optimizedConfigForHugePage(size_t maxSmallArraySize,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor,
bool enable_free_lists)
{
- auto result = ArrayStore::optimizedConfigForHugePage(maxSmallArraySize, hugePageSize, smallPageSize, minNumArraysForNewBuffer, allocGrowFactor);
+ auto result = ArrayStore::optimizedConfigForHugePage(maxSmallArraySize, hugePageSize, smallPageSize, min_num_entries_for_new_buffer, allocGrowFactor);
result.enable_free_lists(enable_free_lists);
return result;
}
diff --git a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h
index 116e069e8b4..41138ff0890 100644
--- a/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h
+++ b/searchlib/src/vespa/searchlib/attribute/multi_value_mapping_read_view.h
@@ -11,12 +11,12 @@ namespace search::attribute {
/**
* Class for mapping from document id to an array of values as reader.
*/
-template <typename EntryT, typename RefT = vespalib::datastore::EntryRefT<19> >
+template <typename ElemT, typename RefT = vespalib::datastore::EntryRefT<19> >
class MultiValueMappingReadView
{
using AtomicEntryRef = vespalib::datastore::AtomicEntryRef;
using Indices = vespalib::ConstArrayRef<AtomicEntryRef>;
- using ArrayStore = vespalib::datastore::ArrayStore<EntryT, RefT>;
+ using ArrayStore = vespalib::datastore::ArrayStore<ElemT, RefT>;
Indices _indices;
const ArrayStore* _store;
@@ -31,7 +31,7 @@ public:
_store(store)
{
}
- vespalib::ConstArrayRef<EntryT> get(uint32_t doc_id) const { return _store->get(_indices[doc_id].load_acquire()); }
+ vespalib::ConstArrayRef<ElemT> get(uint32_t doc_id) const { return _store->get(_indices[doc_id].load_acquire()); }
bool valid() const noexcept { return _store != nullptr; }
};
diff --git a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp
index ea449300aef..1009fa2fb5f 100644
--- a/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/multinumericpostattribute.hpp
@@ -51,7 +51,7 @@ template <typename B, typename M>
MultiValueNumericPostingAttribute<B, M>::~MultiValueNumericPostingAttribute()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp
index cd46bbb5a8a..19840b5a474 100644
--- a/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/multistringpostattribute.hpp
@@ -27,7 +27,7 @@ template <typename B, typename T>
MultiValueStringPostingAttributeT<B, T>::~MultiValueStringPostingAttributeT()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h b/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h
index 29440b6ce43..ecf7a46f21e 100644
--- a/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h
+++ b/searchlib/src/vespa/searchlib/attribute/postinglistattribute.h
@@ -58,7 +58,7 @@ protected:
void updatePostings(PostingMap &changePost, const vespalib::datastore::EntryComparator &cmp);
void clearAllPostings();
void disableFreeLists() { _postingList.disableFreeLists(); }
- void disableElemHoldList() { _postingList.disableElemHoldList(); }
+ void disable_entry_hold_list() { _postingList.disable_entry_hold_list(); }
void handle_load_posting_lists_and_update_enum_store(enumstore::EnumeratedPostingsLoader& loader);
bool forwardedOnAddDoc(DocId doc, size_t wantSize, size_t wantCapacity);
diff --git a/searchlib/src/vespa/searchlib/attribute/postingstore.cpp b/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
index 94720212faf..2703201b292 100644
--- a/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/postingstore.cpp
@@ -231,7 +231,7 @@ PostingStore<DataT>::dropBitVector(EntryRef &ref)
(void) tree;
(void) docFreq;
_bvs.erase(ref.ref());
- _store.holdElem(iRef, 1);
+ _store.hold_entry(iRef);
_status.decBitVectors();
_bvExtraBytes -= bv->writer().extraByteSize();
ref = ref2;
@@ -267,7 +267,7 @@ PostingStore<DataT>::makeBitVector(EntryRef &ref)
if (_enableOnlyBitVector) {
BTreeType *tree = getWTreeEntry(iRef);
tree->clear(_allocator);
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
} else {
bve->_tree = ref;
}
@@ -590,19 +590,19 @@ PostingStore<DataT>::clear(const EntryRef ref)
assert(isBTree(iRef2));
BTreeType *tree = getWTreeEntry(iRef2);
tree->clear(_allocator);
- _store.holdElem(iRef2, 1);
+ _store.hold_entry(iRef2);
}
_bvs.erase(ref.ref());
_status.decBitVectors();
_bvExtraBytes -= bve->_bv->writer().extraByteSize();
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
} else {
BTreeType *tree = getWTreeEntry(iRef);
tree->clear(_allocator);
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
}
} else {
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
}
}
diff --git a/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp
index 1775774171d..de4a7157dae 100644
--- a/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/singlenumericpostattribute.hpp
@@ -13,7 +13,7 @@ template <typename B>
SingleValueNumericPostingAttribute<B>::~SingleValueNumericPostingAttribute()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp b/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp
index eef72984e79..1ec9b54a73b 100644
--- a/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/singlestringpostattribute.hpp
@@ -27,7 +27,7 @@ template <typename B>
SingleValueStringPostingAttributeT<B>::~SingleValueStringPostingAttributeT()
{
this->disableFreeLists();
- this->disableElemHoldList();
+ this->disable_entry_hold_list();
clearAllPostings();
}
diff --git a/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp b/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp
index 72f4a7ae579..4bc7f5b1144 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp
+++ b/searchlib/src/vespa/searchlib/memoryindex/feature_store.cpp
@@ -36,7 +36,7 @@ EntryRef
FeatureStore::addFeatures(const uint8_t *src, uint64_t byteLen)
{
uint32_t pad = Aligner::pad(byteLen);
- auto result = _store.rawAllocator<uint8_t>(_typeId).alloc(byteLen + pad, DECODE_SAFETY);
+ auto result = _store.rawAllocator<uint8_t>(_typeId).alloc((byteLen + pad) / buffer_array_size, DECODE_SAFETY_ENTRIES);
uint8_t *dst = result.data;
memcpy(dst, src, byteLen);
dst += byteLen;
@@ -113,7 +113,7 @@ FeatureStore::add_features_guard_bytes()
{
uint32_t len = DECODE_SAFETY;
uint32_t pad = Aligner::pad(len);
- auto result = _store.rawAllocator<uint8_t>(_typeId).alloc(len + pad);
+ auto result = _store.rawAllocator<uint8_t>(_typeId).alloc((len + pad) / buffer_array_size);
memset(result.data, 0, len + pad);
}
diff --git a/searchlib/src/vespa/searchlib/memoryindex/feature_store.h b/searchlib/src/vespa/searchlib/memoryindex/feature_store.h
index 53588fa2894..1e48189987e 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/feature_store.h
+++ b/searchlib/src/vespa/searchlib/memoryindex/feature_store.h
@@ -29,6 +29,7 @@ private:
using PosOccFieldsParams = bitcompression::PosOccFieldsParams;
static constexpr uint32_t DECODE_SAFETY = 16;
+ static constexpr uint32_t DECODE_SAFETY_ENTRIES = 16 / buffer_array_size;
DataStoreType _store;
@@ -117,7 +118,7 @@ public:
* overrun beyond the compressed data either goes into other features
* already written or into the guard area.
*
- * If buffer type is changed to have a nonzero numArraysForNewBuffer then
+ * If buffer type is changed to have a nonzero num_entries_for_new_buffer then
* extra logic to add guard bytes is needed when switching primary buffer
* to avoid issues if the buffer is resumed as primary buffer later on.
*/
diff --git a/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp b/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
index 4be3031303e..8dd76a90b14 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
+++ b/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
@@ -55,9 +55,9 @@ template <bool interleaved_features>
FieldIndex<interleaved_features>::~FieldIndex()
{
_postingListStore.disableFreeLists();
- _postingListStore.disableElemHoldList();
+ _postingListStore.disable_entry_hold_list();
_dict.disableFreeLists();
- _dict.disableElemHoldList();
+ _dict.disable_entry_hold_list();
// XXX: Kludge
for (DictionaryTree::Iterator it = _dict.begin();
it.valid(); ++it) {
diff --git a/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp b/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp
index 3e4c38ceb0e..e330dc83055 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp
+++ b/searchlib/src/vespa/searchlib/memoryindex/word_store.cpp
@@ -27,7 +27,7 @@ WordStore::addWord(const vespalib::stringref word)
{
size_t wordSize = word.size() + 1;
size_t bufferSize = wordSize + Aligner::pad(wordSize);
- auto result = _store.rawAllocator<char>(_typeId).alloc(bufferSize);
+ auto result = _store.rawAllocator<char>(_typeId).alloc(bufferSize / buffer_array_size);
char *be = result.data;
for (size_t i = 0; i < word.size(); ++i) {
*be++ = word[i];
diff --git a/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp b/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp
index 604a467a6e6..a6a82ec09f8 100644
--- a/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp
+++ b/searchlib/src/vespa/searchlib/predicate/document_features_store.cpp
@@ -102,7 +102,7 @@ DocumentFeaturesStore::DocumentFeaturesStore(DataBuffer &buffer)
DocumentFeaturesStore::~DocumentFeaturesStore() {
_word_index.disableFreeLists();
- _word_index.disableElemHoldList();
+ _word_index.disable_entry_hold_list();
_word_index.getAllocator().freeze();
_word_index.clear();
}
diff --git a/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp b/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp
index af809b2fa69..af5aae6e519 100644
--- a/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp
+++ b/searchlib/src/vespa/searchlib/predicate/predicate_interval_store.cpp
@@ -95,7 +95,7 @@ PredicateIntervalStore::remove(EntryRef ref) {
// BufferState &state = _store.getBufferState(buffer_id);
// uint32_t type_id = state.getTypeId();
// uint32_t size = type_id <= MAX_ARRAY_SIZE ? type_id : 1;
- // _store.holdElem(ref, size);
+ // _store.hold_entries(ref, size);
}
}
diff --git a/searchlib/src/vespa/searchlib/predicate/simple_index.hpp b/searchlib/src/vespa/searchlib/predicate/simple_index.hpp
index c6f640d72ed..9320488f88e 100644
--- a/searchlib/src/vespa/searchlib/predicate/simple_index.hpp
+++ b/searchlib/src/vespa/searchlib/predicate/simple_index.hpp
@@ -41,7 +41,7 @@ SimpleIndex<Posting, Key, DocId>::insertIntoVectorPosting(vespalib::datastore::E
template <typename Posting, typename Key, typename DocId>
SimpleIndex<Posting, Key, DocId>::~SimpleIndex() {
_btree_posting_lists.disableFreeLists();
- _btree_posting_lists.disableElemHoldList();
+ _btree_posting_lists.disable_entry_hold_list();
for (auto it = _dictionary.begin(); it.valid(); ++it) {
vespalib::datastore::EntryRef ref(it.getData());
@@ -51,13 +51,13 @@ SimpleIndex<Posting, Key, DocId>::~SimpleIndex() {
}
_vector_posting_lists.disableFreeLists();
- _vector_posting_lists.disableElemHoldList();
+ _vector_posting_lists.disable_entry_hold_list();
_vector_posting_lists.clear();
_vector_posting_lists.getAllocator().freeze();
_vector_posting_lists.getAllocator().reclaim_all_memory();
_dictionary.disableFreeLists();
- _dictionary.disableElemHoldList();
+ _dictionary.disable_entry_hold_list();
_dictionary.clear();
_dictionary.getAllocator().freeze();
_dictionary.getAllocator().reclaim_all_memory();
diff --git a/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt b/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt
index c8c5d4d4257..313863d8dcb 100644
--- a/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt
+++ b/searchlib/src/vespa/searchlib/tensor/CMakeLists.txt
@@ -40,6 +40,7 @@ vespa_add_library(searchlib_tensor OBJECT
tensor_buffer_store.cpp
tensor_buffer_type_mapper.cpp
tensor_deserialize.cpp
+ tensor_ext_attribute.cpp
tensor_store.cpp
DEPENDS
)
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
index c373f6bdcd0..c51d0ec7fd3 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.cpp
@@ -62,10 +62,10 @@ DenseTensorStore::BufferType::BufferType(const TensorSizeCalc &tensorSizeCalc, s
DenseTensorStore::BufferType::~BufferType() = default;
void
-DenseTensorStore::BufferType::cleanHold(void *buffer, size_t offset,
- ElemCount numElems, CleanContext)
+DenseTensorStore::BufferType::clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext)
{
- memset(static_cast<char *>(buffer) + offset, 0, numElems);
+ auto num_elems = num_entries * getArraySize();
+ memset(static_cast<char *>(buffer) + offset * getArraySize(), 0, num_elems);
}
const vespalib::alloc::MemoryAllocator*
@@ -107,7 +107,7 @@ DenseTensorStore::allocRawBuffer()
{
size_t bufSize = getBufSize();
size_t alignedBufSize = _tensorSizeCalc.alignedSize();
- auto result = _concreteStore.freeListRawAllocator<char>(0u).alloc(alignedBufSize);
+ auto result = _concreteStore.freeListRawAllocator<char>(0u).alloc(1);
clearPadAreaAfterBuffer(result.data, bufSize, alignedBufSize);
return result;
}
@@ -118,7 +118,7 @@ DenseTensorStore::holdTensor(EntryRef ref)
if (!ref.valid()) {
return;
}
- _concreteStore.holdElem(ref, _tensorSizeCalc.alignedSize());
+ _concreteStore.hold_entry(ref);
}
TensorStore::EntryRef
diff --git a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
index 9e326e0ab1e..0dd483e7f08 100644
--- a/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
+++ b/searchlib/src/vespa/searchlib/tensor/dense_tensor_store.h
@@ -44,7 +44,7 @@ public:
public:
BufferType(const TensorSizeCalc &tensorSizeCalc, std::shared_ptr<vespalib::alloc::MemoryAllocator> allocator);
~BufferType() override;
- void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
+ void clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
private:
diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp
index fa13ab6303c..8526138fd31 100644
--- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.cpp
@@ -30,11 +30,11 @@ DirectTensorStore::TensorBufferType::TensorBufferType()
}
void
-DirectTensorStore::TensorBufferType::cleanHold(void* buffer, size_t offset, ElemCount num_elems, CleanContext clean_ctx)
+DirectTensorStore::TensorBufferType::clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext clean_ctx)
{
TensorSP* elem = static_cast<TensorSP*>(buffer) + offset;
const auto& empty = empty_entry();
- for (size_t i = 0; i < num_elems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
clean_ctx.extraBytesCleaned((*elem)->get_memory_usage().allocatedBytes());
*elem = empty;
++elem;
@@ -69,7 +69,7 @@ DirectTensorStore::holdTensor(EntryRef ref)
}
const auto& tensor = _tensor_store.getEntry(ref);
assert(tensor);
- _tensor_store.holdElem(ref, 1, tensor->get_memory_usage().allocatedBytes());
+ _tensor_store.hold_entry(ref, tensor->get_memory_usage().allocatedBytes());
}
EntryRef
diff --git a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
index 01084e89776..1230494fe41 100644
--- a/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
+++ b/searchlib/src/vespa/searchlib/tensor/direct_tensor_store.h
@@ -20,7 +20,7 @@ namespace search::tensor {
*/
class DirectTensorStore : public TensorStore {
private:
- // Note: Must use SP (instead of UP) because of fallbackCopy() and initializeReservedElements() in BufferType,
+ // Note: Must use SP (instead of UP) because of fallback_copy() and initialize_reserved_entries() in BufferType,
// and implementation of move().
using TensorSP = std::shared_ptr<vespalib::eval::Value>;
using TensorStoreType = vespalib::datastore::DataStore<TensorSP>;
@@ -32,7 +32,7 @@ private:
using CleanContext = typename ParentType::CleanContext;
public:
TensorBufferType();
- void cleanHold(void* buffer, size_t offset, ElemCount num_elems, CleanContext clean_ctx) override;
+ void clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext clean_ctx) override;
};
TensorStoreType _tensor_store;
diff --git a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp
index cb074348f08..5d3b2206703 100644
--- a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.cpp
@@ -12,7 +12,7 @@ using vespalib::alloc::MemoryAllocator;
namespace search::tensor {
LargeSubspacesBufferType::LargeSubspacesBufferType(const AllocSpec& spec, std::shared_ptr<MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept
- : ParentType(1u, spec.minArraysInBuffer, spec.maxArraysInBuffer, spec.numArraysForNewBuffer, spec.allocGrowFactor),
+ : ParentType(1u, spec.min_entries_in_buffer, spec.max_entries_in_buffer, spec.num_entries_for_new_buffer, spec.allocGrowFactor),
_memory_allocator(std::move(memory_allocator)),
_ops(type_mapper.get_tensor_buffer_operations())
{
@@ -21,10 +21,10 @@ LargeSubspacesBufferType::LargeSubspacesBufferType(const AllocSpec& spec, std::s
LargeSubspacesBufferType::~LargeSubspacesBufferType() = default;
void
-LargeSubspacesBufferType::cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx)
+LargeSubspacesBufferType::clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx)
{
auto elem = static_cast<ArrayType*>(buffer) + offset;
- for (size_t i = 0; i < numElems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
if (!elem->empty()) {
cleanCtx.extraBytesCleaned(elem->size());
_ops.reclaim_labels({elem->data(), elem->size()});
@@ -35,10 +35,10 @@ LargeSubspacesBufferType::cleanHold(void* buffer, size_t offset, ElemCount numEl
}
void
-LargeSubspacesBufferType::destroyElements(void *buffer, ElemCount numElems)
+LargeSubspacesBufferType::destroy_entries(void *buffer, EntryCount num_entries)
{
auto elem = static_cast<ArrayType*>(buffer);
- for (size_t i = 0; i < numElems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
if (!elem->empty()) {
_ops.reclaim_labels({elem->data(), elem->size()});
ArrayType().swap(*elem);
@@ -48,11 +48,11 @@ LargeSubspacesBufferType::destroyElements(void *buffer, ElemCount numElems)
}
void
-LargeSubspacesBufferType::fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems)
+LargeSubspacesBufferType::fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries)
{
auto old_elems = static_cast<const ArrayType*>(oldBuffer);
auto new_elems = static_cast<ArrayType*>(newBuffer);
- for (size_t i = 0; i < numElems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
auto& old_elem = old_elems[i];
new (new_elems + i) ArrayType(old_elem);
if (!old_elem.empty()) {
@@ -62,12 +62,12 @@ LargeSubspacesBufferType::fallbackCopy(void *newBuffer, const void *oldBuffer, E
}
void
-LargeSubspacesBufferType::initializeReservedElements(void *buffer, ElemCount reservedElements)
+LargeSubspacesBufferType::initialize_reserved_entries(void *buffer, EntryCount reserved_entries)
{
- auto new_elems = static_cast<ArrayType*>(buffer);
+ auto new_entries = static_cast<ArrayType*>(buffer);
const auto& empty = empty_entry();
- for (size_t i = 0; i < reservedElements; ++i) {
- new (new_elems + i) ArrayType(empty);
+ for (size_t i = 0; i < reserved_entries; ++i) {
+ new (new_entries + i) ArrayType(empty);
}
}
diff --git a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h
index cfab8ef20af..8cce08e9d81 100644
--- a/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h
+++ b/searchlib/src/vespa/searchlib/tensor/large_subspaces_buffer_type.h
@@ -30,10 +30,10 @@ class LargeSubspacesBufferType : public vespalib::datastore::BufferType<vespalib
public:
LargeSubspacesBufferType(const AllocSpec& spec, std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept;
~LargeSubspacesBufferType() override;
- void cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
- void destroyElements(void *buffer, ElemCount numElems) override;
- void fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems) override;
- void initializeReservedElements(void *buffer, ElemCount reservedElements) override;
+ void clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
+ void destroy_entries(void *buffer, EntryCount num_entries) override;
+ void fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries) override;
+ void initialize_reserved_entries(void *buffer, EntryCount reserved_entries) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
diff --git a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp
index 6a71388a3b9..7b54182f062 100644
--- a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.cpp
@@ -10,7 +10,7 @@ using vespalib::alloc::MemoryAllocator;
namespace search::tensor {
SmallSubspacesBufferType::SmallSubspacesBufferType(uint32_t array_size, const AllocSpec& spec, std::shared_ptr<MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept
- : ParentType(array_size, spec.minArraysInBuffer, spec.maxArraysInBuffer, spec.numArraysForNewBuffer, spec.allocGrowFactor),
+ : ParentType(array_size, spec.min_entries_in_buffer, spec.max_entries_in_buffer, spec.num_entries_for_new_buffer, spec.allocGrowFactor),
_memory_allocator(std::move(memory_allocator)),
_ops(type_mapper.get_tensor_buffer_operations())
{
@@ -19,45 +19,45 @@ SmallSubspacesBufferType::SmallSubspacesBufferType(uint32_t array_size, const Al
SmallSubspacesBufferType::~SmallSubspacesBufferType() = default;
void
-SmallSubspacesBufferType::cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext)
+SmallSubspacesBufferType::clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext)
{
- char* elem = static_cast<char *>(buffer) + offset;
- while (numElems >= getArraySize()) {
+ char* elem = static_cast<char *>(buffer) + offset * getArraySize();
+ while (num_entries >= 1) {
_ops.reclaim_labels(vespalib::ArrayRef<char>(elem, getArraySize()));
elem += getArraySize();
- numElems -= getArraySize();
+ --num_entries;
}
}
void
-SmallSubspacesBufferType::destroyElements(void *buffer, ElemCount numElems)
+SmallSubspacesBufferType::destroy_entries(void *buffer, EntryCount num_entries)
{
char* elem = static_cast<char *>(buffer);
- while (numElems >= getArraySize()) {
+ while (num_entries >= 1) {
_ops.reclaim_labels(vespalib::ArrayRef<char>(elem, getArraySize()));
elem += getArraySize();
- numElems -= getArraySize();
+ --num_entries;
}
}
void
-SmallSubspacesBufferType::fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems)
+SmallSubspacesBufferType::fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries)
{
- if (numElems > 0) {
- memcpy(newBuffer, oldBuffer, numElems);
+ if (num_entries > 0) {
+ memcpy(newBuffer, oldBuffer, num_entries * getArraySize());
}
const char *elem = static_cast<const char *>(oldBuffer);
- while (numElems >= getArraySize()) {
+ while (num_entries >= 1) {
_ops.copied_labels(unconstify(vespalib::ConstArrayRef<char>(elem, getArraySize())));
elem += getArraySize();
- numElems -= getArraySize();
+ --num_entries;
}
}
void
-SmallSubspacesBufferType::initializeReservedElements(void *buffer, ElemCount reservedElements)
+SmallSubspacesBufferType::initialize_reserved_entries(void *buffer, EntryCount reserved_entries)
{
- memset(buffer, 0, reservedElements);
+ memset(buffer, 0, reserved_entries * getArraySize());
}
const vespalib::alloc::MemoryAllocator*
diff --git a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h
index 5622e9970b8..2f287ef1f3d 100644
--- a/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h
+++ b/searchlib/src/vespa/searchlib/tensor/small_subspaces_buffer_type.h
@@ -30,10 +30,10 @@ public:
SmallSubspacesBufferType& operator=(SmallSubspacesBufferType&&) noexcept = delete;
SmallSubspacesBufferType(uint32_t array_size, const AllocSpec& spec, std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator, TensorBufferTypeMapper& type_mapper) noexcept;
~SmallSubspacesBufferType() override;
- void cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
- void destroyElements(void *buffer, ElemCount numElems) override;
- void fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems) override;
- void initializeReservedElements(void *buffer, ElemCount reservedElements) override;
+ void clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
+ void destroy_entries(void *buffer, EntryCount num_entries) override;
+ void fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries) override;
+ void initialize_reserved_entries(void *buffer, EntryCount reserved_entries) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp
new file mode 100644
index 00000000000..19c8cf6053b
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.cpp
@@ -0,0 +1,181 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "tensor_ext_attribute.h"
+#include "serialized_tensor_ref.h"
+#include "vector_bundle.h"
+#include <vespa/eval/eval/fast_value.h>
+#include <vespa/eval/eval/tensor_spec.h>
+#include <vespa/eval/eval/value.h>
+#include <vespa/eval/eval/value_codec.h>
+#include <vespa/searchcommon/attribute/config.h>
+
+#include <vespa/log/log.h>
+LOG_SETUP(".searchlib.tensor.tensor_ext_attribute");
+
+using vespalib::eval::FastValueBuilderFactory;
+using vespalib::eval::TensorSpec;
+using vespalib::eval::TypedCells;
+using vespalib::eval::Value;
+using vespalib::eval::ValueType;
+
+namespace search::tensor {
+
+namespace {
+
+std::unique_ptr<Value>
+create_empty_tensor(const ValueType& type)
+{
+ const auto &factory = FastValueBuilderFactory::get();
+ TensorSpec empty_spec(type.to_spec());
+ return vespalib::eval::value_from_spec(empty_spec, factory);
+}
+
+}
+
+TensorExtAttribute::TensorExtAttribute(const vespalib::string& name, const Config& cfg)
+ : NotImplementedAttribute(name, cfg),
+ ITensorAttribute(),
+ IExtendAttribute(),
+ _subspace_type(cfg.tensorType()),
+ _empty(_subspace_type),
+ _empty_tensor(create_empty_tensor(cfg.tensorType()))
+{
+}
+
+TensorExtAttribute::~TensorExtAttribute() = default;
+
+const ITensorAttribute*
+TensorExtAttribute::asTensorAttribute() const
+{
+ return this;
+}
+
+void
+TensorExtAttribute::onCommit()
+{
+ LOG_ABORT("should not be reached");
+}
+
+void
+TensorExtAttribute::onUpdateStat()
+{
+}
+
+bool
+TensorExtAttribute::addDoc(DocId& docId)
+{
+ docId = _data.size();
+ _data.emplace_back(nullptr);
+ incNumDocs();
+ setCommittedDocIdLimit(getNumDocs());
+ return true;
+}
+
+bool
+TensorExtAttribute::add(const vespalib::eval::Value& v, int32_t)
+{
+ _data.back() = &v;
+ return true;
+}
+
+IExtendAttribute*
+TensorExtAttribute::getExtendInterface()
+{
+ return this;
+}
+
+TypedCells
+TensorExtAttribute::get_vector(uint32_t docid, uint32_t subspace) const
+{
+ auto vectors = get_vectors(docid);
+ return (subspace < vectors.subspaces()) ? vectors.cells(subspace) : _empty.cells();
+}
+
+VectorBundle
+TensorExtAttribute::get_vectors(uint32_t docid) const
+{
+ auto tensor = _data[docid];
+ if (tensor == nullptr) {
+ return VectorBundle();
+ }
+ return VectorBundle(tensor->cells().data, tensor->index().size(), _subspace_type);
+}
+
+std::unique_ptr<Value>
+TensorExtAttribute::getTensor(uint32_t docid) const
+{
+ auto tensor = _data[docid];
+ if (tensor == nullptr) {
+ return {};
+ }
+ return FastValueBuilderFactory::get().copy(*tensor);
+}
+
+std::unique_ptr<Value>
+TensorExtAttribute::getEmptyTensor() const
+{
+ return FastValueBuilderFactory::get().copy(*_empty_tensor);
+}
+
+TypedCells
+TensorExtAttribute::extract_cells_ref(uint32_t docid) const
+{
+ return get_vector(docid, 0);
+}
+
+const vespalib::eval::Value&
+TensorExtAttribute::get_tensor_ref(uint32_t docid) const
+{
+ auto tensor = _data[docid];
+ return (tensor == nullptr) ? *_empty_tensor : *tensor;
+}
+
+SerializedTensorRef
+TensorExtAttribute::get_serialized_tensor_ref(uint32_t) const
+{
+ notImplemented();
+}
+
+bool
+TensorExtAttribute::supports_extract_cells_ref() const
+{
+ return getConfig().tensorType().is_dense();
+}
+
+bool
+TensorExtAttribute::supports_get_tensor_ref() const
+{
+ return true;
+}
+
+bool
+TensorExtAttribute::supports_get_serialized_tensor_ref() const
+{
+ return false;
+}
+
+const ValueType&
+TensorExtAttribute::getTensorType() const
+{
+ return getConfig().tensorType();
+}
+
+TensorExtAttribute::DistanceMetric
+TensorExtAttribute::distance_metric() const
+{
+ return getConfig().distance_metric();
+}
+
+uint32_t
+TensorExtAttribute::get_num_docs() const
+{
+ return _data.size();
+}
+
+void
+TensorExtAttribute::get_state(const vespalib::slime::Inserter& inserter) const
+{
+ (void) inserter;
+}
+
+}
diff --git a/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h
new file mode 100644
index 00000000000..a58426cd146
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/tensor/tensor_ext_attribute.h
@@ -0,0 +1,54 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include "i_tensor_attribute.h"
+#include "empty_subspace.h"
+#include "subspace_type.h"
+#include <vespa/searchlib/attribute/not_implemented_attribute.h>
+#include <vespa/vespalib/stllike/allocator.h>
+
+namespace search::tensor {
+
+/**
+ * Attribute vector storing a pointer to single tensor value per
+ * document in streaming search. The tensor is not owned by this
+ * attribute vector.
+ */
+class TensorExtAttribute : public NotImplementedAttribute,
+ public ITensorAttribute,
+ public IExtendAttribute
+{
+ std::vector<const vespalib::eval::Value*> _data;
+ SubspaceType _subspace_type;
+ EmptySubspace _empty;
+ std::unique_ptr<vespalib::eval::Value> _empty_tensor;
+public:
+ TensorExtAttribute(const vespalib::string& name, const Config& cfg);
+ ~TensorExtAttribute() override;
+ const ITensorAttribute* asTensorAttribute() const override;
+ void onCommit() override;
+ void onUpdateStat() override;
+ bool addDoc(DocId& docId) override;
+ bool add(const vespalib::eval::Value& v, int32_t) override;
+ IExtendAttribute* getExtendInterface() override;
+ // DocVectorAccess API
+ vespalib::eval::TypedCells get_vector(uint32_t docid, uint32_t subspace) const override;
+ VectorBundle get_vectors(uint32_t docid) const override;
+
+ // ITensorAttribute API
+ std::unique_ptr<vespalib::eval::Value> getTensor(uint32_t docid) const override;
+ std::unique_ptr<vespalib::eval::Value> getEmptyTensor() const override;
+ vespalib::eval::TypedCells extract_cells_ref(uint32_t docid) const override;
+ const vespalib::eval::Value& get_tensor_ref(uint32_t docid) const override;
+ SerializedTensorRef get_serialized_tensor_ref(uint32_t docid) const override;
+ bool supports_extract_cells_ref() const override;
+ bool supports_get_tensor_ref() const override;
+ bool supports_get_serialized_tensor_ref() const override;
+ const vespalib::eval::ValueType & getTensorType() const override;
+ search::attribute::DistanceMetric distance_metric() const override;
+ uint32_t get_num_docs() const override;
+ void get_state(const vespalib::slime::Inserter& inserter) const override;
+};
+
+}
diff --git a/storage/src/vespa/storage/bucketdb/btree_lockable_map.hpp b/storage/src/vespa/storage/bucketdb/btree_lockable_map.hpp
index 1c0f9ec7a59..e24e97ff2a4 100644
--- a/storage/src/vespa/storage/bucketdb/btree_lockable_map.hpp
+++ b/storage/src/vespa/storage/bucketdb/btree_lockable_map.hpp
@@ -49,7 +49,7 @@ struct BTreeLockableMap<T>::ValueTraits {
return store.addEntry(value).ref();
}
static void remove_by_wrapped_value(DataStoreType& store, uint64_t value) noexcept {
- store.holdElem(entry_ref_from_value(value), 1);
+ store.hold_entry(entry_ref_from_value(value));
}
static ValueType unwrap_from_key_value(const DataStoreType& store, [[maybe_unused]] uint64_t key, uint64_t value) {
return store.getEntry(entry_ref_from_value(value));
diff --git a/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp b/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp
index 92b9e832a23..1d29a8795d5 100644
--- a/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp
+++ b/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp
@@ -1054,7 +1054,7 @@ FileStorHandlerImpl::Stripe::waitUntilNoLocks() const
{
std::unique_lock guard(*_lock);
while (!_lockedBuckets.empty()) {
- _cond->wait(guard);
+ _cond->wait_for(guard, 100ms);
}
}
@@ -1062,7 +1062,7 @@ void
FileStorHandlerImpl::Stripe::waitInactive(const AbortBucketOperationsCommand& cmd) const {
std::unique_lock guard(*_lock);
while (hasActive(guard, cmd)) {
- _cond->wait(guard);
+ _cond->wait_for(guard, 100ms);
}
}
diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp
index d0e3d1f038b..2caf2de1d0b 100644
--- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp
+++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp
@@ -7,6 +7,7 @@
#include <vespa/persistence/spi/docentry.h>
#include <vespa/document/datatype/positiondatatype.h>
#include <vespa/document/datatype/documenttype.h>
+#include <vespa/document/datatype/tensor_data_type.h>
#include <vespa/document/datatype/weightedsetdatatype.h>
#include <vespa/document/datatype/mapdatatype.h>
#include <vespa/searchlib/aggregation/modifiers.h>
@@ -14,6 +15,7 @@
#include <vespa/searchlib/common/packets.h>
#include <vespa/searchlib/uca/ucaconverter.h>
#include <vespa/searchlib/features/setup.h>
+#include <vespa/searchlib/tensor/tensor_ext_attribute.h>
#include <vespa/searchcommon/attribute/config.h>
#include <vespa/vespalib/geo/zcurve.h>
#include <vespa/vespalib/objects/nbostream.h>
@@ -99,6 +101,16 @@ createMultiValueAttribute(const vespalib::string & name, const document::FieldVa
return {};
}
+const document::TensorDataType*
+get_tensor_type(const document::FieldValue& fv)
+{
+ auto tfv = dynamic_cast<const document::TensorFieldValue*>(&fv);
+ if (tfv == nullptr) {
+ return nullptr;
+ }
+ return dynamic_cast<const document::TensorDataType*>(tfv->getDataType());
+}
+
AttributeVector::SP
createAttribute(const vespalib::string & name, const document::FieldValue & fv)
{
@@ -111,6 +123,12 @@ createAttribute(const vespalib::string & name, const document::FieldValue & fv)
return std::make_shared<search::SingleStringExtAttribute>(name);
} else if (fv.isA(document::FieldValue::Type::RAW)) {
return std::make_shared<search::attribute::SingleRawExtAttribute>(name);
+ } else if (fv.isA(document::FieldValue::Type::TENSOR) && get_tensor_type(fv) != nullptr) {
+ search::attribute::Config cfg(search::attribute::BasicType::TENSOR, search::attribute::CollectionType::SINGLE);
+ auto tdt = get_tensor_type(fv);
+ assert(tdt != nullptr);
+ cfg.setTensorType(tdt->getTensorType());
+ return std::make_shared<search::tensor::TensorExtAttribute>(name, cfg);
} else {
LOG(debug, "Can not make an attribute out of %s of type '%s'.", name.c_str(), fv.className());
}
@@ -444,6 +462,14 @@ SearchVisitor::AttributeInserter::onPrimitive(uint32_t, const Content & c)
} else if (_attribute.is_raw_type()) {
auto raw_value = value.getAsRaw();
attr.add(vespalib::ConstArrayRef<char>(raw_value.first, raw_value.second), c.getWeight());
+ } else if (_attribute.isTensorType()) {
+ auto tfvalue = dynamic_cast<const document::TensorFieldValue*>(&value);
+ if (tfvalue != nullptr) {
+ auto tensor = tfvalue->getAsTensorPtr();
+ if (tensor != nullptr) {
+ attr.add(*tensor, c.getWeight());
+ }
+ }
} else {
assert(false && "We got an attribute vector that is of an unknown type");
}
diff --git a/vdslib/src/tests/distribution/distributiontest.cpp b/vdslib/src/tests/distribution/distributiontest.cpp
index a10aca45b33..b5c756aece9 100644
--- a/vdslib/src/tests/distribution/distributiontest.cpp
+++ b/vdslib/src/tests/distribution/distributiontest.cpp
@@ -17,8 +17,9 @@
#include <vespa/vespalib/util/size_literals.h>
#include <gmock/gmock.h>
#include <chrono>
-#include <thread>
#include <fstream>
+#include <iterator>
+#include <thread>
using namespace ::testing;
@@ -434,7 +435,8 @@ TEST(DistributionTest, test_distribution)
_distribution[i].second = distr.getIdealStorageNodes(
systemState, document::BucketId(26, i));
sort(_distribution[i].second.begin(), _distribution[i].second.end());
- unique(_distribution[i].second.begin(), _distribution[i].second.end());
+ auto unique_nodes = std::distance(_distribution[i].second.begin(), unique(_distribution[i].second.begin(), _distribution[i].second.end()));
+ _distribution[i].second.resize(unique_nodes);
for (unsigned j = 0; j < _distribution[i].second.size(); j++) {
_nodeCount[_distribution[i].second[j]]++;
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java
index fe1e2b46830..2a688ad078b 100644
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java
+++ b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java
@@ -1226,7 +1226,7 @@ public class DocumentV1ApiHandler extends AbstractRequestHandler {
getProperty(request, TRACELEVEL, integerParser).ifPresent(parameters::setTraceLevel);
- getProperty(request, CONTINUATION).map(ProgressToken::fromSerializedString).ifPresent(parameters::setResumeToken);
+ getProperty(request, CONTINUATION, ProgressToken::fromSerializedString).ifPresent(parameters::setResumeToken);
parameters.setPriority(DocumentProtocol.Priority.NORMAL_4);
getProperty(request, FROM_TIMESTAMP, unsignedLongParser).ifPresent(parameters::setFromTimestamp);
diff --git a/vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java b/vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java
index 33e46ebc75f..31f4038c16e 100644
--- a/vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java
+++ b/vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java
@@ -37,15 +37,17 @@ public abstract class Maintainer implements Runnable {
private final AtomicBoolean shutDown = new AtomicBoolean();
private final boolean ignoreCollision;
private final Clock clock;
+ private final Double successFactorBaseline;
public Maintainer(String name, Duration interval, Clock clock, JobControl jobControl,
- JobMetrics jobMetrics, List<String> clusterHostnames, boolean ignoreCollision) {
+ JobMetrics jobMetrics, List<String> clusterHostnames, boolean ignoreCollision, Double successFactorBaseline) {
this.name = name;
this.interval = requireInterval(interval);
this.jobControl = Objects.requireNonNull(jobControl);
this.jobMetrics = Objects.requireNonNull(jobMetrics);
this.ignoreCollision = ignoreCollision;
this.clock = clock;
+ this.successFactorBaseline = successFactorBaseline;
var startedAt = clock.instant();
Objects.requireNonNull(clusterHostnames);
Duration initialDelay = staggeredDelay(interval, startedAt, HostName.getLocalhost(), clusterHostnames)
@@ -55,6 +57,10 @@ public abstract class Maintainer implements Runnable {
jobControl.started(name(), this);
}
+ public Maintainer(String name, Duration interval, Clock clock, JobControl jobControl,
+ JobMetrics jobMetrics, List<String> clusterHostnames, boolean ignoreCollision) {
+ this(name, interval, clock, jobControl, jobMetrics, clusterHostnames, ignoreCollision, 1.0);
+ }
@Override
public void run() {
lockAndMaintain(false);
@@ -91,16 +97,16 @@ public abstract class Maintainer implements Runnable {
/**
* Called once each time this maintenance job should run.
*
- * @return the degree to which the run was successful - a number between 0 (no success), to 1 (complete success).
+ * @return the degree to which the run was deviated from the successFactorBaseline - a number between -1 (no success), to 0 (complete success).
* Note that this indicates whether something is wrong, so e.g if the call did nothing because it should do
- * nothing, 1.0 should be returned.
+ * nothing, 0.0 should be returned.
*/
protected abstract double maintain();
- /** Convenience methods to convert attempts and failures into a success factor */
- protected final double asSuccessFactor(int attempts, int failures) {
+ /** Convenience methods to convert attempts and failures into a success factor, and return */
+ protected final double asSuccessFactorDeviation(int attempts, int failures) {
double factor = attempts == 0 ? 1.0 : 1 - (double)failures / attempts;
- return new BigDecimal(factor).setScale(2, RoundingMode.HALF_UP).doubleValue();
+ return new BigDecimal(factor - successFactorBaseline).setScale(2, RoundingMode.HALF_UP).doubleValue();
}
/** Returns the interval at which this job is set to run */
@@ -111,14 +117,14 @@ public abstract class Maintainer implements Runnable {
if (!force && !jobControl.isActive(name())) return;
log.log(Level.FINE, () -> "Running " + this.getClass().getSimpleName());
- double successFactor = 0;
+ double successFactorDeviation = 0;
long startTime = clock.millis();
try (var lock = jobControl.lockJob(name())) {
- successFactor = maintain();
+ successFactorDeviation = maintain();
}
catch (UncheckedTimeoutException e) {
if (ignoreCollision)
- successFactor = 1;
+ successFactorDeviation = 0;
else
log.log(Level.WARNING, this + " collided with another run. Will retry in " + interval);
}
@@ -127,7 +133,7 @@ public abstract class Maintainer implements Runnable {
}
finally {
long endTime = clock.millis();
- jobMetrics.completed(name(), successFactor, endTime - startTime);
+ jobMetrics.completed(name(), successFactorDeviation, endTime - startTime);
}
log.log(Level.FINE, () -> "Finished " + this.getClass().getSimpleName());
}
diff --git a/vespajlib/src/main/java/com/yahoo/slime/SlimeUtils.java b/vespajlib/src/main/java/com/yahoo/slime/SlimeUtils.java
index f9230ab6df6..6acd0679da2 100644
--- a/vespajlib/src/main/java/com/yahoo/slime/SlimeUtils.java
+++ b/vespajlib/src/main/java/com/yahoo/slime/SlimeUtils.java
@@ -166,81 +166,32 @@ public class SlimeUtils {
false);
}
- private static class Equal {
- protected final Inspector rhsInspector;
-
- protected boolean equal = true;
-
- public Equal(Inspector rhsInspector) { this.rhsInspector = rhsInspector; }
-
- public boolean isEqual() { return equal; }
- }
-
- private static class EqualArray extends Equal implements ArrayTraverser {
- public EqualArray(Inspector rhsInspector) { super(rhsInspector); }
-
- @Override
- public void entry(int idx, Inspector inspector) {
- if (equal) {
- equal = inspector.equalTo(rhsInspector.entry(idx));
- }
- }
- }
-
- private static class EqualObject extends Equal implements ObjectTraverser {
- public EqualObject(Inspector rhsInspector) { super(rhsInspector); }
-
- @Override
- public void field(String name, Inspector inspector) {
- if (equal) {
- equal = inspector.equalTo(rhsInspector.field(name));
- }
- }
- }
-
public static boolean equalTo(Inspector a, Inspector b) {
- boolean equal = a.type() == b.type();
-
- if (equal) {
- switch (a.type()) {
- case NIX:
- equal = a.valid() == b.valid();
- break;
- case BOOL:
- equal = a.asBool() == b.asBool();
- break;
- case LONG:
- equal = a.asLong() == b.asLong();
- break;
- case DOUBLE:
- equal = Double.compare(a.asDouble(), b.asDouble()) == 0;
- break;
- case STRING:
- equal = a.asString().equals(b.asString());
- break;
- case DATA:
- equal = Arrays.equals(a.asData(), b.asData());
- break;
- case ARRAY:
- {
- var traverser = new EqualArray(b);
- a.traverse(traverser);
- equal = traverser.isEqual() && (a.entries() == b.entries());
- }
- break;
- case OBJECT:
- {
- var traverser = new EqualObject(b);
- a.traverse(traverser);
- equal = traverser.isEqual() && (a.fields() == b.fields());
+ if (a.type() != b.type()) return false;
+
+ switch (a.type()) {
+ case NIX: return a.valid() == b.valid();
+ case BOOL: return a.asBool() == b.asBool();
+ case LONG: return a.asLong() == b.asLong();
+ case DOUBLE: return Double.compare(a.asDouble(), b.asDouble()) == 0;
+ case STRING: return a.asString().equals(b.asString());
+ case DATA: return Arrays.equals(a.asData(), b.asData());
+ case ARRAY: {
+ if (a.entries() != b.entries()) return false;
+ for (int i = 0; i < a.entries(); i++) {
+ if (!equalTo(a.entry(i), b.entry(i))) return false;
}
- break;
- default:
- assert(false);
- break;
+ return true;
}
+ case OBJECT: {
+ if (a.fields() != b.fields()) return false;
+ boolean[] equal = new boolean[]{ true };
+ a.traverse((String key, Inspector value) -> {
+ if (equal[0] && !equalTo(value, b.field(key))) equal[0] = false;
+ });
+ return equal[0];
+ }
+ default: throw new IllegalStateException("Unexpected type: " + a.type());
}
-
- return equal;
}
}
diff --git a/vespalib/src/tests/btree/btree-stress/btree_stress_test.cpp b/vespalib/src/tests/btree/btree-stress/btree_stress_test.cpp
index 44decb9bf91..31113f2b4f2 100644
--- a/vespalib/src/tests/btree/btree-stress/btree_stress_test.cpp
+++ b/vespalib/src/tests/btree/btree-stress/btree_stress_test.cpp
@@ -53,7 +53,7 @@ public:
~RealIntStore();
EntryRef add(uint32_t value) { return _store.addEntry(value); }
AtomicEntryRef add_relaxed(uint32_t value) { return AtomicEntryRef(add(value)); }
- void hold(const AtomicEntryRef& ref) { _store.holdElem(ref.load_relaxed(), 1); }
+ void hold(const AtomicEntryRef& ref) { _store.hold_entry(ref.load_relaxed()); }
EntryRef move(EntryRef ref);
void assign_generation(generation_t current_gen) { _store.assign_generation(current_gen); }
void reclaim_memory(generation_t gen) { _store.reclaim_memory(gen); }
diff --git a/vespalib/src/tests/btree/btree_test.cpp b/vespalib/src/tests/btree/btree_test.cpp
index b8da9ea6042..afad3523fa3 100644
--- a/vespalib/src/tests/btree/btree_test.cpp
+++ b/vespalib/src/tests/btree/btree_test.cpp
@@ -1065,7 +1065,7 @@ adjustAllocatedBytes(size_t nodeCount, size_t nodeSize)
TEST_F(BTreeTest, require_that_memory_usage_is_calculated)
{
constexpr size_t BASE_ALLOCATED = 28744u;
- constexpr size_t BASE_USED = 24984;
+ constexpr size_t BASE_USED = 24936;
typedef BTreeNodeAllocator<int32_t, int8_t,
btree::NoAggregated,
MyTraits::INTERNAL_SLOTS, MyTraits::LEAF_SLOTS> NodeAllocator;
diff --git a/vespalib/src/tests/datastore/array_store/array_store_test.cpp b/vespalib/src/tests/datastore/array_store/array_store_test.cpp
index ccc3ab88c31..1df03f6eb0a 100644
--- a/vespalib/src/tests/datastore/array_store/array_store_test.cpp
+++ b/vespalib/src/tests/datastore/array_store/array_store_test.cpp
@@ -29,16 +29,16 @@ constexpr float ALLOC_GROW_FACTOR = 0.2;
}
-template <typename TestT, typename EntryT, typename RefT = EntryRefT<19> >
+template <typename TestT, typename ElemT, typename RefT = EntryRefT<19> >
struct ArrayStoreTest : public TestT
{
using EntryRefType = RefT;
- using ArrayStoreType = ArrayStore<EntryT, RefT>;
+ using ArrayStoreType = ArrayStore<ElemT, RefT>;
using LargeArray = typename ArrayStoreType::LargeArray;
using ConstArrayRef = typename ArrayStoreType::ConstArrayRef;
- using EntryVector = std::vector<EntryT>;
- using value_type = EntryT;
- using ReferenceStore = vespalib::hash_map<EntryRef, EntryVector>;
+ using ElemVector = std::vector<ElemT>;
+ using value_type = ElemT;
+ using ReferenceStore = vespalib::hash_map<EntryRef, ElemVector>;
AllocStats stats;
ArrayStoreType store;
@@ -61,11 +61,11 @@ struct ArrayStoreTest : public TestT
add_using_allocate(false)
{}
~ArrayStoreTest() override;
- void assertAdd(const EntryVector &input) {
+ void assertAdd(const ElemVector &input) {
EntryRef ref = add(input);
assertGet(ref, input);
}
- EntryRef add(const EntryVector &input) {
+ EntryRef add(const ElemVector &input) {
EntryRef result;
if (add_using_allocate) {
result = store.allocate(input.size());
@@ -82,16 +82,16 @@ struct ArrayStoreTest : public TestT
refStore.insert(std::make_pair(result, input));
return result;
}
- void assertGet(EntryRef ref, const EntryVector &exp) const {
+ void assertGet(EntryRef ref, const ElemVector &exp) const {
ConstArrayRef act = store.get(ref);
- EXPECT_EQ(exp, EntryVector(act.begin(), act.end()));
+ EXPECT_EQ(exp, ElemVector(act.begin(), act.end()));
}
void remove(EntryRef ref) {
ASSERT_EQ(1u, refStore.count(ref));
store.remove(ref);
refStore.erase(ref);
}
- void remove(const EntryVector &input) {
+ void remove(const ElemVector &input) {
remove(getEntryRef(input));
}
uint32_t getBufferId(EntryRef ref) const {
@@ -99,14 +99,14 @@ struct ArrayStoreTest : public TestT
}
void assertBufferState(EntryRef ref, const MemStats& expStats) {
EXPECT_EQ(expStats._used, store.bufferState(ref).size());
- EXPECT_EQ(expStats._hold, store.bufferState(ref).stats().hold_elems());
- EXPECT_EQ(expStats._dead, store.bufferState(ref).stats().dead_elems());
+ EXPECT_EQ(expStats._hold, store.bufferState(ref).stats().hold_entries());
+ EXPECT_EQ(expStats._dead, store.bufferState(ref).stats().dead_entries());
}
void assert_buffer_stats(EntryRef ref, const TestBufferStats& exp_stats) {
const auto& state = store.bufferState(ref);
EXPECT_EQ(exp_stats._used, state.size());
- EXPECT_EQ(exp_stats._hold, state.stats().hold_elems());
- EXPECT_EQ(exp_stats._dead, state.stats().dead_elems());
+ EXPECT_EQ(exp_stats._hold, state.stats().hold_entries());
+ EXPECT_EQ(exp_stats._dead, state.stats().dead_entries());
EXPECT_EQ(exp_stats._extra_used, state.stats().extra_used_bytes());
EXPECT_EQ(exp_stats._extra_hold, state.stats().extra_hold_bytes());
}
@@ -121,7 +121,7 @@ struct ArrayStoreTest : public TestT
assertGet(elem.first, elem.second);
}
}
- void assert_ref_reused(const EntryVector& first, const EntryVector& second, bool should_reuse) {
+ void assert_ref_reused(const ElemVector& first, const ElemVector& second, bool should_reuse) {
EntryRef ref1 = add(first);
remove(ref1);
reclaim_memory();
@@ -129,7 +129,7 @@ struct ArrayStoreTest : public TestT
EXPECT_EQ(should_reuse, (ref2 == ref1));
assertGet(ref2, second);
}
- EntryRef getEntryRef(const EntryVector &input) {
+ EntryRef getEntryRef(const ElemVector &input) {
for (auto itr = refStore.begin(); itr != refStore.end(); ++itr) {
if (itr->second == input) {
return itr->first;
@@ -160,12 +160,12 @@ struct ArrayStoreTest : public TestT
}
refStore = compactedRefStore;
}
- size_t entrySize() const { return sizeof(EntryT); }
+ size_t elem_size() const { return sizeof(ElemT); }
size_t largeArraySize() const { return sizeof(LargeArray); }
};
-template <typename TestT, typename EntryT, typename RefT>
-ArrayStoreTest<TestT, EntryT, RefT>::~ArrayStoreTest() = default;
+template <typename TestT, typename ElemT, typename RefT>
+ArrayStoreTest<TestT, ElemT, RefT>::~ArrayStoreTest() = default;
struct TestParam {
bool add_using_allocate;
@@ -214,8 +214,8 @@ TEST_P(NumberStoreTest, control_static_sizes) {
EXPECT_EQ(240u + sizeof_deque, sizeof(NumberStoreTest::ArrayStoreType::DataStoreType));
EXPECT_EQ(104u, sizeof(NumberStoreTest::ArrayStoreType::SmallBufferType));
MemoryUsage usage = store.getMemoryUsage();
- EXPECT_EQ(202120u, usage.allocatedBytes());
- EXPECT_EQ(197752u, usage.usedBytes());
+ EXPECT_EQ(202116u, usage.allocatedBytes());
+ EXPECT_EQ(197656u, usage.usedBytes());
}
TEST_P(NumberStoreTest, add_and_get_small_arrays_of_trivial_type)
@@ -246,15 +246,15 @@ TEST_F(StringStoreTest, add_and_get_large_arrays_of_non_trivial_type)
assertAdd({"ddd", "eee", "ffff", "gggg", "hhhh"});
}
-TEST_P(NumberStoreTest, elements_are_put_on_hold_when_a_small_array_is_removed)
+TEST_P(NumberStoreTest, entries_are_put_on_hold_when_a_small_array_is_removed)
{
EntryRef ref = add({1,2,3});
- assertBufferState(ref, MemStats().used(3).hold(0));
+ assertBufferState(ref, MemStats().used(1).hold(0));
store.remove(ref);
- assertBufferState(ref, MemStats().used(3).hold(3));
+ assertBufferState(ref, MemStats().used(1).hold(1));
}
-TEST_P(NumberStoreTest, elements_are_put_on_hold_when_a_large_array_is_removed)
+TEST_P(NumberStoreTest, entries_are_put_on_hold_when_a_large_array_is_removed)
{
EntryRef ref = add({1,2,3,4});
// Note: The first buffer has the first element reserved -> we expect 2 elements used here.
@@ -319,7 +319,7 @@ test_compaction(NumberStoreBasicTest &f)
f.remove(f.add({5,5}));
f.reclaim_memory();
f.assertBufferState(size1Ref, MemStats().used(1).dead(0));
- f.assertBufferState(size2Ref, MemStats().used(4).dead(2));
+ f.assertBufferState(size2Ref, MemStats().used(2).dead(1));
f.assertBufferState(size3Ref, MemStats().used(2).dead(1)); // Note: First element is reserved
uint32_t size1BufferId = f.getBufferId(size1Ref);
uint32_t size2BufferId = f.getBufferId(size2Ref);
@@ -363,8 +363,8 @@ void testCompaction(NumberStoreTest &f, bool compactMemory, bool compactAddressS
f.remove(f.add({7}));
f.reclaim_memory();
f.assertBufferState(size1Ref, MemStats().used(3).dead(2));
- f.assertBufferState(size2Ref, MemStats().used(2).dead(0));
- f.assertBufferState(size3Ref, MemStats().used(6).dead(3));
+ f.assertBufferState(size2Ref, MemStats().used(1).dead(0));
+ f.assertBufferState(size3Ref, MemStats().used(2).dead(1));
uint32_t size1BufferId = f.getBufferId(size1Ref);
uint32_t size2BufferId = f.getBufferId(size2Ref);
uint32_t size3BufferId = f.getBufferId(size3Ref);
@@ -434,22 +434,22 @@ TEST_P(NumberStoreTest, used_onHold_and_dead_memory_usage_is_tracked_for_small_a
{
MemStats exp(store.getMemoryUsage());
add({1,2,3});
- assertMemoryUsage(exp.used(entrySize() * 3));
+ assertMemoryUsage(exp.used(elem_size() * 3));
remove({1,2,3});
- assertMemoryUsage(exp.hold(entrySize() * 3));
+ assertMemoryUsage(exp.hold(elem_size() * 3));
reclaim_memory();
- assertMemoryUsage(exp.holdToDead(entrySize() * 3));
+ assertMemoryUsage(exp.holdToDead(elem_size() * 3));
}
TEST_P(NumberStoreTest, used_onHold_and_dead_memory_usage_is_tracked_for_large_arrays)
{
MemStats exp(store.getMemoryUsage());
add({1,2,3,4});
- assertMemoryUsage(exp.used(largeArraySize() + entrySize() * 4));
+ assertMemoryUsage(exp.used(largeArraySize() + elem_size() * 4));
remove({1,2,3,4});
- assertMemoryUsage(exp.hold(largeArraySize() + entrySize() * 4));
+ assertMemoryUsage(exp.hold(largeArraySize() + elem_size() * 4));
reclaim_memory();
- assertMemoryUsage(exp.decUsed(entrySize() * 4).decHold(largeArraySize() + entrySize() * 4).
+ assertMemoryUsage(exp.decUsed(elem_size() * 4).decHold(largeArraySize() + elem_size() * 4).
dead(largeArraySize()));
}
diff --git a/vespalib/src/tests/datastore/array_store_config/array_store_config_test.cpp b/vespalib/src/tests/datastore/array_store_config/array_store_config_test.cpp
index fcf1acd5cd3..171e7216638 100644
--- a/vespalib/src/tests/datastore/array_store_config/array_store_config_test.cpp
+++ b/vespalib/src/tests/datastore/array_store_config/array_store_config_test.cpp
@@ -22,32 +22,32 @@ struct Fixture
Fixture(uint32_t maxSmallArrayTypeId,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer)
+ size_t min_num_entries_for_new_buffer)
: cfg(ArrayStoreConfig::optimizeForHugePage(maxSmallArrayTypeId,
[](size_t type_id) noexcept { return type_id; },
hugePageSize, smallPageSize,
sizeof(int), EntryRefType::offsetSize(),
- minNumArraysForNewBuffer,
+ min_num_entries_for_new_buffer,
ALLOC_GROW_FACTOR)) { }
- void assertSpec(uint32_t type_id, uint32_t numArraysForNewBuffer) {
+ void assertSpec(uint32_t type_id, uint32_t num_entries_for_new_buffer) {
assertSpec(type_id, AllocSpec(0, EntryRefType::offsetSize(),
- numArraysForNewBuffer, ALLOC_GROW_FACTOR));
+ num_entries_for_new_buffer, ALLOC_GROW_FACTOR));
}
void assertSpec(uint32_t type_id, const AllocSpec &expSpec) {
const auto& actSpec = cfg.spec_for_type_id(type_id);
- EXPECT_EQUAL(expSpec.minArraysInBuffer, actSpec.minArraysInBuffer);
- EXPECT_EQUAL(expSpec.maxArraysInBuffer, actSpec.maxArraysInBuffer);
- EXPECT_EQUAL(expSpec.numArraysForNewBuffer, actSpec.numArraysForNewBuffer);
+ EXPECT_EQUAL(expSpec.min_entries_in_buffer, actSpec.min_entries_in_buffer);
+ EXPECT_EQUAL(expSpec.max_entries_in_buffer, actSpec.max_entries_in_buffer);
+ EXPECT_EQUAL(expSpec.num_entries_for_new_buffer, actSpec.num_entries_for_new_buffer);
EXPECT_EQUAL(expSpec.allocGrowFactor, actSpec.allocGrowFactor);
}
};
AllocSpec
-makeSpec(size_t minArraysInBuffer,
- size_t maxArraysInBuffer,
- size_t numArraysForNewBuffer)
+makeSpec(size_t min_entries_in_buffer,
+ size_t max_entries_in_buffer,
+ size_t num_entries_for_new_buffer)
{
- return AllocSpec(minArraysInBuffer, maxArraysInBuffer, numArraysForNewBuffer, ALLOC_GROW_FACTOR);
+ return AllocSpec(min_entries_in_buffer, max_entries_in_buffer, num_entries_for_new_buffer, ALLOC_GROW_FACTOR);
}
constexpr size_t KB = 1024;
diff --git a/vespalib/src/tests/datastore/buffer_stats/buffer_stats_test.cpp b/vespalib/src/tests/datastore/buffer_stats/buffer_stats_test.cpp
index 09b2590a5f3..fec8d5949f8 100644
--- a/vespalib/src/tests/datastore/buffer_stats/buffer_stats_test.cpp
+++ b/vespalib/src/tests/datastore/buffer_stats/buffer_stats_test.cpp
@@ -9,10 +9,10 @@ using namespace vespalib::datastore;
TEST(BufferStatsTest, buffer_stats_to_memory_stats)
{
InternalBufferStats buf;
- buf.set_alloc_elems(17);
+ buf.set_alloc_entries(17);
buf.pushed_back(7);
- buf.set_dead_elems(5);
- buf.set_hold_elems(3);
+ buf.set_dead_entries(5);
+ buf.set_hold_entries(3);
buf.inc_extra_used_bytes(13);
buf.inc_extra_hold_bytes(11);
@@ -20,10 +20,10 @@ TEST(BufferStatsTest, buffer_stats_to_memory_stats)
constexpr size_t es = 8;
buf.add_to_mem_stats(es, mem);
- EXPECT_EQ(17, mem._allocElems);
- EXPECT_EQ(7, mem._usedElems);
- EXPECT_EQ(5, mem._deadElems);
- EXPECT_EQ(3, mem._holdElems);
+ EXPECT_EQ(17, mem._alloc_entries);
+ EXPECT_EQ(7, mem._used_entries);
+ EXPECT_EQ(5, mem._dead_entries);
+ EXPECT_EQ(3, mem._hold_entries);
EXPECT_EQ(17 * es + 13, mem._allocBytes);
EXPECT_EQ(7 * es + 13, mem._usedBytes);
EXPECT_EQ(5 * es, mem._deadBytes);
diff --git a/vespalib/src/tests/datastore/buffer_type/buffer_type_test.cpp b/vespalib/src/tests/datastore/buffer_type/buffer_type_test.cpp
index de7d899e68a..9f7535a3676 100644
--- a/vespalib/src/tests/datastore/buffer_type/buffer_type_test.cpp
+++ b/vespalib/src/tests/datastore/buffer_type/buffer_type_test.cpp
@@ -7,40 +7,40 @@ using namespace vespalib::datastore;
using IntBufferType = BufferType<int>;
constexpr uint32_t ARRAYS_SIZE(4);
-constexpr uint32_t MAX_ARRAYS(128);
-constexpr uint32_t NUM_ARRAYS_FOR_NEW_BUFFER(0);
+constexpr uint32_t MAX_ENTRIES(128);
+constexpr uint32_t NUM_ENTRIES_FOR_NEW_BUFFER(0);
struct Setup {
- uint32_t _minArrays;
- std::atomic<ElemCount> _usedElems;
- ElemCount _neededElems;
- std::atomic<ElemCount> _deadElems;
+ uint32_t _min_entries;
+ std::atomic<EntryCount> _used_entries;
+ EntryCount _needed_entries;
+ std::atomic<EntryCount> _dead_entries;
uint32_t _bufferId;
float _allocGrowFactor;
bool _resizing;
Setup()
- : _minArrays(0),
- _usedElems(0),
- _neededElems(0),
- _deadElems(0),
+ : _min_entries(0),
+ _used_entries(0),
+ _needed_entries(0),
+ _dead_entries(0),
_bufferId(1),
_allocGrowFactor(0.5),
_resizing(false)
{}
Setup(const Setup& rhs) noexcept;
- Setup &minArrays(uint32_t value) { _minArrays = value; return *this; }
- Setup &used(size_t value) { _usedElems = value; return *this; }
- Setup &needed(size_t value) { _neededElems = value; return *this; }
- Setup &dead(size_t value) { _deadElems = value; return *this; }
+ Setup &min_entries(uint32_t value) { _min_entries = value; return *this; }
+ Setup &used(size_t value) { _used_entries = value; return *this; }
+ Setup &needed(size_t value) { _needed_entries = value; return *this; }
+ Setup &dead(size_t value) { _dead_entries = value; return *this; }
Setup &bufferId(uint32_t value) { _bufferId = value; return *this; }
Setup &resizing(bool value) { _resizing = value; return *this; }
};
Setup::Setup(const Setup& rhs) noexcept
- : _minArrays(rhs._minArrays),
- _usedElems(rhs._usedElems.load(std::memory_order_relaxed)),
- _neededElems(rhs._neededElems),
- _deadElems(rhs._deadElems.load(std::memory_order_relaxed)),
+ : _min_entries(rhs._min_entries),
+ _used_entries(rhs._used_entries.load(std::memory_order_relaxed)),
+ _needed_entries(rhs._needed_entries),
+ _dead_entries(rhs._dead_entries.load(std::memory_order_relaxed)),
_bufferId(rhs._bufferId),
_allocGrowFactor(rhs._allocGrowFactor),
_resizing(rhs._resizing)
@@ -53,7 +53,7 @@ struct Fixture {
int buffer[ARRAYS_SIZE];
Fixture(const Setup &setup_)
: setups(),
- bufferType(ARRAYS_SIZE, setup_._minArrays, MAX_ARRAYS, NUM_ARRAYS_FOR_NEW_BUFFER, setup_._allocGrowFactor),
+ bufferType(ARRAYS_SIZE, setup_._min_entries, MAX_ENTRIES, NUM_ENTRIES_FOR_NEW_BUFFER, setup_._allocGrowFactor),
buffer()
{
setups.reserve(4);
@@ -61,121 +61,121 @@ struct Fixture {
}
~Fixture() {
for (auto& setup : setups) {
- bufferType.onHold(setup._bufferId, &setup._usedElems, &setup._deadElems);
- bufferType.onFree(setup._usedElems);
+ bufferType.on_hold(setup._bufferId, &setup._used_entries, &setup._dead_entries);
+ bufferType.on_free(setup._used_entries);
}
}
Setup& curr_setup() {
return setups.back();
}
void add_setup(const Setup& setup_in) {
- // The buffer type stores pointers to ElemCount (from Setup) and we must ensure these do not move in memory.
+ // The buffer type stores pointers to EntryCount (from Setup) and we must ensure these do not move in memory.
assert(setups.size() < setups.capacity());
setups.push_back(setup_in);
}
void onActive() {
- bufferType.onActive(curr_setup()._bufferId, &curr_setup()._usedElems, &curr_setup()._deadElems, &buffer[0]);
+ bufferType.on_active(curr_setup()._bufferId, &curr_setup()._used_entries, &curr_setup()._dead_entries, &buffer[0]);
}
- size_t arraysToAlloc() {
- return bufferType.calcArraysToAlloc(curr_setup()._bufferId, curr_setup()._neededElems, curr_setup()._resizing);
+ size_t entries_to_alloc() {
+ return bufferType.calc_entries_to_alloc(curr_setup()._bufferId, curr_setup()._needed_entries, curr_setup()._resizing);
}
- void assertArraysToAlloc(size_t exp) {
+ void assert_entries_to_alloc(size_t exp) {
onActive();
- EXPECT_EQUAL(exp, arraysToAlloc());
+ EXPECT_EQUAL(exp, entries_to_alloc());
}
};
void
-assertArraysToAlloc(size_t exp, const Setup &setup)
+assert_entries_to_alloc(size_t exp, const Setup &setup)
{
Fixture f(setup);
- f.assertArraysToAlloc(exp);
+ f.assert_entries_to_alloc(exp);
}
-TEST("require that complete arrays are allocated")
+TEST("require that entries are allocated")
{
- TEST_DO(assertArraysToAlloc(1, Setup().needed(1)));
- TEST_DO(assertArraysToAlloc(1, Setup().needed(2)));
- TEST_DO(assertArraysToAlloc(1, Setup().needed(3)));
- TEST_DO(assertArraysToAlloc(1, Setup().needed(4)));
- TEST_DO(assertArraysToAlloc(2, Setup().needed(5)));
+ TEST_DO(assert_entries_to_alloc(1, Setup().needed(1)));
+ TEST_DO(assert_entries_to_alloc(2, Setup().needed(2)));
+ TEST_DO(assert_entries_to_alloc(3, Setup().needed(3)));
+ TEST_DO(assert_entries_to_alloc(4, Setup().needed(4)));
+ TEST_DO(assert_entries_to_alloc(5, Setup().needed(5)));
}
-TEST("require that reserved elements are taken into account when not resizing")
+TEST("require that reserved entries are taken into account when not resizing")
{
- TEST_DO(assertArraysToAlloc(2, Setup().needed(1).bufferId(0)));
- TEST_DO(assertArraysToAlloc(2, Setup().needed(4).bufferId(0)));
- TEST_DO(assertArraysToAlloc(3, Setup().needed(5).bufferId(0)));
+ TEST_DO(assert_entries_to_alloc(2, Setup().needed(1).bufferId(0)));
+ TEST_DO(assert_entries_to_alloc(5, Setup().needed(4).bufferId(0)));
+ TEST_DO(assert_entries_to_alloc(6, Setup().needed(5).bufferId(0)));
}
-TEST("require that arrays to alloc is based on currently used elements (no resizing)")
+TEST("require that entries to alloc is based on currently used entries (no resizing)")
{
- TEST_DO(assertArraysToAlloc(2, Setup().used(4 * 4).needed(4)));
- TEST_DO(assertArraysToAlloc(4, Setup().used(8 * 4).needed(4)));
+ TEST_DO(assert_entries_to_alloc(2, Setup().used(4).needed(1)));
+ TEST_DO(assert_entries_to_alloc(4, Setup().used(8).needed(1)));
}
-TEST("require that arrays to alloc is based on currently used elements (with resizing)")
+TEST("require that entries to alloc is based on currently used entries (with resizing)")
{
- TEST_DO(assertArraysToAlloc(4 + 2, Setup().used(4 * 4).needed(4).resizing(true)));
- TEST_DO(assertArraysToAlloc(8 + 4, Setup().used(8 * 4).needed(4).resizing(true)));
- TEST_DO(assertArraysToAlloc(4 + 3, Setup().used(4 * 4).needed(3 * 4).resizing(true)));
+ TEST_DO(assert_entries_to_alloc(4 + 2, Setup().used(4).needed(1).resizing(true)));
+ TEST_DO(assert_entries_to_alloc(8 + 4, Setup().used(8).needed(1).resizing(true)));
+ TEST_DO(assert_entries_to_alloc(4 + 3, Setup().used(4).needed(3).resizing(true)));
}
-TEST("require that arrays to alloc always contain elements needed")
+TEST("require that entries to alloc always contain entries needed")
{
- TEST_DO(assertArraysToAlloc(2, Setup().used(4 * 4).needed(2 * 4)));
- TEST_DO(assertArraysToAlloc(3, Setup().used(4 * 4).needed(3 * 4)));
- TEST_DO(assertArraysToAlloc(4, Setup().used(4 * 4).needed(4 * 4)));
+ TEST_DO(assert_entries_to_alloc(2, Setup().used(4).needed(2)));
+ TEST_DO(assert_entries_to_alloc(3, Setup().used(4).needed(3)));
+ TEST_DO(assert_entries_to_alloc(4, Setup().used(4).needed(4)));
}
-TEST("require that arrays to alloc is capped to max arrays")
+TEST("require that entries to alloc is capped to max entries")
{
- TEST_DO(assertArraysToAlloc(127, Setup().used(254 * 4).needed(4)));
- TEST_DO(assertArraysToAlloc(128, Setup().used(256 * 4).needed(4)));
- TEST_DO(assertArraysToAlloc(128, Setup().used(258 * 4).needed(8)));
+ TEST_DO(assert_entries_to_alloc(127, Setup().used(254).needed(1)));
+ TEST_DO(assert_entries_to_alloc(128, Setup().used(256).needed(1)));
+ TEST_DO(assert_entries_to_alloc(128, Setup().used(258).needed(2)));
}
TEST("require that arrays to alloc is capped to min arrays")
{
- TEST_DO(assertArraysToAlloc(16, Setup().used(30 * 4).needed(4).minArrays(16)));
- TEST_DO(assertArraysToAlloc(16, Setup().used(32 * 4).needed(4).minArrays(16)));
- TEST_DO(assertArraysToAlloc(17, Setup().used(34 * 4).needed(4).minArrays(16)));
+ TEST_DO(assert_entries_to_alloc(16, Setup().used(30).needed(1).min_entries(16)));
+ TEST_DO(assert_entries_to_alloc(16, Setup().used(32).needed(1).min_entries(16)));
+ TEST_DO(assert_entries_to_alloc(17, Setup().used(34).needed(1).min_entries(16)));
}
-TEST("arrays to alloc considers used elements across all active buffers of same type (no resizing)")
+TEST("entries to alloc considers used entries across all active buffers of same type (no resizing)")
{
- Fixture f(Setup().used(6 * 4));
- f.assertArraysToAlloc(6 * 0.5);
- f.add_setup(Setup().used(8 * 4).bufferId(2));
- f.assertArraysToAlloc((6 + 8) * 0.5);
- f.add_setup(Setup().used(10 * 4).bufferId(3));
- f.assertArraysToAlloc((6 + 8 + 10) * 0.5);
+ Fixture f(Setup().used(6));
+ f.assert_entries_to_alloc(6 * 0.5);
+ f.add_setup(Setup().used(8).bufferId(2));
+ f.assert_entries_to_alloc((6 + 8) * 0.5);
+ f.add_setup(Setup().used(10).bufferId(3));
+ f.assert_entries_to_alloc((6 + 8 + 10) * 0.5);
}
-TEST("arrays to alloc considers used elements across all active buffers of same type when resizing")
+TEST("entries to alloc considers used entries across all active buffers of same type when resizing")
{
- Fixture f(Setup().used(6 * 4));
- f.assertArraysToAlloc(6 * 0.5);
- f.add_setup(Setup().used(8 * 4).resizing(true).bufferId(2));
- f.assertArraysToAlloc(8 + (6 + 8) * 0.5);
+ Fixture f(Setup().used(6));
+ f.assert_entries_to_alloc(6 * 0.5);
+ f.add_setup(Setup().used(8).resizing(true).bufferId(2));
+ f.assert_entries_to_alloc(8 + (6 + 8) * 0.5);
}
-TEST("arrays to alloc considers (and subtracts) dead elements across all active buffers of same type (no resizing)")
+TEST("entries to alloc considers (and subtracts) dead entries across all active buffers of same type (no resizing)")
{
- Fixture f(Setup().used(6 * 4).dead(2 * 4));
- f.assertArraysToAlloc((6 - 2) * 0.5);
- f.add_setup(Setup().used(12 * 4).dead(4 * 4).bufferId(2));
- f.assertArraysToAlloc((6 - 2 + 12 - 4) * 0.5);
- f.add_setup(Setup().used(20 * 4).dead(6 * 4).bufferId(3));
- f.assertArraysToAlloc((6 - 2 + 12 - 4 + 20 - 6) * 0.5);
+ Fixture f(Setup().used(6).dead(2));
+ f.assert_entries_to_alloc((6 - 2) * 0.5);
+ f.add_setup(Setup().used(12).dead(4).bufferId(2));
+ f.assert_entries_to_alloc((6 - 2 + 12 - 4) * 0.5);
+ f.add_setup(Setup().used(20).dead(6).bufferId(3));
+ f.assert_entries_to_alloc((6 - 2 + 12 - 4 + 20 - 6) * 0.5);
}
TEST("arrays to alloc considers (and subtracts) dead elements across all active buffers of same type when resizing")
{
- Fixture f(Setup().used(6 * 4).dead(2 * 4));
- f.assertArraysToAlloc((6 - 2) * 0.5);
- f.add_setup(Setup().used(12 * 4).dead(4 * 4).resizing(true).bufferId(2));
- f.assertArraysToAlloc(12 + (6 - 2 + 12 - 4) * 0.5);
+ Fixture f(Setup().used(6).dead(2));
+ f.assert_entries_to_alloc((6 - 2) * 0.5);
+ f.add_setup(Setup().used(12).dead(4).resizing(true).bufferId(2));
+ f.assert_entries_to_alloc(12 + (6 - 2 + 12 - 4) * 0.5);
}
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/vespalib/src/tests/datastore/datastore/datastore_test.cpp b/vespalib/src/tests/datastore/datastore/datastore_test.cpp
index df347267c7e..9e27ed37dd3 100644
--- a/vespalib/src/tests/datastore/datastore/datastore_test.cpp
+++ b/vespalib/src/tests/datastore/datastore/datastore_test.cpp
@@ -26,8 +26,8 @@ public:
void holdBuffer(uint32_t bufferId) {
ParentType::holdBuffer(bufferId);
}
- void holdElem(EntryRef ref, uint64_t len) {
- ParentType::holdElem(ref, len);
+ void hold_entry(EntryRef ref) {
+ ParentType::hold_entry(ref);
}
void assign_generation(generation_t current_gen) {
ParentType::assign_generation(current_gen);
@@ -35,8 +35,8 @@ public:
void reclaim_entry_refs(generation_t oldest_used_gen) override {
ParentType::reclaim_entry_refs(oldest_used_gen);
}
- void ensureBufferCapacity(size_t sizeNeeded) {
- ParentType::ensureBufferCapacity(0, sizeNeeded);
+ void ensure_buffer_capacity(size_t entries_needed) {
+ ParentType::ensure_buffer_capacity(0, entries_needed);
}
void enableFreeLists() {
ParentType::enableFreeLists();
@@ -66,10 +66,10 @@ class GrowStore
BufferType<DataType> _type;
uint32_t _typeId;
public:
- GrowStore(size_t arraySize, size_t minArrays, size_t maxArrays, size_t numArraysForNewBuffer)
+ GrowStore(size_t arraySize, size_t min_entries, size_t max_entries, size_t num_entries_for_new_buffer)
: _store(),
- _firstType(1, 1, maxArrays, 0, ALLOC_GROW_FACTOR),
- _type(arraySize, minArrays, maxArrays, numArraysForNewBuffer, ALLOC_GROW_FACTOR),
+ _firstType(1, 1, max_entries, 0, ALLOC_GROW_FACTOR),
+ _type(arraySize, min_entries, max_entries, num_entries_for_new_buffer, ALLOC_GROW_FACTOR),
_typeId(0)
{
(void) _store.addType(&_firstType);
@@ -87,7 +87,7 @@ public:
while (sizes.size() < bufs) {
RefType iRef = (_type.getArraySize() == 1) ?
(_store.template allocator<DataType>(_typeId).alloc().ref) :
- (_store.template allocator<DataType>(_typeId).allocArray(_type.getArraySize()).ref);
+ (_store.template allocator<DataType>(_typeId).allocArray().ref);
int bufferId = iRef.bufferId();
if (bufferId != prevBufferId) {
if (prevBufferId >= 0) {
@@ -126,7 +126,7 @@ public:
while (buffers.size() < bufs) {
RefType iRef = (_type.getArraySize() == 1) ?
(_store.template allocator<DataType>(_typeId).alloc().ref) :
- (_store.template allocator<DataType>(_typeId).allocArray(_type.getArraySize()).ref);
+ (_store.template allocator<DataType>(_typeId).allocArray().ref);
int buffer_id = iRef.bufferId();
if (buffers.empty() || buffers.back() != buffer_id) {
buffers.push_back(buffer_id);
@@ -143,10 +143,10 @@ void
assertMemStats(const MemoryStats &exp,
const MemoryStats &act)
{
- EXPECT_EQ(exp._allocElems, act._allocElems);
- EXPECT_EQ(exp._usedElems, act._usedElems);
- EXPECT_EQ(exp._deadElems, act._deadElems);
- EXPECT_EQ(exp._holdElems, act._holdElems);
+ EXPECT_EQ(exp._alloc_entries, act._alloc_entries);
+ EXPECT_EQ(exp._used_entries, act._used_entries);
+ EXPECT_EQ(exp._dead_entries, act._dead_entries);
+ EXPECT_EQ(exp._hold_entries, act._hold_entries);
EXPECT_EQ(exp._freeBuffers, act._freeBuffers);
EXPECT_EQ(exp._activeBuffers, act._activeBuffers);
EXPECT_EQ(exp._holdBuffers, act._holdBuffers);
@@ -304,13 +304,13 @@ TEST(DataStoreTest, require_that_we_can_hold_and_trim_elements)
{
MyStore s;
MyRef r1 = s.addEntry(1);
- s.holdElem(r1, 1);
+ s.hold_entry(r1);
s.assign_generation(10);
MyRef r2 = s.addEntry(2);
- s.holdElem(r2, 1);
+ s.hold_entry(r2);
s.assign_generation(20);
MyRef r3 = s.addEntry(3);
- s.holdElem(r3, 1);
+ s.hold_entry(r3);
s.assign_generation(30);
EXPECT_EQ(1, s.getEntry(r1));
EXPECT_EQ(2, s.getEntry(r2));
@@ -358,11 +358,11 @@ TEST(DataStoreTest, require_that_we_can_use_free_lists)
MyStore s;
s.enableFreeLists();
auto r1 = s.addEntry(1);
- s.holdElem(r1, 1);
+ s.hold_entry(r1);
s.assign_generation(10);
auto r2 = s.addEntry(2);
expect_successive_refs(r1, r2);
- s.holdElem(r2, 1);
+ s.hold_entry(r2);
s.assign_generation(20);
s.reclaim_entry_refs(11);
auto r3 = s.addEntry(3); // reuse r1
@@ -389,21 +389,21 @@ TEST(DataStoreTest, require_that_we_can_use_free_lists_with_raw_allocator)
s.enableFreeLists();
auto allocator = s.freeListRawAllocator<int>(grow_store.typeId());
- auto h1 = allocator.alloc(3);
- auto h2 = allocator.alloc(3);
+ auto h1 = allocator.alloc(1);
+ auto h2 = allocator.alloc(1);
expect_successive_handles(h1, h2);
- s.holdElem(h1.ref, 3);
- s.holdElem(h2.ref, 3);
+ s.hold_entry(h1.ref);
+ s.hold_entry(h2.ref);
s.assign_generation(10);
s.reclaim_entry_refs(11);
- auto h3 = allocator.alloc(3); // reuse h2.ref from free list
+ auto h3 = allocator.alloc(1); // reuse h2.ref from free list
EXPECT_EQ(h2, h3);
- auto h4 = allocator.alloc(3); // reuse h1.ref from free list
+ auto h4 = allocator.alloc(1); // reuse h1.ref from free list
EXPECT_EQ(h1, h4);
- auto h5 = allocator.alloc(3);
+ auto h5 = allocator.alloc(1);
expect_successive_handles(h2, h5);
expect_successive_handles(h3, h5);
}
@@ -412,10 +412,10 @@ TEST(DataStoreTest, require_that_memory_stats_are_calculated)
{
MyStore s;
MemoryStats m;
- m._allocElems = MyRef::offsetSize();
- m._usedElems = 1; // ref = 0 is reserved
- m._deadElems = 1; // ref = 0 is reserved
- m._holdElems = 0;
+ m._alloc_entries = MyRef::offsetSize();
+ m._used_entries = 1; // ref = 0 is reserved
+ m._dead_entries = 1; // ref = 0 is reserved
+ m._hold_entries = 0;
m._activeBuffers = 1;
m._freeBuffers = MyRef::numBuffers() - 1;
m._holdBuffers = 0;
@@ -423,7 +423,7 @@ TEST(DataStoreTest, require_that_memory_stats_are_calculated)
// add entry
MyRef r = s.addEntry(10);
- m._usedElems++;
+ m._used_entries++;
assertMemStats(m, s.getMemStats());
// hold buffer
@@ -431,9 +431,9 @@ TEST(DataStoreTest, require_that_memory_stats_are_calculated)
s.addEntry(30);
s.holdBuffer(r.bufferId());
s.assign_generation(100);
- m._usedElems += 2;
- m._holdElems = m._usedElems;
- m._deadElems = 0;
+ m._used_entries += 2;
+ m._hold_entries = m._used_entries;
+ m._dead_entries = 0;
m._activeBuffers--;
m._holdBuffers++;
assertMemStats(m, s.getMemStats());
@@ -441,17 +441,17 @@ TEST(DataStoreTest, require_that_memory_stats_are_calculated)
// new active buffer
s.switch_primary_buffer();
s.addEntry(40);
- m._allocElems += MyRef::offsetSize();
- m._usedElems++;
+ m._alloc_entries += MyRef::offsetSize();
+ m._used_entries++;
m._activeBuffers++;
m._freeBuffers--;
// trim hold buffer
s.reclaim_memory(101);
- m._allocElems -= MyRef::offsetSize();
- m._usedElems = 1;
- m._deadElems = 0;
- m._holdElems = 0;
+ m._alloc_entries -= MyRef::offsetSize();
+ m._used_entries = 1;
+ m._dead_entries = 0;
+ m._hold_entries = 0;
m._freeBuffers = MyRef::numBuffers() - 1;
m._holdBuffers = 0;
assertMemStats(m, s.getMemStats());
@@ -466,7 +466,7 @@ TEST(DataStoreTest, require_that_memory_stats_are_calculated)
{ // increase extra hold bytes
auto prev_stats = s.getMemStats();
- s.get_active_buffer_state().hold_elems(0, 30);
+ s.get_active_buffer_state().hold_entries(0, 30);
auto curr_stats = s.getMemStats();
EXPECT_EQ(prev_stats._holdBytes + 30, curr_stats._holdBytes);
}
@@ -475,7 +475,7 @@ TEST(DataStoreTest, require_that_memory_stats_are_calculated)
TEST(DataStoreTest, require_that_memory_usage_is_calculated)
{
constexpr size_t BASE_ALLOCATED = 4228;
- constexpr size_t BASE_USED = 308;
+ constexpr size_t BASE_USED = 284;
MyStore s;
MyRef r = s.addEntry(10);
s.addEntry(20);
@@ -494,7 +494,7 @@ TEST(DataStoreTest, require_that_memory_usage_is_calculated)
TEST(DataStoreTest, require_that_we_can_disable_elemement_hold_list)
{
constexpr size_t BASE_ALLOCATED = 4228;
- constexpr size_t BASE_USED = 308;
+ constexpr size_t BASE_USED = 284;
MyStore s;
MyRef r1 = s.addEntry(10);
MyRef r2 = s.addEntry(20);
@@ -505,14 +505,14 @@ TEST(DataStoreTest, require_that_we_can_disable_elemement_hold_list)
EXPECT_EQ(4 * sizeof(int) + BASE_USED, m.usedBytes());
EXPECT_EQ(1 * sizeof(int), m.deadBytes());
EXPECT_EQ(0 * sizeof(int), m.allocatedBytesOnHold());
- s.holdElem(r1, 1);
+ s.hold_entry(r1);
m = s.getMemoryUsage();
EXPECT_EQ(MyRef::offsetSize() * sizeof(int) + BASE_ALLOCATED, m.allocatedBytes());
EXPECT_EQ(4 * sizeof(int) + BASE_USED, m.usedBytes());
EXPECT_EQ(1 * sizeof(int), m.deadBytes());
EXPECT_EQ(1 * sizeof(int), m.allocatedBytesOnHold());
- s.disableElemHoldList();
- s.holdElem(r2, 1);
+ s.disable_entry_hold_list();
+ s.hold_entry(r2);
m = s.getMemoryUsage();
EXPECT_EQ(MyRef::offsetSize() * sizeof(int) + BASE_ALLOCATED, m.allocatedBytes());
EXPECT_EQ(4 * sizeof(int) + BASE_USED, m.usedBytes());
@@ -529,11 +529,11 @@ namespace {
void assertGrowStats(GrowthStats expSizes,
GrowthStats expFirstBufSizes,
size_t expInitMemUsage,
- size_t minArrays, size_t numArraysForNewBuffer, size_t maxArrays = 128)
+ size_t min_entries, size_t num_entries_for_new_buffer, size_t max_entries = 128)
{
- EXPECT_EQ(expSizes, IntGrowStore(1, minArrays, maxArrays, numArraysForNewBuffer).getGrowthStats(expSizes.size()));
- EXPECT_EQ(expFirstBufSizes, IntGrowStore(1, minArrays, maxArrays, numArraysForNewBuffer).getFirstBufGrowStats());
- EXPECT_EQ(expInitMemUsage, IntGrowStore(1, minArrays, maxArrays, numArraysForNewBuffer).getMemoryUsage().allocatedBytes());
+ EXPECT_EQ(expSizes, IntGrowStore(1, min_entries, max_entries, num_entries_for_new_buffer).getGrowthStats(expSizes.size()));
+ EXPECT_EQ(expFirstBufSizes, IntGrowStore(1, min_entries, max_entries, num_entries_for_new_buffer).getFirstBufGrowStats());
+ EXPECT_EQ(expInitMemUsage, IntGrowStore(1, min_entries, max_entries, num_entries_for_new_buffer).getMemoryUsage().allocatedBytes());
}
}
@@ -574,10 +574,10 @@ namespace {
template <typename DataType>
void assertGrowStats(GrowthStats expSizes, uint32_t arraySize)
{
- uint32_t minArrays = 2048;
- uint32_t maxArrays = RefType15::offsetSize();
- uint32_t numArraysForNewBuffer = 2048;
- GrowStore<DataType, RefType15> store(arraySize, minArrays, maxArrays, numArraysForNewBuffer);
+ uint32_t min_entries = 2048;
+ uint32_t max_entries = RefType15::offsetSize();
+ uint32_t num_entries_for_new_buffer = 2048;
+ GrowStore<DataType, RefType15> store(arraySize, min_entries, max_entries, num_entries_for_new_buffer);
EXPECT_EQ(expSizes, store.getGrowthStats(expSizes.size()));
}
@@ -594,14 +594,14 @@ TEST(DataStoreTest, require_that_offset_in_EntryRefT_is_within_bounds_when_alloc
* 3) Round up bytes to alloc to match the underlying allocator (power of 2 if less than huge page size):
* After this we might end up with more bytes than the offset in EntryRef can handle. In this case this is 32768.
* 4) Cap bytes to alloc to the max offset EntryRef can handle.
- * The max bytes to alloc is: maxArrays * arraySize * elementSize.
+ * The max bytes to alloc is: max_entries * arraySize * elementSize.
*/
- assertGrowStats<uint8_t>({8192,16384,16384,65536,65536,98304,98304,98304,98304,98304,98304,98304}, 3);
- assertGrowStats<uint8_t>({16384,16384,65536,65536,131072,131072,163840,163840,163840,163840,163840,163840}, 5);
- assertGrowStats<uint8_t>({16384,32768,32768,131072,131072,229376,229376,229376,229376,229376,229376,229376}, 7);
- assertGrowStats<uint32_t>({8192,16384,16384,65536,65536,98304,98304,98304,98304,98304,98304,98304}, 3);
- assertGrowStats<uint32_t>({16384,16384,65536,65536,131072,131072,163840,163840,163840,163840,163840,163840}, 5);
- assertGrowStats<uint32_t>({16384,32768,32768,131072,131072,229376,229376,229376,229376,229376,229376,229376}, 7);
+ assertGrowStats<uint8_t>({2730,5461,5461,21845,21845,32768,32768,32768,32768,32768,32768,32768}, 3);
+ assertGrowStats<uint8_t>({3276,3276,13107,13107,26214,26214,32768,32768,32768,32768,32768,32768}, 5);
+ assertGrowStats<uint8_t>({2340,4681,4681,18724,18724,32768,32768,32768,32768,32768,32768,32768}, 7);
+ assertGrowStats<uint32_t>({2730,5461,5461,21845,21845,32768,32768,32768,32768,32768,32768,32768}, 3);
+ assertGrowStats<uint32_t>({3276,3276,13107,13107,26214,26214,32768,32768,32768,32768,32768,32768}, 5);
+ assertGrowStats<uint32_t>({2340,4681,4681,18724,18724,32768,32768,32768,32768,32768,32768,32768}, 7);
}
namespace {
@@ -667,9 +667,9 @@ TEST(DataStoreTest, can_reuse_active_buffer_as_primary_buffer)
TEST(DataStoreTest, control_static_sizes) {
EXPECT_EQ(88, sizeof(BufferTypeBase));
EXPECT_EQ(24, sizeof(FreeList));
- EXPECT_EQ(56, sizeof(BufferFreeList));
+ EXPECT_EQ(48, sizeof(BufferFreeList));
EXPECT_EQ(1, sizeof(BufferState::State));
- EXPECT_EQ(144, sizeof(BufferState));
+ EXPECT_EQ(120, sizeof(BufferState));
BufferState bs;
EXPECT_EQ(0, bs.size());
}
@@ -685,11 +685,11 @@ void test_free_element_to_held_buffer(bool before_hold_buffer)
EXPECT_EQ(1u, s.primary_buffer_id());
if (before_hold_buffer) {
- s.holdElem(ref, 1);
+ s.hold_entry(ref);
}
s.holdBuffer(0); // hold last buffer
if (!before_hold_buffer) {
- ASSERT_DEATH({ s.holdElem(ref, 1); }, "isActive\\(\\)");
+ ASSERT_DEATH({ s.hold_entry(ref); }, "isActive\\(\\)");
}
s.assign_generation(100);
s.reclaim_memory(101);
diff --git a/vespalib/src/tests/datastore/free_list/free_list_test.cpp b/vespalib/src/tests/datastore/free_list/free_list_test.cpp
index 44e11b2316b..ec14d0dd28c 100644
--- a/vespalib/src/tests/datastore/free_list/free_list_test.cpp
+++ b/vespalib/src/tests/datastore/free_list/free_list_test.cpp
@@ -8,20 +8,18 @@
using namespace vespalib::datastore;
using MyEntryRef = EntryRefT<8, 4>;
-constexpr uint32_t array_size = 6;
struct FreeListTest : public testing::Test
{
FreeList list;
- std::atomic<ElemCount> dead_elems;
+ std::atomic<EntryCount> dead_entries;
std::vector<BufferFreeList> bufs;
FreeListTest()
: list(),
bufs()
{
for (size_t i = 0; i < 3; ++i) {
- bufs.emplace_back(dead_elems);
- bufs.back().set_array_size(array_size);
+ bufs.emplace_back(dead_entries);
}
}
void TearDown() override {
@@ -126,13 +124,13 @@ TEST_F(FreeListTest, buffer_free_list_can_be_disabled_and_detached_when_not_curr
EXPECT_TRUE(list.empty());
}
-TEST_F(FreeListTest, dead_elems_count_is_updated_when_popping_an_entry)
+TEST_F(FreeListTest, dead_entries_count_is_updated_when_popping_an_entry)
{
enable(0);
push_entry({10, 0});
- dead_elems.store(18, std::memory_order_relaxed);
+ dead_entries.store(18, std::memory_order_relaxed);
pop_entry();
- EXPECT_EQ(18 - array_size, dead_elems.load(std::memory_order_relaxed));
+ EXPECT_EQ(17, dead_entries.load(std::memory_order_relaxed));
}
GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp
index 5ccf9a8908c..a09a7213bf5 100644
--- a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp
+++ b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp
@@ -96,8 +96,8 @@ struct TestBase : public ::testing::Test {
}
void assertBufferState(EntryRef ref, const TestBufferStats expStats) const {
EXPECT_EQ(expStats._used, store.bufferState(ref).size());
- EXPECT_EQ(expStats._hold, store.bufferState(ref).stats().hold_elems());
- EXPECT_EQ(expStats._dead, store.bufferState(ref).stats().dead_elems());
+ EXPECT_EQ(expStats._hold, store.bufferState(ref).stats().hold_entries());
+ EXPECT_EQ(expStats._dead, store.bufferState(ref).stats().dead_entries());
}
void assertStoreContent() const {
for (const auto &elem : refStore) {
@@ -147,10 +147,7 @@ struct TestBase : public ::testing::Test {
auto getBuilder(uint32_t uniqueValuesHint) { return store.getBuilder(uniqueValuesHint); }
auto getEnumerator(bool sort_unique_values) { return store.getEnumerator(sort_unique_values); }
size_t get_reserved(EntryRef ref) {
- return store.bufferState(ref).getTypeHandler()->getReservedElements(getBufferId(ref));
- }
- size_t get_array_size(EntryRef ref) {
- return store.bufferState(ref).getArraySize();
+ return store.bufferState(ref).getTypeHandler()->get_reserved_entries(getBufferId(ref));
}
};
@@ -309,29 +306,27 @@ TYPED_TEST(TestBase, can_add_and_get_values)
}
}
-TYPED_TEST(TestBase, elements_are_put_on_hold_when_value_is_removed)
+TYPED_TEST(TestBase, entries_are_put_on_hold_when_value_is_removed)
{
EntryRef ref = this->add(this->values()[0]);
size_t reserved = this->get_reserved(ref);
- size_t array_size = this->get_array_size(ref);
- this->assertBufferState(ref, TestBufferStats().used(array_size + reserved).hold(0).dead(reserved));
+ this->assertBufferState(ref, TestBufferStats().used(1 + reserved).hold(0).dead(reserved));
this->store.remove(ref);
- this->assertBufferState(ref, TestBufferStats().used(array_size + reserved).hold(array_size).dead(reserved));
+ this->assertBufferState(ref, TestBufferStats().used(1 + reserved).hold(1).dead(reserved));
}
-TYPED_TEST(TestBase, elements_are_reference_counted)
+TYPED_TEST(TestBase, entries_are_reference_counted)
{
EntryRef ref = this->add(this->values()[0]);
EntryRef ref2 = this->add(this->values()[0]);
EXPECT_EQ(ref.ref(), ref2.ref());
- // Note: The first buffer have the first element reserved -> we expect 2 elements used here.
+ // Note: The first buffer have the first entry reserved -> we expect 2 entries used here.
size_t reserved = this->get_reserved(ref);
- size_t array_size = this->get_array_size(ref);
- this->assertBufferState(ref, TestBufferStats().used(array_size + reserved).hold(0).dead(reserved));
+ this->assertBufferState(ref, TestBufferStats().used(1 + reserved).hold(0).dead(reserved));
this->store.remove(ref);
- this->assertBufferState(ref, TestBufferStats().used(array_size + reserved).hold(0).dead(reserved));
+ this->assertBufferState(ref, TestBufferStats().used(1 + reserved).hold(0).dead(reserved));
this->store.remove(ref);
- this->assertBufferState(ref, TestBufferStats().used(array_size + reserved).hold(array_size).dead(reserved));
+ this->assertBufferState(ref, TestBufferStats().used(1 + reserved).hold(1).dead(reserved));
}
TEST_F(SmallOffsetNumberTest, new_underlying_buffer_is_allocated_when_current_is_full)
@@ -360,8 +355,7 @@ TYPED_TEST(TestBase, store_can_be_compacted)
this->remove(this->add(this->values()[2]));
this->reclaim_memory();
size_t reserved = this->get_reserved(val0Ref);
- size_t array_size = this->get_array_size(val0Ref);
- this->assertBufferState(val0Ref, TestBufferStats().used(reserved + 3 * array_size).dead(reserved + array_size));
+ this->assertBufferState(val0Ref, TestBufferStats().used(reserved + 3).dead(reserved + 1));
uint32_t val1BufferId = this->getBufferId(val0Ref);
EXPECT_EQ(2u, this->refStore.size());
@@ -389,8 +383,7 @@ TYPED_TEST(TestBase, store_can_be_instantiated_with_builder)
EntryRef val0Ref = builder.mapEnumValueToEntryRef(1);
EntryRef val1Ref = builder.mapEnumValueToEntryRef(2);
size_t reserved = this->get_reserved(val0Ref);
- size_t array_size = this->get_array_size(val0Ref);
- this->assertBufferState(val0Ref, TestBufferStats().used(2 * array_size + reserved).dead(reserved)); // Note: First element is reserved
+ this->assertBufferState(val0Ref, TestBufferStats().used(2 + reserved).dead(reserved)); // Note: First entry is reserved
EXPECT_TRUE(val0Ref.valid());
EXPECT_TRUE(val1Ref.valid());
EXPECT_NE(val0Ref.ref(), val1Ref.ref());
@@ -472,13 +465,13 @@ TEST_F(DoubleTest, nan_is_handled)
TEST_F(DoubleTest, control_memory_usage) {
static constexpr size_t sizeof_deque = vespalib::datastore::DataStoreBase::sizeof_entry_ref_hold_list_deque;
EXPECT_EQ(368u + sizeof_deque, sizeof(store));
- EXPECT_EQ(144u, sizeof(BufferState));
+ EXPECT_EQ(120u, sizeof(BufferState));
EXPECT_EQ(28740u, store.get_values_memory_usage().allocatedBytes());
- EXPECT_EQ(24804u, store.get_values_memory_usage().usedBytes());
+ EXPECT_EQ(24780u, store.get_values_memory_usage().usedBytes());
EXPECT_EQ(126952u, store.get_dictionary_memory_usage().allocatedBytes());
- EXPECT_EQ(25248u, store.get_dictionary_memory_usage().usedBytes());
+ EXPECT_EQ(25200u, store.get_dictionary_memory_usage().usedBytes());
EXPECT_EQ(155692u, store.getMemoryUsage().allocatedBytes());
- EXPECT_EQ(50052, store.getMemoryUsage().usedBytes());
+ EXPECT_EQ(49980u, store.getMemoryUsage().usedBytes());
}
GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/vespalib/src/tests/datastore/unique_store_string_allocator/unique_store_string_allocator_test.cpp b/vespalib/src/tests/datastore/unique_store_string_allocator/unique_store_string_allocator_test.cpp
index 7d4451556c8..8ea7f807f56 100644
--- a/vespalib/src/tests/datastore/unique_store_string_allocator/unique_store_string_allocator_test.cpp
+++ b/vespalib/src/tests/datastore/unique_store_string_allocator/unique_store_string_allocator_test.cpp
@@ -62,8 +62,8 @@ struct TestBase : public ::testing::Test {
void assert_buffer_state(EntryRef ref, const TestBufferStats expStats) {
auto & stats = buffer_state(ref).stats();
EXPECT_EQ(expStats._used, buffer_state(ref).size());
- EXPECT_EQ(expStats._hold, stats.hold_elems());
- EXPECT_EQ(expStats._dead, stats.dead_elems());
+ EXPECT_EQ(expStats._hold, stats.hold_entries());
+ EXPECT_EQ(expStats._dead, stats.dead_entries());
EXPECT_EQ(expStats._extra_used, stats.extra_used_bytes());
EXPECT_EQ(expStats._extra_hold, stats.extra_hold_bytes());
}
@@ -83,14 +83,14 @@ TEST_F(StringTest, can_add_and_get_values)
assert_add(spaces1000.c_str());
}
-TEST_F(StringTest, elements_are_put_on_hold_when_value_is_removed)
+TEST_F(StringTest, entries_are_put_on_hold_when_value_is_removed)
{
EntryRef ref = add(small.c_str());
- assert_buffer_state(ref, TestBufferStats().used(16).hold(0).dead(0));
+ assert_buffer_state(ref, TestBufferStats().used(1).hold(0).dead(0));
remove(ref);
- assert_buffer_state(ref, TestBufferStats().used(16).hold(16).dead(0));
+ assert_buffer_state(ref, TestBufferStats().used(1).hold(1).dead(0));
reclaim_memory();
- assert_buffer_state(ref, TestBufferStats().used(16).hold(0).dead(16));
+ assert_buffer_state(ref, TestBufferStats().used(1).hold(0).dead(1));
}
TEST_F(StringTest, extra_bytes_used_is_tracked)
@@ -139,7 +139,7 @@ TEST_F(StringTest, free_list_is_used_when_enabled)
EntryRef ref4 = add(spaces1000.c_str());
EXPECT_EQ(ref1, ref3);
EXPECT_EQ(ref2, ref4);
- assert_buffer_state(ref1, TestBufferStats().used(16).hold(0).dead(0));
+ assert_buffer_state(ref1, TestBufferStats().used(1).hold(0).dead(0));
assert_buffer_state(ref2, TestBufferStats().used(2).hold(0).dead(1).extra_used(1001));
}
@@ -155,7 +155,7 @@ TEST_F(StringTest, free_list_is_not_used_when_disabled)
EntryRef ref4 = add(spaces1000.c_str());
EXPECT_NE(ref1, ref3);
EXPECT_NE(ref2, ref4);
- assert_buffer_state(ref1, TestBufferStats().used(32).hold(0).dead(16));
+ assert_buffer_state(ref1, TestBufferStats().used(2).hold(0).dead(1));
assert_buffer_state(ref2, TestBufferStats().used(3).hold(0).dead(2).extra_used(1001));
}
@@ -173,7 +173,7 @@ TEST_F(StringTest, free_list_is_never_used_for_move_on_compact)
EntryRef ref6 = move_on_compact(ref2);
EXPECT_NE(ref5, ref3);
EXPECT_NE(ref6, ref4);
- assert_buffer_state(ref1, TestBufferStats().used(48).hold(0).dead(16));
+ assert_buffer_state(ref1, TestBufferStats().used(3).hold(0).dead(1));
assert_buffer_state(ref2, TestBufferStats().used(4).hold(0).dead(2).extra_used(2002));
}
diff --git a/vespalib/src/tests/signalhandler/CMakeLists.txt b/vespalib/src/tests/signalhandler/CMakeLists.txt
index 4f78eb2e82d..88be14f994f 100644
--- a/vespalib/src/tests/signalhandler/CMakeLists.txt
+++ b/vespalib/src/tests/signalhandler/CMakeLists.txt
@@ -5,6 +5,11 @@ vespa_add_library(vespalib_signalhandler_test_my_shared_library TEST
DEPENDS
vespalib
)
+
+# Don't convert call to jump when returning a value from a function with
+# a compatible stack.
+set_source_files_properties(my_shared_library.cpp PROPERTIES COMPILE_OPTIONS "-fno-optimize-sibling-calls")
+
vespa_add_executable(vespalib_signalhandler_test_app TEST
SOURCES
signalhandler_test.cpp
diff --git a/vespalib/src/vespa/vespalib/btree/btree.h b/vespalib/src/vespa/vespalib/btree/btree.h
index 32b538b65ec..c2f5aac01b7 100644
--- a/vespalib/src/vespa/vespalib/btree/btree.h
+++ b/vespalib/src/vespa/vespalib/btree/btree.h
@@ -61,9 +61,9 @@ public:
}
void
- disableElemHoldList()
+ disable_entry_hold_list()
{
- _alloc.disableElemHoldList();
+ _alloc.disable_entry_hold_list();
}
// Inherit doc from BTreeRoot
diff --git a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h
index 784e95e3817..b537602c703 100644
--- a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h
+++ b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h
@@ -60,8 +60,8 @@ public:
_nodeStore.disableFreeLists();
}
- void disableElemHoldList() {
- _nodeStore.disableElemHoldList();
+ void disable_entry_hold_list() {
+ _nodeStore.disable_entry_hold_list();
}
/**
diff --git a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp
index a38b68afe73..d23c8fc2054 100644
--- a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp
+++ b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp
@@ -162,7 +162,7 @@ holdNode(BTreeNode::Ref nodeRef,
InternalNodeType *node)
{
if (node->getFrozen()) {
- _nodeStore.holdElem(nodeRef);
+ _nodeStore.hold_entry(nodeRef);
} else {
node->clean();
_internalHoldUntilFreeze.push_back(nodeRef);
@@ -178,7 +178,7 @@ holdNode(BTreeNode::Ref nodeRef,
LeafNodeType *node)
{
if (node->getFrozen()) {
- _nodeStore.holdElem(nodeRef);
+ _nodeStore.hold_entry(nodeRef);
} else {
node->clean();
_leafHoldUntilFreeze.push_back(nodeRef);
@@ -235,7 +235,7 @@ freeze()
InternalNodeType *inode = mapInternalRef(i);
(void) inode;
assert(inode->getFrozen());
- _nodeStore.holdElem(i);
+ _nodeStore.hold_entry(i);
}
_internalHoldUntilFreeze.clear();
}
@@ -245,7 +245,7 @@ freeze()
LeafNodeType *lnode = mapLeafRef(i);
(void) lnode;
assert(lnode->getFrozen());
- _nodeStore.holdElem(i);
+ _nodeStore.hold_entry(i);
}
_leafHoldUntilFreeze.clear();
}
diff --git a/vespalib/src/vespa/vespalib/btree/btreenodestore.h b/vespalib/src/vespa/vespalib/btree/btreenodestore.h
index c59092bf75c..38bf4e5ed4e 100644
--- a/vespalib/src/vespa/vespalib/btree/btreenodestore.h
+++ b/vespalib/src/vespa/vespalib/btree/btreenodestore.h
@@ -29,16 +29,16 @@ class BTreeNodeBufferType : public datastore::BufferType<EntryType, FrozenBtreeN
using ParentType = datastore::BufferType<EntryType, FrozenBtreeNode<EntryType>>;
using ParentType::empty_entry;
using ParentType::_arraySize;
- using ElemCount = typename ParentType::ElemCount;
+ using EntryCount = typename ParentType::EntryCount;
using CleanContext = typename ParentType::CleanContext;
public:
- BTreeNodeBufferType(uint32_t minArrays, uint32_t maxArrays)
- : ParentType(1, minArrays, maxArrays)
+ BTreeNodeBufferType(uint32_t min_entries, uint32_t max_entries)
+ : ParentType(1, min_entries, max_entries)
{ }
- void initializeReservedElements(void *buffer, ElemCount reservedElements) override;
+ void initialize_reserved_entries(void *buffer, EntryCount reserved_entries) override;
- void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
+ void clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
};
@@ -79,7 +79,7 @@ public:
~BTreeNodeStore();
void disableFreeLists() { _store.disableFreeLists(); }
- void disableElemHoldList() { _store.disableElemHoldList(); }
+ void disable_entry_hold_list() { _store.disable_entry_hold_list(); }
static bool isValidRef(EntryRef ref) { return ref.valid(); }
@@ -152,8 +152,8 @@ public:
return _store.freeListAllocator<InternalNodeType, BTreeNodeReclaimer>(NODETYPE_INTERNAL).alloc(rhs);
}
- void holdElem(EntryRef ref) {
- _store.holdElem(ref, 1);
+ void hold_entry(EntryRef ref) {
+ _store.hold_entry(ref);
}
std::unique_ptr<vespalib::datastore::CompactingBuffers> start_compact_worst(const CompactionStrategy& compaction_strategy);
diff --git a/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp b/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp
index a1ffb4d445d..99054f35d61 100644
--- a/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp
+++ b/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp
@@ -11,11 +11,11 @@ namespace vespalib::btree {
template <typename EntryType>
void
-BTreeNodeBufferType<EntryType>::initializeReservedElements(void *buffer, ElemCount reservedElements)
+BTreeNodeBufferType<EntryType>::initialize_reserved_entries(void *buffer, EntryCount reserved_entries)
{
- ParentType::initializeReservedElements(buffer, reservedElements);
+ ParentType::initialize_reserved_entries(buffer, reserved_entries);
EntryType *e = static_cast<EntryType *>(buffer);
- for (size_t j = reservedElements; j != 0; --j) {
+ for (size_t j = reserved_entries; j != 0; --j) {
e->freeze();
++e;
}
@@ -24,10 +24,10 @@ BTreeNodeBufferType<EntryType>::initializeReservedElements(void *buffer, ElemCou
template <typename EntryType>
void
-BTreeNodeBufferType<EntryType>::cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext)
+BTreeNodeBufferType<EntryType>::clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext)
{
EntryType *e = static_cast<EntryType *>(buffer) + offset;
- for (size_t j = numElems; j != 0; --j) {
+ for (size_t j = num_entries; j != 0; --j) {
e->cleanFrozen();
++e;
}
diff --git a/vespalib/src/vespa/vespalib/btree/btreestore.h b/vespalib/src/vespa/vespalib/btree/btreestore.h
index 9fdade850f1..7dd839f1529 100644
--- a/vespalib/src/vespa/vespalib/btree/btreestore.h
+++ b/vespalib/src/vespa/vespalib/btree/btreestore.h
@@ -50,8 +50,8 @@ public:
using CompactionSpec = datastore::CompactionSpec;
using CompactionStrategy = datastore::CompactionStrategy;
using EntryRef = datastore::EntryRef;
- template <typename EntryType>
- using BufferType = datastore::BufferType<EntryType>;
+ template <typename ElemT>
+ using BufferType = datastore::BufferType<ElemT>;
using BufferState = datastore::BufferState;
static constexpr uint32_t clusterLimit = 8;
@@ -105,9 +105,9 @@ public:
_allocator.disableFreeLists();
}
- void disableElemHoldList() {
- _store.disableElemHoldList();
- _allocator.disableElemHoldList();
+ void disable_entry_hold_list() {
+ _store.disable_entry_hold_list();
+ _allocator.disable_entry_hold_list();
}
BTreeTypeRefPair allocNewBTree() {
diff --git a/vespalib/src/vespa/vespalib/btree/btreestore.hpp b/vespalib/src/vespa/vespalib/btree/btreestore.hpp
index a19d0b34aa6..90c302af5e4 100644
--- a/vespalib/src/vespa/vespalib/btree/btreestore.hpp
+++ b/vespalib/src/vespa/vespalib/btree/btreestore.hpp
@@ -74,7 +74,7 @@ allocNewKeyData(uint32_t clusterSize)
{
assert(clusterSize >= 1 && clusterSize <= clusterLimit);
uint32_t typeId = clusterSize - 1;
- return _store.allocator<KeyDataType>(typeId).allocArray(clusterSize);
+ return _store.allocator<KeyDataType>(typeId).allocArray();
}
@@ -87,7 +87,7 @@ allocKeyData(uint32_t clusterSize)
{
assert(clusterSize >= 1 && clusterSize <= clusterLimit);
uint32_t typeId = clusterSize - 1;
- return _store.freeListAllocator<KeyDataType, datastore::DefaultReclaimer<KeyDataType>>(typeId).allocArray(clusterSize);
+ return _store.freeListAllocator<KeyDataType, datastore::DefaultReclaimer<KeyDataType>>(typeId).allocArray();
}
@@ -156,7 +156,7 @@ makeTree(EntryRef &ref,
lNode->freeze();
BTreeTypeRefPair tPair(allocBTree());
tPair.data->setRoots(lPair.ref);
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
ref = tPair.ref;
}
@@ -176,7 +176,7 @@ makeArray(EntryRef &ref, EntryRef root, LeafNodeType *leafNode)
kd->setData(leafNode->getData(idx));
}
assert(kd == kPair.data + clusterSize);
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
if (!leafNode->getFrozen()) {
leafNode->freeze();
}
@@ -255,7 +255,7 @@ insert(EntryRef &ref,
kd->setData(i->getData());
}
assert(kd == kPair.data + clusterSize + 1);
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
ref = kPair.ref;
return true;
}
@@ -284,7 +284,7 @@ insert(EntryRef &ref,
lNode->freeze();
BTreeTypeRefPair tPair(allocBTree());
tPair.data->setRoots(lPair.ref); // allow immediate access to readers
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
ref = tPair.ref;
return true;
#endif
@@ -339,7 +339,7 @@ remove(EntryRef &ref,
if (oldi == olde || comp(key, oldi->_key))
return false; // not found
if (clusterSize == 1) {
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
ref = EntryRef();
return true;
}
@@ -357,7 +357,7 @@ remove(EntryRef &ref,
kd->setData(i->getData());
}
assert(kd == kPair.data + clusterSize - 1);
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
ref = kPair.ref;
return true;
}
@@ -670,7 +670,7 @@ applyCluster(EntryRef &ref,
if (newSizeMin <= clusterLimit) {
uint32_t newSize = getNewClusterSize(ob, oe, a, ae, r, re, comp);
if (newSize == 0) {
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
ref = EntryRef();
return true;
}
@@ -678,7 +678,7 @@ applyCluster(EntryRef &ref,
KeyDataTypeRefPair kPair(allocKeyData(newSize));
applyCluster(ob, oe, kPair.data, kPair.data + newSize,
a, ae, r, re, comp);
- _store.holdElem(ref, clusterSize);
+ _store.hold_entry(ref);
ref = kPair.ref;
return true;
}
@@ -735,7 +735,7 @@ normalizeTree(EntryRef &ref,
{
EntryRef root = tree->getRoot();
if (!NodeAllocatorType::isValidRef(root)) {
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
ref = EntryRef();
return;
}
@@ -798,10 +798,8 @@ clear(const EntryRef ref)
if (clusterSize == 0) {
BTreeType *tree = getWTreeEntry(iRef);
tree->clear(_allocator);
- _store.holdElem(ref, 1);
- } else {
- _store.holdElem(ref, clusterSize);
}
+ _store.hold_entry(ref);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/allocator.h b/vespalib/src/vespa/vespalib/datastore/allocator.h
index 297270af0f5..30938bdc1c1 100644
--- a/vespalib/src/vespa/vespalib/datastore/allocator.h
+++ b/vespalib/src/vespa/vespalib/datastore/allocator.h
@@ -30,7 +30,7 @@ public:
HandleType alloc(Args && ... args);
HandleType allocArray(ConstArrayRef array);
- HandleType allocArray(size_t size);
+ HandleType allocArray();
};
}
diff --git a/vespalib/src/vespa/vespalib/datastore/allocator.hpp b/vespalib/src/vespa/vespalib/datastore/allocator.hpp
index 85f0e842519..fa97ef9a5f5 100644
--- a/vespalib/src/vespa/vespalib/datastore/allocator.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/allocator.hpp
@@ -20,7 +20,7 @@ template <typename ... Args>
typename Allocator<EntryT, RefT>::HandleType
Allocator<EntryT, RefT>::alloc(Args && ... args)
{
- _store.ensureBufferCapacity(_typeId, 1);
+ _store.ensure_buffer_capacity(_typeId, 1);
uint32_t buffer_id = _store.primary_buffer_id(_typeId);
BufferState &state = _store.getBufferState(buffer_id);
assert(state.isActive());
@@ -36,39 +36,35 @@ template <typename EntryT, typename RefT>
typename Allocator<EntryT, RefT>::HandleType
Allocator<EntryT, RefT>::allocArray(ConstArrayRef array)
{
- _store.ensureBufferCapacity(_typeId, array.size());
+ _store.ensure_buffer_capacity(_typeId, 1);
uint32_t buffer_id = _store.primary_buffer_id(_typeId);
BufferState &state = _store.getBufferState(buffer_id);
assert(state.isActive());
assert(state.getArraySize() == array.size());
- size_t oldBufferSize = state.size();
- assert((oldBufferSize % array.size()) == 0);
- RefT ref((oldBufferSize / array.size()), buffer_id);
+ RefT ref(state.size(), buffer_id);
EntryT *buf = _store.template getEntryArray<EntryT>(ref, array.size());
for (size_t i = 0; i < array.size(); ++i) {
new (static_cast<void *>(buf + i)) EntryT(array[i]);
}
- state.stats().pushed_back(array.size());
+ state.stats().pushed_back(1);
return HandleType(ref, buf);
}
template <typename EntryT, typename RefT>
typename Allocator<EntryT, RefT>::HandleType
-Allocator<EntryT, RefT>::allocArray(size_t size)
+Allocator<EntryT, RefT>::allocArray()
{
- _store.ensureBufferCapacity(_typeId, size);
+ _store.ensure_buffer_capacity(_typeId, 1);
uint32_t buffer_id = _store.primary_buffer_id(_typeId);
BufferState &state = _store.getBufferState(buffer_id);
assert(state.isActive());
- assert(state.getArraySize() == size);
- size_t oldBufferSize = state.size();
- assert((oldBufferSize % size) == 0);
- RefT ref((oldBufferSize / size), buffer_id);
- EntryT *buf = _store.template getEntryArray<EntryT>(ref, size);
- for (size_t i = 0; i < size; ++i) {
+ RefT ref(state.size(), buffer_id);
+ auto array_size = state.getArraySize();
+ EntryT *buf = _store.template getEntryArray<EntryT>(ref, array_size);
+ for (size_t i = 0; i < array_size; ++i) {
new (static_cast<void *>(buf + i)) EntryT();
}
- state.stats().pushed_back(size);
+ state.stats().pushed_back(1);
return HandleType(ref, buf);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/array_store.h b/vespalib/src/vespa/vespalib/datastore/array_store.h
index c2b65d72f03..809ac10f6e3 100644
--- a/vespalib/src/vespa/vespalib/datastore/array_store.h
+++ b/vespalib/src/vespa/vespalib/datastore/array_store.h
@@ -19,7 +19,7 @@
namespace vespalib::datastore {
/**
- * Datastore for storing arrays of type EntryT that is accessed via a 32-bit EntryRef.
+ * Datastore for storing arrays of type ElemT that is accessed via a 32-bit EntryRef.
*
* The default EntryRef type uses 19 bits for offset (524288 values) and 13 bits for buffer id (8192 buffers).
*
@@ -29,16 +29,18 @@ namespace vespalib::datastore {
*
* The max value of maxSmallArrayTypeId is (2^bufferBits - 1).
*/
-template <typename EntryT, typename RefT = EntryRefT<19>, typename TypeMapperT = ArrayStoreSimpleTypeMapper<EntryT> >
+template <typename ElemT, typename RefT = EntryRefT<19>, typename TypeMapperT = ArrayStoreSimpleTypeMapper<ElemT> >
class ArrayStore : public ICompactable
{
public:
using AllocSpec = ArrayStoreConfig::AllocSpec;
- using ArrayRef = vespalib::ArrayRef<EntryT>;
- using ConstArrayRef = vespalib::ConstArrayRef<EntryT>;
+ using ArrayRef = vespalib::ArrayRef<ElemT>;
+ using ConstArrayRef = vespalib::ConstArrayRef<ElemT>;
using DataStoreType = DataStoreT<RefT>;
- using LargeArray = vespalib::Array<EntryT>;
+ using ElemType = ElemT;
+ using LargeArray = vespalib::Array<ElemT>;
using LargeBufferType = typename TypeMapperT::LargeBufferType;
+ using RefType = RefT;
using SmallBufferType = typename TypeMapperT::SmallBufferType;
using TypeMapper = TypeMapperT;
private:
@@ -58,7 +60,7 @@ private:
EntryRef addLargeArray(const ConstArrayRef &array);
EntryRef allocate_large_array(size_t array_size);
ConstArrayRef getSmallArray(RefT ref, size_t arraySize) const {
- const EntryT *buf = _store.template getEntryArray<EntryT>(ref, arraySize);
+ const ElemT *buf = _store.template getEntryArray<ElemT>(ref, arraySize);
return ConstArrayRef(buf, arraySize);
}
ConstArrayRef getLargeArray(RefT ref) const {
@@ -85,7 +87,7 @@ public:
}
/**
- * Allocate an array of the given size without any instantiation of EntryT elements.
+ * Allocate an array of the given size without any instantiation of ElemT elements.
*
* Use get_writable() to get a reference to the array for writing.
*
@@ -148,14 +150,14 @@ public:
static ArrayStoreConfig optimizedConfigForHugePage(uint32_t maxSmallArrayTypeId,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor);
static ArrayStoreConfig optimizedConfigForHugePage(uint32_t maxSmallArrayTypeId,
const TypeMapper& mapper,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor);
};
diff --git a/vespalib/src/vespa/vespalib/datastore/array_store.hpp b/vespalib/src/vespa/vespalib/datastore/array_store.hpp
index 301cff1e414..8e9fe779ba9 100644
--- a/vespalib/src/vespa/vespalib/datastore/array_store.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/array_store.hpp
@@ -15,9 +15,9 @@
namespace vespalib::datastore {
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
void
-ArrayStore<EntryT, RefT, TypeMapperT>::initArrayTypes(const ArrayStoreConfig &cfg, std::shared_ptr<alloc::MemoryAllocator> memory_allocator)
+ArrayStore<ElemT, RefT, TypeMapperT>::initArrayTypes(const ArrayStoreConfig &cfg, std::shared_ptr<alloc::MemoryAllocator> memory_allocator)
{
_largeArrayTypeId = _store.addType(&_largeArrayType);
assert(_largeArrayTypeId == 0);
@@ -31,14 +31,14 @@ ArrayStore<EntryT, RefT, TypeMapperT>::initArrayTypes(const ArrayStoreConfig &cf
}
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
-ArrayStore<EntryT, RefT, TypeMapperT>::ArrayStore(const ArrayStoreConfig &cfg, std::shared_ptr<alloc::MemoryAllocator> memory_allocator)
+template <typename ElemT, typename RefT, typename TypeMapperT>
+ArrayStore<ElemT, RefT, TypeMapperT>::ArrayStore(const ArrayStoreConfig &cfg, std::shared_ptr<alloc::MemoryAllocator> memory_allocator)
: ArrayStore(cfg, memory_allocator, TypeMapper())
{
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
-ArrayStore<EntryT, RefT, TypeMapperT>::ArrayStore(const ArrayStoreConfig &cfg, std::shared_ptr<alloc::MemoryAllocator> memory_allocator,
+template <typename ElemT, typename RefT, typename TypeMapperT>
+ArrayStore<ElemT, RefT, TypeMapperT>::ArrayStore(const ArrayStoreConfig &cfg, std::shared_ptr<alloc::MemoryAllocator> memory_allocator,
TypeMapper&& mapper)
: _largeArrayTypeId(0),
_maxSmallArrayTypeId(cfg.maxSmallArrayTypeId()),
@@ -56,25 +56,25 @@ ArrayStore<EntryT, RefT, TypeMapperT>::ArrayStore(const ArrayStoreConfig &cfg, s
}
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
vespalib::MemoryUsage
-ArrayStore<EntryT, RefT, TypeMapperT>::getMemoryUsage() const {
+ArrayStore<ElemT, RefT, TypeMapperT>::getMemoryUsage() const {
vespalib::MemoryUsage usage = _store.getMemoryUsage();
usage.incAllocatedBytes(_smallArrayTypes.capacity() * sizeof(SmallBufferType));
usage.incUsedBytes(_smallArrayTypes.size() * sizeof(SmallBufferType));
return usage;
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
-ArrayStore<EntryT, RefT, TypeMapperT>::~ArrayStore()
+template <typename ElemT, typename RefT, typename TypeMapperT>
+ArrayStore<ElemT, RefT, TypeMapperT>::~ArrayStore()
{
_store.reclaim_all_memory();
_store.dropBuffers();
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
EntryRef
-ArrayStore<EntryT, RefT, TypeMapperT>::add(const ConstArrayRef &array)
+ArrayStore<ElemT, RefT, TypeMapperT>::add(const ConstArrayRef &array)
{
if (array.size() == 0) {
return EntryRef();
@@ -86,9 +86,9 @@ ArrayStore<EntryT, RefT, TypeMapperT>::add(const ConstArrayRef &array)
}
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
EntryRef
-ArrayStore<EntryT, RefT, TypeMapperT>::allocate(size_t array_size)
+ArrayStore<ElemT, RefT, TypeMapperT>::allocate(size_t array_size)
{
if (array_size == 0) {
return EntryRef();
@@ -100,94 +100,93 @@ ArrayStore<EntryT, RefT, TypeMapperT>::allocate(size_t array_size)
}
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
EntryRef
-ArrayStore<EntryT, RefT, TypeMapperT>::addSmallArray(const ConstArrayRef &array)
+ArrayStore<ElemT, RefT, TypeMapperT>::addSmallArray(const ConstArrayRef &array)
{
uint32_t typeId = _mapper.get_type_id(array.size());
- using NoOpReclaimer = DefaultReclaimer<EntryT>;
- return _store.template freeListAllocator<EntryT, NoOpReclaimer>(typeId).allocArray(array).ref;
+ using NoOpReclaimer = DefaultReclaimer<ElemT>;
+ return _store.template freeListAllocator<ElemT, NoOpReclaimer>(typeId).allocArray(array).ref;
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
EntryRef
-ArrayStore<EntryT, RefT, TypeMapperT>::allocate_small_array(size_t array_size)
+ArrayStore<ElemT, RefT, TypeMapperT>::allocate_small_array(size_t array_size)
{
uint32_t type_id = _mapper.get_type_id(array_size);
- return _store.template freeListRawAllocator<EntryT>(type_id).alloc(array_size).ref;
+ return _store.template freeListRawAllocator<ElemT>(type_id).alloc(1).ref;
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
EntryRef
-ArrayStore<EntryT, RefT, TypeMapperT>::addLargeArray(const ConstArrayRef &array)
+ArrayStore<ElemT, RefT, TypeMapperT>::addLargeArray(const ConstArrayRef &array)
{
using NoOpReclaimer = DefaultReclaimer<LargeArray>;
auto handle = _store.template freeListAllocator<LargeArray, NoOpReclaimer>(_largeArrayTypeId)
.alloc(array.cbegin(), array.cend());
auto& state = _store.getBufferState(RefT(handle.ref).bufferId());
- state.stats().inc_extra_used_bytes(sizeof(EntryT) * array.size());
+ state.stats().inc_extra_used_bytes(sizeof(ElemT) * array.size());
return handle.ref;
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
EntryRef
-ArrayStore<EntryT, RefT, TypeMapperT>::allocate_large_array(size_t array_size)
+ArrayStore<ElemT, RefT, TypeMapperT>::allocate_large_array(size_t array_size)
{
using NoOpReclaimer = DefaultReclaimer<LargeArray>;
auto handle = _store.template freeListAllocator<LargeArray, NoOpReclaimer>(_largeArrayTypeId).alloc(array_size);
auto& state = _store.getBufferState(RefT(handle.ref).bufferId());
- state.stats().inc_extra_used_bytes(sizeof(EntryT) * array_size);
+ state.stats().inc_extra_used_bytes(sizeof(ElemT) * array_size);
return handle.ref;
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
void
-ArrayStore<EntryT, RefT, TypeMapperT>::remove(EntryRef ref)
+ArrayStore<ElemT, RefT, TypeMapperT>::remove(EntryRef ref)
{
if (ref.valid()) {
RefT internalRef(ref);
uint32_t typeId = _store.getTypeId(internalRef.bufferId());
if (typeId != _largeArrayTypeId) {
- size_t arraySize = _mapper.get_array_size(typeId);
- _store.holdElem(ref, arraySize);
+ _store.hold_entry(ref);
} else {
- _store.holdElem(ref, 1, sizeof(EntryT) * get(ref).size());
+ _store.hold_entry(ref, sizeof(ElemT) * get(ref).size());
}
}
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
EntryRef
-ArrayStore<EntryT, RefT, TypeMapperT>::move_on_compact(EntryRef ref)
+ArrayStore<ElemT, RefT, TypeMapperT>::move_on_compact(EntryRef ref)
{
return add(get(ref));
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
ICompactionContext::UP
-ArrayStore<EntryT, RefT, TypeMapperT>::compact_worst(const CompactionStrategy &compaction_strategy)
+ArrayStore<ElemT, RefT, TypeMapperT>::compact_worst(const CompactionStrategy &compaction_strategy)
{
auto compacting_buffers = _store.start_compact_worst_buffers(_compaction_spec, compaction_strategy);
return std::make_unique<CompactionContext>(*this, std::move(compacting_buffers));
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
std::unique_ptr<CompactingBuffers>
-ArrayStore<EntryT, RefT, TypeMapperT>::start_compact_worst_buffers(const CompactionStrategy &compaction_strategy)
+ArrayStore<ElemT, RefT, TypeMapperT>::start_compact_worst_buffers(const CompactionStrategy &compaction_strategy)
{
return _store.start_compact_worst_buffers(_compaction_spec, compaction_strategy);
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
vespalib::AddressSpace
-ArrayStore<EntryT, RefT, TypeMapperT>::addressSpaceUsage() const
+ArrayStore<ElemT, RefT, TypeMapperT>::addressSpaceUsage() const
{
return _store.getAddressSpaceUsage();
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
vespalib::MemoryUsage
-ArrayStore<EntryT, RefT, TypeMapperT>::update_stat(const CompactionStrategy& compaction_strategy)
+ArrayStore<ElemT, RefT, TypeMapperT>::update_stat(const CompactionStrategy& compaction_strategy)
{
auto address_space_usage = _store.getAddressSpaceUsage();
auto memory_usage = getMemoryUsage();
@@ -195,20 +194,20 @@ ArrayStore<EntryT, RefT, TypeMapperT>::update_stat(const CompactionStrategy& com
return memory_usage;
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
const BufferState &
-ArrayStore<EntryT, RefT, TypeMapperT>::bufferState(EntryRef ref)
+ArrayStore<ElemT, RefT, TypeMapperT>::bufferState(EntryRef ref)
{
RefT internalRef(ref);
return _store.getBufferState(internalRef.bufferId());
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
ArrayStoreConfig
-ArrayStore<EntryT, RefT, TypeMapperT>::optimizedConfigForHugePage(uint32_t maxSmallArrayTypeId,
+ArrayStore<ElemT, RefT, TypeMapperT>::optimizedConfigForHugePage(uint32_t maxSmallArrayTypeId,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor)
{
TypeMapper mapper;
@@ -216,26 +215,26 @@ ArrayStore<EntryT, RefT, TypeMapperT>::optimizedConfigForHugePage(uint32_t maxSm
mapper,
hugePageSize,
smallPageSize,
- minNumArraysForNewBuffer,
+ min_num_entries_for_new_buffer,
allocGrowFactor);
}
-template <typename EntryT, typename RefT, typename TypeMapperT>
+template <typename ElemT, typename RefT, typename TypeMapperT>
ArrayStoreConfig
-ArrayStore<EntryT, RefT, TypeMapperT>::optimizedConfigForHugePage(uint32_t maxSmallArrayTypeId,
+ArrayStore<ElemT, RefT, TypeMapperT>::optimizedConfigForHugePage(uint32_t maxSmallArrayTypeId,
const TypeMapper& mapper,
size_t hugePageSize,
size_t smallPageSize,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor)
{
return ArrayStoreConfig::optimizeForHugePage(mapper.get_max_small_array_type_id(maxSmallArrayTypeId),
[&](uint32_t type_id) noexcept { return mapper.get_array_size(type_id); },
hugePageSize,
smallPageSize,
- sizeof(EntryT),
+ sizeof(ElemT),
RefT::offsetSize(),
- minNumArraysForNewBuffer,
+ min_num_entries_for_new_buffer,
allocGrowFactor);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/array_store_config.cpp b/vespalib/src/vespa/vespalib/datastore/array_store_config.cpp
index d5587841745..1df9354cd6c 100644
--- a/vespalib/src/vespa/vespalib/datastore/array_store_config.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/array_store_config.cpp
@@ -49,19 +49,19 @@ ArrayStoreConfig::optimizeForHugePage(uint32_t maxSmallArrayTypeId,
std::function<size_t(uint32_t)> type_id_to_array_size,
size_t hugePageSize,
size_t smallPageSize,
- size_t entrySize,
+ size_t elem_size,
size_t maxEntryRefOffset,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor)
{
AllocSpecVector allocSpecs;
- allocSpecs.emplace_back(0, maxEntryRefOffset, minNumArraysForNewBuffer, allocGrowFactor); // large array spec;
+ allocSpecs.emplace_back(0, maxEntryRefOffset, min_num_entries_for_new_buffer, allocGrowFactor); // large array spec;
for (uint32_t type_id = 1; type_id <= maxSmallArrayTypeId; ++type_id) {
size_t arraySize = type_id_to_array_size(type_id);
- size_t numArraysForNewBuffer = hugePageSize / (entrySize * arraySize);
- numArraysForNewBuffer = capToLimits(numArraysForNewBuffer, minNumArraysForNewBuffer, maxEntryRefOffset);
- numArraysForNewBuffer = alignToSmallPageSize(numArraysForNewBuffer, minNumArraysForNewBuffer, smallPageSize);
- allocSpecs.emplace_back(0, maxEntryRefOffset, numArraysForNewBuffer, allocGrowFactor);
+ size_t num_entries_for_new_buffer = hugePageSize / (elem_size * arraySize);
+ num_entries_for_new_buffer = capToLimits(num_entries_for_new_buffer, min_num_entries_for_new_buffer, maxEntryRefOffset);
+ num_entries_for_new_buffer = alignToSmallPageSize(num_entries_for_new_buffer, min_num_entries_for_new_buffer, smallPageSize);
+ allocSpecs.emplace_back(0, maxEntryRefOffset, num_entries_for_new_buffer, allocGrowFactor);
}
return ArrayStoreConfig(allocSpecs);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/array_store_config.h b/vespalib/src/vespa/vespalib/datastore/array_store_config.h
index a326c00d042..cae241dba10 100644
--- a/vespalib/src/vespa/vespalib/datastore/array_store_config.h
+++ b/vespalib/src/vespa/vespalib/datastore/array_store_config.h
@@ -19,21 +19,21 @@ public:
* Specification of buffer allocation strategy for arrays of a given size.
*/
struct AllocSpec {
- // Minimum number of arrays to allocate in a buffer.
- size_t minArraysInBuffer;
- // Maximum number of arrays to allocate in a buffer.
- size_t maxArraysInBuffer;
- // Number of arrays needed before allocating a new buffer instead of just resizing the first one.
- size_t numArraysForNewBuffer;
+ // Minimum number of entries to allocate in a buffer.
+ size_t min_entries_in_buffer;
+ // Maximum number of entries to allocate in a buffer.
+ size_t max_entries_in_buffer;
+ // Number of entries needed before allocating a new buffer instead of just resizing the first one.
+ size_t num_entries_for_new_buffer;
// Grow factor used when allocating a new buffer.
float allocGrowFactor;
- AllocSpec(size_t minArraysInBuffer_,
- size_t maxArraysInBuffer_,
- size_t numArraysForNewBuffer_,
+ AllocSpec(size_t min_entries_in_buffer_,
+ size_t max_entries_in_buffer_,
+ size_t num_entries_for_new_buffer_,
float allocGrowFactor_) noexcept
- : minArraysInBuffer(minArraysInBuffer_),
- maxArraysInBuffer(maxArraysInBuffer_),
- numArraysForNewBuffer(numArraysForNewBuffer_),
+ : min_entries_in_buffer(min_entries_in_buffer_),
+ max_entries_in_buffer(max_entries_in_buffer_),
+ num_entries_for_new_buffer(num_entries_for_new_buffer_),
allocGrowFactor(allocGrowFactor_) {}
};
@@ -76,9 +76,9 @@ public:
std::function<size_t(uint32_t)> type_id_to_array_size,
size_t hugePageSize,
size_t smallPageSize,
- size_t entrySize,
+ size_t elem_size,
size_t maxEntryRefOffset,
- size_t minNumArraysForNewBuffer,
+ size_t min_num_entries_for_new_buffer,
float allocGrowFactor);
};
diff --git a/vespalib/src/vespa/vespalib/datastore/array_store_simple_type_mapper.h b/vespalib/src/vespa/vespalib/datastore/array_store_simple_type_mapper.h
index a0cd7827b2d..5f9728a43cc 100644
--- a/vespalib/src/vespa/vespalib/datastore/array_store_simple_type_mapper.h
+++ b/vespalib/src/vespa/vespalib/datastore/array_store_simple_type_mapper.h
@@ -15,11 +15,11 @@ namespace vespalib::datastore {
*
* A more complex mapping can be used by creating a custom mapper and BufferType implementations.
*/
-template <typename EntryT>
+template <typename ElemT>
class ArrayStoreSimpleTypeMapper {
public:
- using SmallBufferType = SmallArrayBufferType<EntryT>;
- using LargeBufferType = LargeArrayBufferType<EntryT>;
+ using SmallBufferType = SmallArrayBufferType<ElemT>;
+ using LargeBufferType = LargeArrayBufferType<ElemT>;
uint32_t get_type_id(size_t array_size) const { return array_size; }
size_t get_array_size(uint32_t type_id) const { return type_id; }
diff --git a/vespalib/src/vespa/vespalib/datastore/array_store_type_mapper.h b/vespalib/src/vespa/vespalib/datastore/array_store_type_mapper.h
index e707627de19..2a406a39bf9 100644
--- a/vespalib/src/vespa/vespalib/datastore/array_store_type_mapper.h
+++ b/vespalib/src/vespa/vespalib/datastore/array_store_type_mapper.h
@@ -12,7 +12,7 @@ namespace vespalib::datastore {
* This class provides mapping between type ids and array sizes needed for
* storing a value with size smaller than or equal to the array size.
*
- * The array sizes vector is a monotic increasing sequence that might end
+ * The array sizes vector is a monotonic strictly increasing sequence that might end
* with exponential growth.
*/
class ArrayStoreTypeMapper
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp
index 224ed4b0c8f..851db0222c2 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp
@@ -20,9 +20,8 @@ BufferFreeList::detach()
_free_list->detach(*this);
}
-BufferFreeList::BufferFreeList(std::atomic<ElemCount>& dead_elems)
- : _dead_elems(dead_elems),
- _array_size(0),
+BufferFreeList::BufferFreeList(std::atomic<EntryCount>& dead_entries)
+ : _dead_entries(dead_entries),
_free_list(),
_free_refs()
{
@@ -66,7 +65,7 @@ BufferFreeList::pop_entry() {
if (empty()) {
detach();
}
- _dead_elems.store(_dead_elems.load(std::memory_order_relaxed) - _array_size, std::memory_order_relaxed);
+ _dead_entries.store(_dead_entries.load(std::memory_order_relaxed) - 1, std::memory_order_relaxed);
return ret;
}
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h
index 148ddd8db88..4348a41af04 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h
@@ -19,8 +19,7 @@ class BufferFreeList {
private:
using EntryRefArray = vespalib::Array<EntryRef>;
- std::atomic<ElemCount>& _dead_elems;
- uint32_t _array_size;
+ std::atomic<EntryCount>& _dead_entries;
FreeList* _free_list;
EntryRefArray _free_refs;
@@ -28,7 +27,7 @@ private:
void detach();
public:
- BufferFreeList(std::atomic<ElemCount>& dead_elems);
+ BufferFreeList(std::atomic<EntryCount>& dead_entrie);
~BufferFreeList();
BufferFreeList(BufferFreeList&&) = default; // Needed for emplace_back() during setup.
BufferFreeList(const BufferFreeList&) = delete;
@@ -37,10 +36,8 @@ public:
void enable(FreeList& free_list);
void disable();
- void set_array_size(uint32_t value) { _array_size = value; }
bool enabled() const { return _free_list != nullptr; }
bool empty() const { return _free_refs.empty(); }
- uint32_t array_size() const { return _array_size; }
void push_entry(EntryRef ref);
EntryRef pop_entry();
};
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp b/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp
index 8d97414626e..0d96e3f6d47 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp
@@ -6,27 +6,27 @@
namespace vespalib::datastore {
BufferStats::BufferStats()
- : _alloc_elems(0),
- _used_elems(0),
- _hold_elems(0),
- _dead_elems(0),
+ : _alloc_entries(0),
+ _used_entries(0),
+ _hold_entries(0),
+ _dead_entries(0),
_extra_used_bytes(0),
_extra_hold_bytes(0)
{
}
void
-BufferStats::add_to_mem_stats(size_t element_size, MemoryStats& stats) const
+BufferStats::add_to_mem_stats(size_t entry_size, MemoryStats& stats) const
{
size_t extra_used = extra_used_bytes();
- stats._allocElems += capacity();
- stats._usedElems += size();
- stats._deadElems += dead_elems();
- stats._holdElems += hold_elems();
- stats._allocBytes += (capacity() * element_size) + extra_used;
- stats._usedBytes += (size() * element_size) + extra_used;
- stats._deadBytes += dead_elems() * element_size;
- stats._holdBytes += (hold_elems() * element_size) + extra_hold_bytes();
+ stats._alloc_entries += capacity();
+ stats._used_entries += size();
+ stats._dead_entries += dead_entries();
+ stats._hold_entries += hold_entries();
+ stats._allocBytes += (capacity() * entry_size) + extra_used;
+ stats._usedBytes += (size() * entry_size) + extra_used;
+ stats._deadBytes += dead_entries() * entry_size;
+ stats._holdBytes += (hold_entries() * entry_size) + extra_hold_bytes();
}
InternalBufferStats::InternalBufferStats()
@@ -37,20 +37,20 @@ InternalBufferStats::InternalBufferStats()
void
InternalBufferStats::clear()
{
- _alloc_elems.store(0, std::memory_order_relaxed);
- _used_elems.store(0, std::memory_order_relaxed);
- _hold_elems.store(0, std::memory_order_relaxed);
- _dead_elems.store(0, std::memory_order_relaxed);
+ _alloc_entries.store(0, std::memory_order_relaxed);
+ _used_entries.store(0, std::memory_order_relaxed);
+ _hold_entries.store(0, std::memory_order_relaxed);
+ _dead_entries.store(0, std::memory_order_relaxed);
_extra_used_bytes.store(0, std::memory_order_relaxed);
_extra_hold_bytes.store(0, std::memory_order_relaxed);
}
void
-InternalBufferStats::dec_hold_elems(size_t value)
+InternalBufferStats::dec_hold_entries(size_t value)
{
- ElemCount elems = hold_elems();
+ EntryCount elems = hold_entries();
assert(elems >= value);
- _hold_elems.store(elems - value, std::memory_order_relaxed);
+ _hold_entries.store(elems - value, std::memory_order_relaxed);
}
}
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_stats.h b/vespalib/src/vespa/vespalib/datastore/buffer_stats.h
index 66f8b532c41..1974efa97ec 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_stats.h
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_stats.h
@@ -13,16 +13,16 @@ namespace vespalib::datastore {
*/
class BufferStats {
protected:
- // The number of elements that are allocated in the buffer.
- std::atomic<ElemCount> _alloc_elems;
- // The number of elements (of the allocated) that are used: _used_elems <= _alloc_elems.
- std::atomic<ElemCount> _used_elems;
- // The number of elements (of the used) that are on hold: _hold_elems <= _used_elems.
- // "On hold" is a transitionary state used when removing elements.
- std::atomic<ElemCount> _hold_elems;
- // The number of elements (of the used) that are dead: _dead_elems <= _used_elems.
- // A dead element was first on hold, and is now available for reuse in the free list (if enabled).
- std::atomic<ElemCount> _dead_elems;
+ // The number of entries that are allocated in the buffer.
+ std::atomic<EntryCount> _alloc_entries;
+ // The number of entries (of the allocated) that are used: _used_entries <= _alloc_entries.
+ std::atomic<EntryCount> _used_entries;
+ // The number of entries (of the used) that are on hold: _hold_entries <= _used_entries.
+ // "On hold" is a transitionary state used when removing entries.
+ std::atomic<EntryCount> _hold_entries;
+ // The number of entries (of the used) that are dead: _dead_entries <= _used_entries.
+ // A dead entry was first on hold, and is now available for reuse in the free list (if enabled).
+ std::atomic<EntryCount> _dead_entries;
// Number of bytes that are heap allocated (and used) by elements that are stored in this buffer.
// For simple types this is always 0.
@@ -34,22 +34,22 @@ protected:
public:
BufferStats();
- size_t size() const { return _used_elems.load(std::memory_order_relaxed); }
- size_t capacity() const { return _alloc_elems.load(std::memory_order_relaxed); }
+ size_t size() const { return _used_entries.load(std::memory_order_relaxed); }
+ size_t capacity() const { return _alloc_entries.load(std::memory_order_relaxed); }
size_t remaining() const { return capacity() - size(); }
- void pushed_back(size_t num_elems) {
- _used_elems.store(size() + num_elems, std::memory_order_relaxed);
+ void pushed_back(size_t num_entries) {
+ _used_entries.store(size() + num_entries, std::memory_order_relaxed);
}
- size_t dead_elems() const { return _dead_elems.load(std::memory_order_relaxed); }
- size_t hold_elems() const { return _hold_elems.load(std::memory_order_relaxed); }
+ size_t dead_entries() const { return _dead_entries.load(std::memory_order_relaxed); }
+ size_t hold_entries() const { return _hold_entries.load(std::memory_order_relaxed); }
size_t extra_used_bytes() const { return _extra_used_bytes.load(std::memory_order_relaxed); }
size_t extra_hold_bytes() const { return _extra_hold_bytes.load(std::memory_order_relaxed); }
void inc_extra_used_bytes(size_t value) { _extra_used_bytes.store(extra_used_bytes() + value, std::memory_order_relaxed); }
- void add_to_mem_stats(size_t element_size, MemoryStats& stats) const;
+ void add_to_mem_stats(size_t entry_size, MemoryStats& stats) const;
};
/**
@@ -59,15 +59,15 @@ class InternalBufferStats : public BufferStats {
public:
InternalBufferStats();
void clear();
- void set_alloc_elems(size_t value) { _alloc_elems.store(value, std::memory_order_relaxed); }
- void set_dead_elems(size_t value) { _dead_elems.store(value, std::memory_order_relaxed); }
- void set_hold_elems(size_t value) { _hold_elems.store(value, std::memory_order_relaxed); }
- void inc_dead_elems(size_t value) { _dead_elems.store(dead_elems() + value, std::memory_order_relaxed); }
- void inc_hold_elems(size_t value) { _hold_elems.store(hold_elems() + value, std::memory_order_relaxed); }
- void dec_hold_elems(size_t value);
+ void set_alloc_entries(size_t value) { _alloc_entries.store(value, std::memory_order_relaxed); }
+ void set_dead_entries(size_t value) { _dead_entries.store(value, std::memory_order_relaxed); }
+ void set_hold_entries(size_t value) { _hold_entries.store(value, std::memory_order_relaxed); }
+ void inc_dead_entries(size_t value) { _dead_entries.store(dead_entries() + value, std::memory_order_relaxed); }
+ void inc_hold_entries(size_t value) { _hold_entries.store(hold_entries() + value, std::memory_order_relaxed); }
+ void dec_hold_entries(size_t value);
void inc_extra_hold_bytes(size_t value) { _extra_hold_bytes.store(extra_hold_bytes() + value, std::memory_order_relaxed); }
- std::atomic<ElemCount>& used_elems_ref() { return _used_elems; }
- std::atomic<ElemCount>& dead_elems_ref() { return _dead_elems; }
+ std::atomic<EntryCount>& used_entries_ref() { return _used_entries; }
+ std::atomic<EntryCount>& dead_entries_ref() { return _dead_entries; }
std::atomic<size_t>& extra_used_bytes_ref() { return _extra_used_bytes; }
std::atomic<size_t>& extra_hold_bytes_ref() { return _extra_hold_bytes; }
};
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp b/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp
index 4a9ba2d33a8..0d43ede9e62 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp
@@ -27,85 +27,85 @@ BufferTypeBase::CleanContext::extraBytesCleaned(size_t value)
}
BufferTypeBase::BufferTypeBase(uint32_t arraySize,
- uint32_t minArrays,
- uint32_t maxArrays,
- uint32_t numArraysForNewBuffer,
+ uint32_t min_entries,
+ uint32_t max_entries,
+ uint32_t num_entries_for_new_buffer,
float allocGrowFactor) noexcept
: _arraySize(arraySize),
- _minArrays(std::min(minArrays, maxArrays)),
- _maxArrays(maxArrays),
- _numArraysForNewBuffer(std::min(numArraysForNewBuffer, maxArrays)),
+ _min_entries(std::min(min_entries, max_entries)),
+ _max_entries(max_entries),
+ _num_entries_for_new_buffer(std::min(num_entries_for_new_buffer, max_entries)),
_allocGrowFactor(allocGrowFactor),
_holdBuffers(0),
- _holdUsedElems(0),
+ _hold_used_entries(0),
_aggr_counts(),
_active_buffers()
{
}
BufferTypeBase::BufferTypeBase(uint32_t arraySize,
- uint32_t minArrays,
- uint32_t maxArrays) noexcept
- : BufferTypeBase(arraySize, minArrays, maxArrays, 0u, DEFAULT_ALLOC_GROW_FACTOR)
+ uint32_t min_entries,
+ uint32_t max_entries) noexcept
+ : BufferTypeBase(arraySize, min_entries, max_entries, 0u, DEFAULT_ALLOC_GROW_FACTOR)
{
}
BufferTypeBase::~BufferTypeBase()
{
assert(_holdBuffers == 0);
- assert(_holdUsedElems == 0);
+ assert(_hold_used_entries == 0);
assert(_aggr_counts.empty());
assert(_active_buffers.empty());
}
-ElemCount
-BufferTypeBase::getReservedElements(uint32_t bufferId) const
+EntryCount
+BufferTypeBase::get_reserved_entries(uint32_t bufferId) const
{
- return bufferId == 0 ? _arraySize : 0u;
+ return bufferId == 0 ? 1u : 0u;
}
void
-BufferTypeBase::onActive(uint32_t bufferId, std::atomic<ElemCount>* usedElems, std::atomic<ElemCount>* deadElems, void* buffer)
+BufferTypeBase::on_active(uint32_t bufferId, std::atomic<EntryCount>* used_entries, std::atomic<EntryCount>* dead_entries, void* buffer)
{
- _aggr_counts.add_buffer(usedElems, deadElems);
+ _aggr_counts.add_buffer(used_entries, dead_entries);
assert(std::find(_active_buffers.begin(), _active_buffers.end(), bufferId) == _active_buffers.end());
_active_buffers.emplace_back(bufferId);
- size_t reservedElems = getReservedElements(bufferId);
- if (reservedElems != 0u) {
- initializeReservedElements(buffer, reservedElems);
- *usedElems = reservedElems;
- *deadElems = reservedElems;
+ auto reserved_entries = get_reserved_entries(bufferId);
+ if (reserved_entries != 0u) {
+ initialize_reserved_entries(buffer, reserved_entries);
+ *used_entries = reserved_entries;
+ *dead_entries = reserved_entries;
}
}
void
-BufferTypeBase::onHold(uint32_t buffer_id, const std::atomic<ElemCount>* usedElems, const std::atomic<ElemCount>* deadElems)
+BufferTypeBase::on_hold(uint32_t buffer_id, const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries)
{
++_holdBuffers;
auto itr = std::find(_active_buffers.begin(), _active_buffers.end(), buffer_id);
assert(itr != _active_buffers.end());
_active_buffers.erase(itr);
- _aggr_counts.remove_buffer(usedElems, deadElems);
- _holdUsedElems += *usedElems;
+ _aggr_counts.remove_buffer(used_entries, dead_entries);
+ _hold_used_entries += *used_entries;
}
void
-BufferTypeBase::onFree(ElemCount usedElems)
+BufferTypeBase::on_free(EntryCount used_entries)
{
--_holdBuffers;
- assert(_holdUsedElems >= usedElems);
- _holdUsedElems -= usedElems;
+ assert(_hold_used_entries >= used_entries);
+ _hold_used_entries -= used_entries;
}
void
-BufferTypeBase::resume_primary_buffer(uint32_t buffer_id, std::atomic<ElemCount>* used_elems, std::atomic<ElemCount>* dead_elems)
+BufferTypeBase::resume_primary_buffer(uint32_t buffer_id, std::atomic<EntryCount>* used_entries, std::atomic<EntryCount>* dead_entries)
{
auto itr = std::find(_active_buffers.begin(), _active_buffers.end(), buffer_id);
assert(itr != _active_buffers.end());
_active_buffers.erase(itr);
_active_buffers.emplace_back(buffer_id);
- _aggr_counts.remove_buffer(used_elems, dead_elems);
- _aggr_counts.add_buffer(used_elems, dead_elems);
+ _aggr_counts.remove_buffer(used_entries, dead_entries);
+ _aggr_counts.add_buffer(used_entries, dead_entries);
}
const alloc::MemoryAllocator*
@@ -115,17 +115,17 @@ BufferTypeBase::get_memory_allocator() const
}
void
-BufferTypeBase::clampMaxArrays(uint32_t maxArrays)
+BufferTypeBase::clamp_max_entries(uint32_t max_entries)
{
- _maxArrays = std::min(_maxArrays, maxArrays);
- _minArrays = std::min(_minArrays, _maxArrays);
- _numArraysForNewBuffer = std::min(_numArraysForNewBuffer, _maxArrays);
+ _max_entries = std::min(_max_entries, max_entries);
+ _min_entries = std::min(_min_entries, _max_entries);
+ _num_entries_for_new_buffer = std::min(_num_entries_for_new_buffer, _max_entries);
}
size_t
-BufferTypeBase::calcArraysToAlloc(uint32_t bufferId, ElemCount elemsNeeded, bool resizing) const
+BufferTypeBase::calc_entries_to_alloc(uint32_t bufferId, EntryCount free_entries_needed, bool resizing) const
{
- size_t reservedElems = getReservedElements(bufferId);
+ size_t reserved_entries = get_reserved_entries(bufferId);
BufferCounts last_bc;
BufferCounts bc;
if (resizing) {
@@ -134,56 +134,53 @@ BufferTypeBase::calcArraysToAlloc(uint32_t bufferId, ElemCount elemsNeeded, bool
}
}
bc = _aggr_counts.all_buffers();
- assert((bc.used_elems % _arraySize) == 0);
- assert((bc.dead_elems % _arraySize) == 0);
- assert(bc.used_elems >= bc.dead_elems);
- size_t neededArrays = (elemsNeeded + (resizing ? last_bc.used_elems : reservedElems) + _arraySize - 1) / _arraySize;
-
- size_t liveArrays = (bc.used_elems - bc.dead_elems) / _arraySize;
- size_t growArrays = (liveArrays * _allocGrowFactor);
- size_t usedArrays = last_bc.used_elems / _arraySize;
- size_t wantedArrays = std::max((resizing ? usedArrays : 0u) + growArrays,
- static_cast<size_t>(_minArrays));
-
- size_t result = wantedArrays;
- if (result < neededArrays) {
- result = neededArrays;
+ assert(bc.used_entries >= bc.dead_entries);
+ size_t needed_entries = static_cast<size_t>(free_entries_needed) + (resizing ? last_bc.used_entries : reserved_entries);
+ size_t live_entries = (bc.used_entries - bc.dead_entries);
+ size_t grow_entries = (live_entries * _allocGrowFactor);
+ size_t used_entries = last_bc.used_entries;
+ size_t wanted_entries = std::max((resizing ? used_entries : 0u) + grow_entries,
+ static_cast<size_t>(_min_entries));
+
+ size_t result = wanted_entries;
+ if (result < needed_entries) {
+ result = needed_entries;
}
- if (result > _maxArrays) {
- result = _maxArrays;
+ if (result > _max_entries) {
+ result = _max_entries;
}
- if (result < neededArrays) {
+ if (result < needed_entries) {
vespalib::asciistream s;
s << "BufferTypeBase::calcArraysToAlloc(" <<
"bufferId=" << bufferId <<
- ",elemsNeeeded=" << elemsNeeded <<
+ ",free_entries_needed=" << free_entries_needed <<
",resizing=" << (resizing ? "true" : "false") << ")" <<
- " wantedArrays=" << wantedArrays <<
+ " wanted_entries=" << wanted_entries <<
", _arraySize=" << _arraySize <<
- ", _maxArrays=" << _maxArrays <<
- ", reservedElems=" << reservedElems <<
- ", liveArrays=" << liveArrays <<
- ", growArrays=" << growArrays <<
- ", usedArrays=" << usedArrays <<
+ ", _max_entries=" << _max_entries <<
+ ", reserved_entries=" << reserved_entries <<
+ ", live_entries=" << live_entries <<
+ ", grow_entries=" << grow_entries <<
+ ", used_entries=" << used_entries <<
", typeid(*this).name=\"" << typeid(*this).name() << "\"" <<
- ", newArrays=" << result <<
- " < neededArrays=" << neededArrays;;
+ ", new_entries=" << result <<
+ " < needed_entries=" << needed_entries;
throw vespalib::OverflowException(s.c_str());
}
return result;
}
uint32_t
-BufferTypeBase::get_scaled_num_arrays_for_new_buffer() const
+BufferTypeBase::get_scaled_num_entries_for_new_buffer() const
{
uint32_t active_buffers_count = get_active_buffers_count();
- if (active_buffers_count <= 1u || _numArraysForNewBuffer == 0u) {
- return _numArraysForNewBuffer;
+ if (active_buffers_count <= 1u || _num_entries_for_new_buffer == 0u) {
+ return _num_entries_for_new_buffer;
}
double scale_factor = std::pow(1.0 + _allocGrowFactor, active_buffers_count - 1);
- double scaled_result = _numArraysForNewBuffer * scale_factor;
- if (scaled_result >= _maxArrays) {
- return _maxArrays;
+ double scaled_result = _num_entries_for_new_buffer * scale_factor;
+ if (scaled_result >= _max_entries) {
+ return _max_entries;
}
return scaled_result;
}
@@ -194,22 +191,22 @@ BufferTypeBase::AggregatedBufferCounts::AggregatedBufferCounts()
}
void
-BufferTypeBase::AggregatedBufferCounts::add_buffer(const std::atomic<ElemCount>* used_elems, const std::atomic<ElemCount>* dead_elems)
+BufferTypeBase::AggregatedBufferCounts::add_buffer(const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries)
{
for (const auto& elem : _counts) {
- assert(elem.used_ptr != used_elems);
- assert(elem.dead_ptr != dead_elems);
+ assert(elem.used_ptr != used_entries);
+ assert(elem.dead_ptr != dead_entries);
}
- _counts.emplace_back(used_elems, dead_elems);
+ _counts.emplace_back(used_entries, dead_entries);
}
void
-BufferTypeBase::AggregatedBufferCounts::remove_buffer(const std::atomic<ElemCount>* used_elems, const std::atomic<ElemCount>* dead_elems)
+BufferTypeBase::AggregatedBufferCounts::remove_buffer(const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries)
{
auto itr = std::find_if(_counts.begin(), _counts.end(),
- [=](const auto& elem){ return elem.used_ptr == used_elems; });
+ [=](const auto& elem){ return elem.used_ptr == used_entries; });
assert(itr != _counts.end());
- assert(itr->dead_ptr == dead_elems);
+ assert(itr->dead_ptr == dead_entries);
_counts.erase(itr);
}
@@ -219,8 +216,8 @@ BufferTypeBase::AggregatedBufferCounts::last_buffer() const
BufferCounts result;
assert(!_counts.empty());
const auto& last = _counts.back();
- result.used_elems += last.used_ptr->load(std::memory_order_relaxed);
- result.dead_elems += last.dead_ptr->load(std::memory_order_relaxed);
+ result.used_entries += last.used_ptr->load(std::memory_order_relaxed);
+ result.dead_entries += last.dead_ptr->load(std::memory_order_relaxed);
return result;
}
@@ -229,8 +226,8 @@ BufferTypeBase::AggregatedBufferCounts::all_buffers() const
{
BufferCounts result;
for (const auto& elem : _counts) {
- result.used_elems += elem.used_ptr->load(std::memory_order_relaxed);
- result.dead_elems += elem.dead_ptr->load(std::memory_order_relaxed);
+ result.used_entries += elem.used_ptr->load(std::memory_order_relaxed);
+ result.dead_entries += elem.dead_ptr->load(std::memory_order_relaxed);
}
return result;
}
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_type.h b/vespalib/src/vespa/vespalib/datastore/buffer_type.h
index bedbb2c984e..ea52b026228 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_type.h
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_type.h
@@ -10,7 +10,7 @@ namespace vespalib::alloc { class MemoryAllocator; }
namespace vespalib::datastore {
-using ElemCount = uint64_t;
+using EntryCount = uint32_t;
/**
* Abstract class used to manage allocation and de-allocation of a specific data type in underlying memory buffers in a data store.
@@ -22,7 +22,7 @@ using ElemCount = uint64_t;
class BufferTypeBase
{
public:
- using ElemCount = vespalib::datastore::ElemCount;
+ using EntryCount = vespalib::datastore::EntryCount;
class CleanContext {
private:
std::atomic<size_t> &_extraUsedBytes;
@@ -39,53 +39,52 @@ public:
BufferTypeBase & operator=(const BufferTypeBase &rhs) = delete;
BufferTypeBase(BufferTypeBase &&rhs) noexcept = default;
BufferTypeBase & operator=(BufferTypeBase &&rhs) noexcept = default;
- BufferTypeBase(uint32_t arraySize, uint32_t minArrays, uint32_t maxArrays) noexcept;
- BufferTypeBase(uint32_t arraySize, uint32_t minArrays, uint32_t maxArrays,
- uint32_t numArraysForNewBuffer, float allocGrowFactor) noexcept;
+ BufferTypeBase(uint32_t arraySize, uint32_t min_entries, uint32_t max_entries) noexcept;
+ BufferTypeBase(uint32_t arraySize, uint32_t min_entries, uint32_t max_entries,
+ uint32_t num_entries_for_new_buffer, float allocGrowFactor) noexcept;
virtual ~BufferTypeBase();
- virtual void destroyElements(void *buffer, ElemCount numElems) = 0;
- virtual void fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems) = 0;
+ virtual void destroy_entries(void *buffer, EntryCount num_entries) = 0;
+ virtual void fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries) = 0;
/**
- * Return number of reserved elements at start of buffer, to avoid
- * invalid reference and handle data at negative offset (alignment
- * hacks) as used by dense tensor store.
+ * Return number of reserved entries at start of buffer, to avoid
+ * invalid reference.
*/
- virtual ElemCount getReservedElements(uint32_t bufferId) const;
+ virtual EntryCount get_reserved_entries(uint32_t bufferId) const;
/**
* Initialize reserved elements at start of buffer.
*/
- virtual void initializeReservedElements(void *buffer, ElemCount reservedElements) = 0;
- virtual size_t elementSize() const = 0;
- virtual void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) = 0;
+ virtual void initialize_reserved_entries(void *buffer, EntryCount reserved_entries) = 0;
+ virtual size_t entry_size() const = 0; // Size of entry measured in bytes
+ virtual void clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) = 0;
size_t getArraySize() const { return _arraySize; }
- virtual void onActive(uint32_t bufferId, std::atomic<ElemCount>* usedElems, std::atomic<ElemCount>* deadElems, void* buffer);
- void onHold(uint32_t buffer_id, const std::atomic<ElemCount>* usedElems, const std::atomic<ElemCount>* deadElems);
- virtual void onFree(ElemCount usedElems);
- void resume_primary_buffer(uint32_t buffer_id, std::atomic<ElemCount>* used_elems, std::atomic<ElemCount>* dead_elems);
+ virtual void on_active(uint32_t bufferId, std::atomic<EntryCount>* used_entries, std::atomic<EntryCount>* dead_entries, void* buffer);
+ void on_hold(uint32_t buffer_id, const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries);
+ virtual void on_free(EntryCount used_entries);
+ void resume_primary_buffer(uint32_t buffer_id, std::atomic<EntryCount>* used_entries, std::atomic<EntryCount>* dead_entries);
virtual const alloc::MemoryAllocator* get_memory_allocator() const;
/**
- * Calculate number of arrays to allocate for new buffer given how many elements are needed.
+ * Calculate number of entries to allocate for new buffer given how many free entries are needed.
*/
- virtual size_t calcArraysToAlloc(uint32_t bufferId, ElemCount elementsNeeded, bool resizing) const;
+ virtual size_t calc_entries_to_alloc(uint32_t bufferId, EntryCount free_entries_needed, bool resizing) const;
- void clampMaxArrays(uint32_t maxArrays);
+ void clamp_max_entries(uint32_t max_entries);
uint32_t get_active_buffers_count() const { return _active_buffers.size(); }
const std::vector<uint32_t>& get_active_buffers() const noexcept { return _active_buffers; }
- size_t getMaxArrays() const { return _maxArrays; }
- uint32_t get_scaled_num_arrays_for_new_buffer() const;
- uint32_t get_num_arrays_for_new_buffer() const noexcept { return _numArraysForNewBuffer; }
+ size_t get_max_entries() const { return _max_entries; }
+ uint32_t get_scaled_num_entries_for_new_buffer() const;
+ uint32_t get_num_entries_for_new_buffer() const noexcept { return _num_entries_for_new_buffer; }
protected:
struct BufferCounts {
- ElemCount used_elems;
- ElemCount dead_elems;
- BufferCounts() : used_elems(0), dead_elems(0) {}
- BufferCounts(ElemCount used_elems_in, ElemCount dead_elems_in)
- : used_elems(used_elems_in), dead_elems(dead_elems_in)
+ EntryCount used_entries;
+ EntryCount dead_entries;
+ BufferCounts() : used_entries(0), dead_entries(0) {}
+ BufferCounts(EntryCount used_entries_in, EntryCount dead_entries_in)
+ : used_entries(used_entries_in), dead_entries(dead_entries_in)
{}
};
@@ -94,45 +93,48 @@ protected:
*/
class AggregatedBufferCounts {
private:
- struct Element {
- const std::atomic<ElemCount>* used_ptr;
- const std::atomic<ElemCount>* dead_ptr;
- Element() noexcept : used_ptr(nullptr), dead_ptr(nullptr) {}
- Element(const std::atomic<ElemCount>* used_ptr_in, const std::atomic<ElemCount>* dead_ptr_in) noexcept
+ struct ActiveBufferCounts {
+ const std::atomic<EntryCount>* used_ptr;
+ const std::atomic<EntryCount>* dead_ptr;
+ ActiveBufferCounts() noexcept : used_ptr(nullptr), dead_ptr(nullptr) {}
+ ActiveBufferCounts(const std::atomic<EntryCount>* used_ptr_in, const std::atomic<EntryCount>* dead_ptr_in) noexcept
: used_ptr(used_ptr_in), dead_ptr(dead_ptr_in)
{}
};
- std::vector<Element> _counts;
+ std::vector<ActiveBufferCounts> _counts;
public:
AggregatedBufferCounts();
- void add_buffer(const std::atomic<ElemCount>* used_elems, const std::atomic<ElemCount>* dead_elems);
- void remove_buffer(const std::atomic<ElemCount>* used_elems, const std::atomic<ElemCount>* dead_elems);
+ void add_buffer(const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries);
+ void remove_buffer(const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries);
BufferCounts last_buffer() const;
BufferCounts all_buffers() const;
bool empty() const { return _counts.empty(); }
};
uint32_t _arraySize; // Number of elements in an allocation unit
- uint32_t _minArrays; // Minimum number of arrays to allocate in a buffer
- uint32_t _maxArrays; // Maximum number of arrays to allocate in a buffer
- // Number of arrays needed before allocating a new buffer instead of just resizing the first one
- uint32_t _numArraysForNewBuffer;
+ uint32_t _min_entries; // Minimum number of entries to allocate in a buffer
+ uint32_t _max_entries; // Maximum number of entries to allocate in a buffer
+ // Number of entries needed before allocating a new buffer instead of just resizing the first one
+ uint32_t _num_entries_for_new_buffer;
float _allocGrowFactor;
uint32_t _holdBuffers;
- size_t _holdUsedElems; // Number of used elements in all held buffers for this type.
+ size_t _hold_used_entries; // Number of used entries in all held buffers for this type.
AggregatedBufferCounts _aggr_counts;
std::vector<uint32_t> _active_buffers;
};
/**
- * Concrete class used to manage allocation and de-allocation of elements of type EntryType in data store buffers.
+ * Concrete class used to manage allocation and de-allocation of elements of type ElemType in data store buffers.
*/
-template <typename EntryType, typename EmptyType = EntryType>
+template <typename ElemT, typename EmptyT = ElemT>
class BufferType : public BufferTypeBase
{
+public:
+ using ElemType = ElemT;
+ using EmptyType = EmptyT;
protected:
- static const EntryType& empty_entry() noexcept;
+ static const ElemType& empty_entry() noexcept;
public:
BufferType() noexcept : BufferType(1,1,1) {}
@@ -140,15 +142,15 @@ public:
BufferType & operator=(const BufferType &rhs) = delete;
BufferType(BufferType && rhs) noexcept = default;
BufferType & operator=(BufferType && rhs) noexcept = default;
- BufferType(uint32_t arraySize, uint32_t minArrays, uint32_t maxArrays) noexcept;
- BufferType(uint32_t arraySize, uint32_t minArrays, uint32_t maxArrays,
- uint32_t numArraysForNewBuffer, float allocGrowFactor) noexcept;
+ BufferType(uint32_t arraySize, uint32_t min_entries, uint32_t max_entries) noexcept;
+ BufferType(uint32_t arraySize, uint32_t min_entries, uint32_t max_entries,
+ uint32_t num_entries_for_new_buffer, float allocGrowFactor) noexcept;
~BufferType() override;
- void destroyElements(void *buffer, ElemCount numElems) override;
- void fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems) override;
- void initializeReservedElements(void *buffer, ElemCount reservedElements) override;
- void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCxt) override;
- size_t elementSize() const override { return sizeof(EntryType); }
+ void destroy_entries(void *buffer, EntryCount num_entries) override;
+ void fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries) override;
+ void initialize_reserved_entries(void *buffer, EntryCount reserved_entries) override;
+ void clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext cleanCxt) override;
+ size_t entry_size() const override { return sizeof(ElemType) * _arraySize; }
};
extern template class BufferType<char>;
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp b/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp
index 72c8f574a70..60acca5ff39 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp
@@ -6,78 +6,80 @@
namespace vespalib::datastore {
-template <typename EntryType, typename EmptyType>
-BufferType<EntryType, EmptyType>::BufferType(uint32_t arraySize, uint32_t minArrays, uint32_t maxArrays) noexcept
- : BufferTypeBase(arraySize, minArrays, maxArrays)
+template <typename ElemT, typename EmptyT>
+BufferType<ElemT, EmptyT>::BufferType(uint32_t arraySize, uint32_t min_entries, uint32_t max_entries) noexcept
+ : BufferTypeBase(arraySize, min_entries, max_entries)
{ }
-template <typename EntryType, typename EmptyType>
-BufferType<EntryType, EmptyType>::BufferType(uint32_t arraySize, uint32_t minArrays, uint32_t maxArrays,
- uint32_t numArraysForNewBuffer, float allocGrowFactor) noexcept
- : BufferTypeBase(arraySize, minArrays, maxArrays, numArraysForNewBuffer, allocGrowFactor)
+template <typename ElemT, typename EmptyT>
+BufferType<ElemT, EmptyT>::BufferType(uint32_t arraySize, uint32_t min_entries, uint32_t max_entries,
+ uint32_t num_entries_for_new_buffer, float allocGrowFactor) noexcept
+ : BufferTypeBase(arraySize, min_entries, max_entries, num_entries_for_new_buffer, allocGrowFactor)
{ }
-template <typename EntryType, typename EmptyType>
-BufferType<EntryType, EmptyType>::~BufferType() = default;
+template <typename ElemT, typename EmptyT>
+BufferType<ElemT, EmptyT>::~BufferType() = default;
-template <typename EntryType, typename EmptyType>
+template <typename ElemT, typename EmptyT>
void
-BufferType<EntryType, EmptyType>::destroyElements(void *buffer, ElemCount numElems)
+BufferType<ElemT, EmptyT>::destroy_entries(void *buffer, EntryCount num_entries)
{
- EntryType *e = static_cast<EntryType *>(buffer);
- for (size_t j = numElems; j != 0; --j) {
- e->~EntryType();
+ auto num_elems = num_entries * getArraySize();
+ ElemType *e = static_cast<ElemType *>(buffer);
+ for (size_t j = num_elems; j != 0; --j) {
+ e->~ElemType();
++e;
}
}
-template <typename EntryType, typename EmptyType>
+template <typename ElemT, typename EmptyT>
void
-BufferType<EntryType, EmptyType>::fallbackCopy(void *newBuffer,
- const void *oldBuffer,
- ElemCount numElems)
+BufferType<ElemT, EmptyT>::fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries)
{
- EntryType *d = static_cast<EntryType *>(newBuffer);
- const EntryType *s = static_cast<const EntryType *>(oldBuffer);
- for (size_t j = numElems; j != 0; --j) {
- new (static_cast<void *>(d)) EntryType(*s);
+ auto num_elems = num_entries * getArraySize();
+ ElemType *d = static_cast<ElemType *>(newBuffer);
+ const ElemType *s = static_cast<const ElemType *>(oldBuffer);
+ for (size_t j = num_elems; j != 0; --j) {
+ new (static_cast<void *>(d)) ElemType(*s);
++s;
++d;
}
}
-template <typename EntryType, typename EmptyType>
+template <typename ElemT, typename EmptyT>
void
-BufferType<EntryType, EmptyType>::initializeReservedElements(void *buffer, ElemCount reservedElems)
+BufferType<ElemT, EmptyT>::initialize_reserved_entries(void *buffer, EntryCount reserved_entries)
{
- EntryType *e = static_cast<EntryType *>(buffer);
+ auto reserved_elems = reserved_entries * getArraySize();
+ ElemType *e = static_cast<ElemType *>(buffer);
const auto& empty = empty_entry();
- for (size_t j = reservedElems; j != 0; --j) {
- new (static_cast<void *>(e)) EntryType(empty);
+ for (size_t j = reserved_elems; j != 0; --j) {
+ new (static_cast<void *>(e)) ElemType(empty);
++e;
}
}
-template <typename EntryType, typename EmptyType>
+template <typename ElemT, typename EmptyT>
void
-BufferType<EntryType, EmptyType>::cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext)
+BufferType<ElemT, EmptyT>::clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext)
{
- EntryType *e = static_cast<EntryType *>(buffer) + offset;
+ auto num_elems = num_entries * getArraySize();
+ ElemType *e = static_cast<ElemType *>(buffer) + offset * getArraySize();
const auto& empty = empty_entry();
- for (size_t j = numElems; j != 0; --j) {
+ for (size_t j = num_elems; j != 0; --j) {
*e = empty;
++e;
}
}
-template <typename EntryType, typename EmptyType>
-const EntryType&
-BufferType<EntryType, EmptyType>::empty_entry() noexcept
+template <typename ElemT, typename EmptyT>
+const ElemT&
+BufferType<ElemT, EmptyT>::empty_entry() noexcept
{
- // It's possible for EntryType to wrap e.g. an Alloc instance, which has a transitive
+ // It's possible for ElemType to wrap e.g. an Alloc instance, which has a transitive
// dependency on globally constructed allocator object(s). To avoid issues with global
// construction order, initialize the sentinel on the first access.
- static EntryType empty = EmptyType();
+ static ElemType empty = EmptyType();
return empty;
}
diff --git a/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp b/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp
index 47fba1ef697..f312596d6f7 100644
--- a/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp
@@ -12,13 +12,13 @@ namespace vespalib::datastore {
BufferState::BufferState()
: _stats(),
- _free_list(_stats.dead_elems_ref()),
+ _free_list(_stats.dead_entries_ref()),
_typeHandler(nullptr),
_buffer(Alloc::alloc(0, MemoryAllocator::HUGEPAGE_SIZE)),
_arraySize(0),
_typeId(0),
_state(State::FREE),
- _disableElemHoldList(false),
+ _disable_entry_hold_list(false),
_compacting(false)
{
}
@@ -28,15 +28,15 @@ BufferState::~BufferState()
assert(getState() == State::FREE);
assert(!_free_list.enabled());
assert(_free_list.empty());
- assert(_stats.hold_elems() == 0);
+ assert(_stats.hold_entries() == 0);
}
namespace {
struct AllocResult {
- size_t elements;
+ size_t entries;
size_t bytes;
- AllocResult(size_t elements_, size_t bytes_) : elements(elements_), bytes(bytes_) {}
+ AllocResult(size_t entries_, size_t bytes_) : entries(entries_), bytes(bytes_) {}
};
size_t
@@ -57,30 +57,30 @@ roundUpToMatchAllocator(size_t sz)
}
AllocResult
-calcAllocation(uint32_t bufferId,
- BufferTypeBase &typeHandler,
- size_t elementsNeeded,
- bool resizing)
+calc_allocation(uint32_t bufferId,
+ BufferTypeBase &typeHandler,
+ size_t free_entries_needed,
+ bool resizing)
{
- size_t allocArrays = typeHandler.calcArraysToAlloc(bufferId, elementsNeeded, resizing);
- size_t allocElements = allocArrays * typeHandler.getArraySize();
- size_t allocBytes = roundUpToMatchAllocator(allocElements * typeHandler.elementSize());
- size_t maxAllocBytes = typeHandler.getMaxArrays() * typeHandler.getArraySize() * typeHandler.elementSize();
+ size_t alloc_entries = typeHandler.calc_entries_to_alloc(bufferId, free_entries_needed, resizing);
+ size_t entry_size = typeHandler.entry_size();
+ size_t allocBytes = roundUpToMatchAllocator(alloc_entries * entry_size);
+ size_t maxAllocBytes = typeHandler.get_max_entries() * entry_size;
if (allocBytes > maxAllocBytes) {
// Ensure that allocated bytes does not exceed the maximum handled by this type.
allocBytes = maxAllocBytes;
}
- size_t adjustedAllocElements = (allocBytes / typeHandler.elementSize());
- return AllocResult(adjustedAllocElements, allocBytes);
+ size_t adjusted_alloc_entries = allocBytes / entry_size;
+ return AllocResult(adjusted_alloc_entries, allocBytes);
}
}
void
-BufferState::onActive(uint32_t bufferId, uint32_t typeId,
- BufferTypeBase *typeHandler,
- size_t elementsNeeded,
- std::atomic<void*>& buffer)
+BufferState::on_active(uint32_t bufferId, uint32_t typeId,
+ BufferTypeBase *typeHandler,
+ size_t free_entries_needed,
+ std::atomic<void*>& buffer)
{
assert(buffer.load(std::memory_order_relaxed) == nullptr);
assert(_buffer.get() == nullptr);
@@ -88,30 +88,29 @@ BufferState::onActive(uint32_t bufferId, uint32_t typeId,
assert(_typeHandler == nullptr);
assert(capacity() == 0);
assert(size() == 0);
- assert(_stats.dead_elems() == 0u);
- assert(_stats.hold_elems() == 0);
+ assert(_stats.dead_entries() == 0u);
+ assert(_stats.hold_entries() == 0);
assert(_stats.extra_used_bytes() == 0);
assert(_stats.extra_hold_bytes() == 0);
assert(_free_list.empty());
- size_t reservedElements = typeHandler->getReservedElements(bufferId);
- (void) reservedElements;
- AllocResult alloc = calcAllocation(bufferId, *typeHandler, elementsNeeded, false);
- assert(alloc.elements >= reservedElements + elementsNeeded);
+ size_t reserved_entries = typeHandler->get_reserved_entries(bufferId);
+ (void) reserved_entries;
+ AllocResult alloc = calc_allocation(bufferId, *typeHandler, free_entries_needed, false);
+ assert(alloc.entries >= reserved_entries + free_entries_needed);
auto allocator = typeHandler->get_memory_allocator();
_buffer = (allocator != nullptr) ? Alloc::alloc_with_allocator(allocator) : Alloc::alloc(0, MemoryAllocator::HUGEPAGE_SIZE);
_buffer.create(alloc.bytes).swap(_buffer);
- assert(_buffer.get() != nullptr || alloc.elements == 0u);
+ assert(_buffer.get() != nullptr || alloc.entries == 0u);
buffer.store(_buffer.get(), std::memory_order_release);
- _stats.set_alloc_elems(alloc.elements);
+ _stats.set_alloc_entries(alloc.entries);
_typeHandler.store(typeHandler, std::memory_order_release);
assert(typeId <= std::numeric_limits<uint16_t>::max());
_typeId = typeId;
_arraySize = typeHandler->getArraySize();
- _free_list.set_array_size(_arraySize);
_state.store(State::ACTIVE, std::memory_order_release);
- typeHandler->onActive(bufferId, &_stats.used_elems_ref(), &_stats.dead_elems_ref(),
- buffer.load(std::memory_order::relaxed));
+ typeHandler->on_active(bufferId, &_stats.used_entries_ref(), &_stats.dead_entries_ref(),
+ buffer.load(std::memory_order::relaxed));
}
void
@@ -121,11 +120,11 @@ BufferState::onHold(uint32_t buffer_id)
assert(getTypeHandler() != nullptr);
_state.store(State::HOLD, std::memory_order_release);
_compacting = false;
- assert(_stats.dead_elems() <= size());
- assert(_stats.hold_elems() <= (size() - _stats.dead_elems()));
- _stats.set_dead_elems(0);
- _stats.set_hold_elems(size());
- getTypeHandler()->onHold(buffer_id, &_stats.used_elems_ref(), &_stats.dead_elems_ref());
+ assert(_stats.dead_entries() <= size());
+ assert(_stats.hold_entries() <= (size() - _stats.dead_entries()));
+ _stats.set_dead_entries(0);
+ _stats.set_hold_entries(size());
+ getTypeHandler()->on_hold(buffer_id, &_stats.used_entries_ref(), &_stats.dead_entries_ref());
_free_list.disable();
}
@@ -135,20 +134,19 @@ BufferState::onFree(std::atomic<void*>& buffer)
assert(buffer.load(std::memory_order_relaxed) == _buffer.get());
assert(getState() == State::HOLD);
assert(_typeHandler != nullptr);
- assert(_stats.dead_elems() <= size());
- assert(_stats.hold_elems() == (size() - _stats.dead_elems()));
- getTypeHandler()->destroyElements(buffer, size());
+ assert(_stats.dead_entries() <= size());
+ assert(_stats.hold_entries() == (size() - _stats.dead_entries()));
+ getTypeHandler()->destroy_entries(buffer, size());
Alloc::alloc().swap(_buffer);
- getTypeHandler()->onFree(size());
+ getTypeHandler()->on_free(size());
buffer.store(nullptr, std::memory_order_release);
_stats.clear();
_state.store(State::FREE, std::memory_order_release);
_typeHandler = nullptr;
_arraySize = 0;
- _free_list.set_array_size(_arraySize);
assert(!_free_list.enabled());
assert(_free_list.empty());
- _disableElemHoldList = false;
+ _disable_entry_hold_list = false;
}
@@ -171,67 +169,67 @@ BufferState::dropBuffer(uint32_t buffer_id, std::atomic<void*>& buffer)
}
void
-BufferState::disable_elem_hold_list()
+BufferState::disable_entry_hold_list()
{
- _disableElemHoldList = true;
+ _disable_entry_hold_list = true;
}
bool
-BufferState::hold_elems(size_t num_elems, size_t extra_bytes)
+BufferState::hold_entries(size_t num_entries, size_t extra_bytes)
{
assert(isActive());
- if (_disableElemHoldList) {
+ if (_disable_entry_hold_list) {
// The elements are directly marked as dead as they are not put on hold.
- _stats.inc_dead_elems(num_elems);
+ _stats.inc_dead_entries(num_entries);
return true;
}
- _stats.inc_hold_elems(num_elems);
+ _stats.inc_hold_entries(num_entries);
_stats.inc_extra_hold_bytes(extra_bytes);
return false;
}
void
-BufferState::free_elems(EntryRef ref, size_t num_elems, size_t ref_offset)
+BufferState::free_entries(EntryRef ref, size_t num_entries, size_t ref_offset)
{
if (isActive()) {
- if (_free_list.enabled() && (num_elems == getArraySize())) {
+ if (_free_list.enabled() && (num_entries == 1)) {
_free_list.push_entry(ref);
}
} else {
assert(isOnHold());
}
- _stats.inc_dead_elems(num_elems);
- _stats.dec_hold_elems(num_elems);
- getTypeHandler()->cleanHold(_buffer.get(), (ref_offset * _arraySize), num_elems,
- BufferTypeBase::CleanContext(_stats.extra_used_bytes_ref(),
- _stats.extra_hold_bytes_ref()));
+ _stats.inc_dead_entries(num_entries);
+ _stats.dec_hold_entries(num_entries);
+ getTypeHandler()->clean_hold(_buffer.get(), ref_offset, num_entries,
+ BufferTypeBase::CleanContext(_stats.extra_used_bytes_ref(),
+ _stats.extra_hold_bytes_ref()));
}
void
-BufferState::fallbackResize(uint32_t bufferId,
- size_t elementsNeeded,
+BufferState::fallback_resize(uint32_t bufferId,
+ size_t free_entries_needed,
std::atomic<void*>& buffer,
Alloc &holdBuffer)
{
assert(getState() == State::ACTIVE);
assert(_typeHandler != nullptr);
assert(holdBuffer.get() == nullptr);
- AllocResult alloc = calcAllocation(bufferId, *_typeHandler, elementsNeeded, true);
- assert(alloc.elements >= size() + elementsNeeded);
- assert(alloc.elements > capacity());
+ AllocResult alloc = calc_allocation(bufferId, *_typeHandler, free_entries_needed, true);
+ assert(alloc.entries >= size() + free_entries_needed);
+ assert(alloc.entries > capacity());
Alloc newBuffer = _buffer.create(alloc.bytes);
- getTypeHandler()->fallbackCopy(newBuffer.get(), buffer.load(std::memory_order_relaxed), size());
+ getTypeHandler()->fallback_copy(newBuffer.get(), buffer.load(std::memory_order_relaxed), size());
holdBuffer.swap(_buffer);
std::atomic_thread_fence(std::memory_order_release);
_buffer = std::move(newBuffer);
buffer.store(_buffer.get(), std::memory_order_release);
- _stats.set_alloc_elems(alloc.elements);
+ _stats.set_alloc_entries(alloc.entries);
}
void
BufferState::resume_primary_buffer(uint32_t buffer_id)
{
- getTypeHandler()->resume_primary_buffer(buffer_id, &_stats.used_elems_ref(), &_stats.dead_elems_ref());
+ getTypeHandler()->resume_primary_buffer(buffer_id, &_stats.used_entries_ref(), &_stats.dead_entries_ref());
}
}
diff --git a/vespalib/src/vespa/vespalib/datastore/bufferstate.h b/vespalib/src/vespa/vespalib/datastore/bufferstate.h
index 5b98099ed69..f714f8e24d5 100644
--- a/vespalib/src/vespa/vespalib/datastore/bufferstate.h
+++ b/vespalib/src/vespa/vespalib/datastore/bufferstate.h
@@ -23,8 +23,8 @@ namespace vespalib::datastore {
* It is kept in this state until all reader threads are no longer accessing the buffer.
* Finally, it transitions back to FREE via onFree() and memory is de-allocated.
*
- * This class also supports use of free lists, where previously allocated elements in the buffer can be re-used.
- * First the element is put on hold, then on the free list (counted as dead) to be re-used.
+ * This class also supports use of free lists, where previously allocated entries in the buffer can be re-used.
+ * First the entry is put on hold, then on the free list (counted as dead) to be re-used.
*/
class BufferState
{
@@ -45,7 +45,7 @@ private:
uint32_t _arraySize;
uint16_t _typeId;
std::atomic<State> _state;
- bool _disableElemHoldList : 1;
+ bool _disable_entry_hold_list : 1;
bool _compacting : 1;
public:
@@ -62,14 +62,14 @@ public:
/**
* Transition from FREE to ACTIVE state.
*
- * @param bufferId Id of buffer to be active.
- * @param typeId Registered data type id for buffer.
- * @param typeHandler Type handler for registered data type.
- * @param elementsNeeded Number of elements needed to be free in the memory allocated.
- * @param buffer Start of allocated buffer return value.
+ * @param bufferId Id of buffer to be active.
+ * @param typeId Registered data type id for buffer.
+ * @param typeHandler Type handler for registered data type.
+ * @param free_entries_needed Number of entries needed to be free in the memory allocated.
+ * @param buffer Start of allocated buffer return value.
*/
- void onActive(uint32_t bufferId, uint32_t typeId, BufferTypeBase *typeHandler,
- size_t elementsNeeded, std::atomic<void*>& buffer);
+ void on_active(uint32_t bufferId, uint32_t typeId, BufferTypeBase *typeHandler,
+ size_t free_entries_needed, std::atomic<void*>& buffer);
/**
* Transition from ACTIVE to HOLD state.
@@ -82,24 +82,24 @@ public:
void onFree(std::atomic<void*>& buffer);
/**
- * Disable hold of elements, just mark elements as dead without cleanup.
+ * Disable hold of entries, just mark entries as dead without cleanup.
* Typically used when tearing down data structure in a controlled manner.
*/
- void disable_elem_hold_list();
+ void disable_entry_hold_list();
/**
- * Update stats to reflect that the given elements are put on hold.
- * Returns true if element hold list is disabled for this buffer.
+ * Update stats to reflect that the given entries are put on hold.
+ * Returns true if entry hold list is disabled for this buffer.
*/
- bool hold_elems(size_t num_elems, size_t extra_bytes);
+ bool hold_entries(size_t num_entries, size_t extra_bytes);
/**
- * Free the given elements and update stats accordingly.
+ * Free the given entries and update stats accordingly.
*
* The given entry ref is put on the free list (if enabled).
- * Hold cleaning of elements is executed on the buffer type.
+ * Hold cleaning of entries is executed on the buffer type.
*/
- void free_elems(EntryRef ref, size_t num_elems, size_t ref_offset);
+ void free_entries(EntryRef ref, size_t num_entries, size_t ref_offset);
BufferStats& stats() { return _stats; }
const BufferStats& stats() const { return _stats; }
@@ -115,8 +115,7 @@ public:
uint32_t getArraySize() const { return _arraySize; }
bool getCompacting() const { return _compacting; }
void setCompacting() { _compacting = true; }
- uint32_t get_used_arrays() const noexcept { return size() / _arraySize; }
- void fallbackResize(uint32_t bufferId, size_t elementsNeeded, std::atomic<void*>& buffer, Alloc &holdBuffer);
+ void fallback_resize(uint32_t bufferId, size_t free_entries_needed, std::atomic<void*>& buffer, Alloc &holdBuffer);
bool isActive(uint32_t typeId) const {
return (isActive() && (_typeId == typeId));
diff --git a/vespalib/src/vespa/vespalib/datastore/datastore.h b/vespalib/src/vespa/vespalib/datastore/datastore.h
index 01b81d0fa58..f81348ce287 100644
--- a/vespalib/src/vespa/vespalib/datastore/datastore.h
+++ b/vespalib/src/vespa/vespalib/datastore/datastore.h
@@ -27,7 +27,7 @@ template <typename RefT = EntryRefT<22> >
class DataStoreT : public DataStoreBase
{
private:
- void free_elem_internal(EntryRef ref, size_t numElems);
+ void free_entry_internal(EntryRef ref, size_t num_entries);
public:
using RefType = RefT;
@@ -38,12 +38,12 @@ public:
~DataStoreT() override;
/**
- * Hold element(s).
+ * Hold entries.
*/
- void holdElem(EntryRef ref, size_t numElems) {
- holdElem(ref, numElems, 0);
- }
- void holdElem(EntryRef ref, size_t numElems, size_t extraBytes);
+ void hold_entry(EntryRef ref) { hold_entries(ref, 1, 0); }
+ void hold_entry(EntryRef ref, size_t extra_bytes) { hold_entries(ref, 1, extra_bytes); }
+ void hold_entries(EntryRef ref, size_t num_entries) { hold_entries(ref, num_entries, 0); }
+ void hold_entries(EntryRef ref, size_t num_entries, size_t extraBytes);
void reclaim_entry_refs(generation_t oldest_used_gen) override;
@@ -75,7 +75,7 @@ class DataStore : public DataStoreT<RefT>
{
protected:
using ParentType = DataStoreT<RefT>;
- using ParentType::ensureBufferCapacity;
+ using ParentType::ensure_buffer_capacity;
using ParentType::getEntry;
using ParentType::dropBuffers;
using ParentType::init_primary_buffers;
diff --git a/vespalib/src/vespa/vespalib/datastore/datastore.hpp b/vespalib/src/vespa/vespalib/datastore/datastore.hpp
index bfb63954875..b21a5954eee 100644
--- a/vespalib/src/vespa/vespalib/datastore/datastore.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/datastore.hpp
@@ -22,21 +22,21 @@ DataStoreT<RefT>::~DataStoreT() = default;
template <typename RefT>
void
-DataStoreT<RefT>::free_elem_internal(EntryRef ref, size_t numElems)
+DataStoreT<RefT>::free_entry_internal(EntryRef ref, size_t num_entries)
{
RefType intRef(ref);
BufferState &state = getBufferState(intRef.bufferId());
- state.free_elems(ref, numElems, intRef.offset());
+ state.free_entries(ref, num_entries, intRef.offset());
}
template <typename RefT>
void
-DataStoreT<RefT>::holdElem(EntryRef ref, size_t numElems, size_t extraBytes)
+DataStoreT<RefT>::hold_entries(EntryRef ref, size_t num_entries, size_t extraBytes)
{
RefType intRef(ref);
BufferState &state = getBufferState(intRef.bufferId());
- if (!state.hold_elems(numElems, extraBytes)) {
- _entry_ref_hold_list.insert({ref, numElems});
+ if (!state.hold_entries(num_entries, extraBytes)) {
+ _entry_ref_hold_list.insert({ref, num_entries});
}
}
@@ -45,7 +45,7 @@ void
DataStoreT<RefT>::reclaim_entry_refs(generation_t oldest_used_gen)
{
_entry_ref_hold_list.reclaim(oldest_used_gen, [this](const auto& elem) {
- free_elem_internal(elem.ref, elem.num_elems);
+ free_entry_internal(elem.ref, elem.num_entries);
});
}
@@ -54,7 +54,7 @@ void
DataStoreT<RefT>::reclaim_all_entry_refs()
{
_entry_ref_hold_list.reclaim_all([this](const auto& elem) {
- free_elem_internal(elem.ref, elem.num_elems);
+ free_entry_internal(elem.ref, elem.num_entries);
});
}
diff --git a/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp b/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp
index a40aa713bca..75ffe855a32 100644
--- a/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp
@@ -40,18 +40,18 @@ constexpr size_t TOO_DEAD_SLACK = 0x4000u;
bool
primary_buffer_too_dead(const BufferState &state)
{
- size_t deadElems = state.stats().dead_elems();
- size_t deadBytes = deadElems * state.getArraySize();
- return ((deadBytes >= TOO_DEAD_SLACK) && (deadElems * 2 >= state.size()));
+ size_t dead_entries = state.stats().dead_entries();
+ size_t deadBytes = dead_entries * state.getTypeHandler()->entry_size();
+ return ((deadBytes >= TOO_DEAD_SLACK) && (dead_entries * 2 >= state.size()));
}
}
-DataStoreBase::FallbackHold::FallbackHold(size_t bytesSize, BufferState::Alloc &&buffer, size_t usedElems,
+DataStoreBase::FallbackHold::FallbackHold(size_t bytesSize, BufferState::Alloc &&buffer, size_t used_entries,
BufferTypeBase *typeHandler, uint32_t typeId)
: GenerationHeldBase(bytesSize),
_buffer(std::move(buffer)),
- _usedElems(usedElems),
+ _used_entries(used_entries),
_typeHandler(typeHandler),
_typeId(typeId)
{
@@ -59,7 +59,7 @@ DataStoreBase::FallbackHold::FallbackHold(size_t bytesSize, BufferState::Alloc &
DataStoreBase::FallbackHold::~FallbackHold()
{
- _typeHandler->destroyElements(_buffer.get(), _usedElems);
+ _typeHandler->destroy_entries(_buffer.get(), _used_entries);
}
class DataStoreBase::BufferHold : public GenerationHeldBase {
@@ -80,7 +80,7 @@ public:
}
};
-DataStoreBase::DataStoreBase(uint32_t numBuffers, uint32_t offset_bits, size_t maxArrays)
+DataStoreBase::DataStoreBase(uint32_t numBuffers, uint32_t offset_bits, size_t max_entries)
: _entry_ref_hold_list(),
_buffers(numBuffers),
_primary_buffer_ids(),
@@ -89,12 +89,12 @@ DataStoreBase::DataStoreBase(uint32_t numBuffers, uint32_t offset_bits, size_t m
_free_lists(),
_compaction_count(0u),
_genHolder(),
- _maxArrays(maxArrays),
+ _max_entries(max_entries),
_bufferIdLimit(0u),
_hold_buffer_count(0u),
_offset_bits(offset_bits),
_freeListsEnabled(false),
- _disableElemHoldList(false),
+ _disable_entry_hold_list(false),
_initializing(false)
{
}
@@ -105,19 +105,19 @@ DataStoreBase::~DataStoreBase()
}
void
-DataStoreBase::switch_primary_buffer(uint32_t typeId, size_t elemsNeeded)
+DataStoreBase::switch_primary_buffer(uint32_t typeId, size_t entries_needed)
{
size_t buffer_id = getFirstFreeBufferId();
if (buffer_id >= getMaxNumBuffers()) {
LOG_ABORT(vespalib::make_string("switch_primary_buffer(%u, %zu): did not find a free buffer",
- typeId, elemsNeeded).c_str());
+ typeId, entries_needed).c_str());
}
- onActive(buffer_id, typeId, elemsNeeded);
+ on_active(buffer_id, typeId, entries_needed);
_primary_buffer_ids[typeId] = buffer_id;
}
bool
-DataStoreBase::consider_grow_active_buffer(uint32_t type_id, size_t elems_needed)
+DataStoreBase::consider_grow_active_buffer(uint32_t type_id, size_t entries_needed)
{
auto type_handler = _typeHandlers[type_id];
uint32_t buffer_id = primary_buffer_id(type_id);
@@ -126,7 +126,7 @@ DataStoreBase::consider_grow_active_buffer(uint32_t type_id, size_t elems_needed
if (active_buffers_count < min_active_buffers) {
return false;
}
- if (type_handler->get_num_arrays_for_new_buffer() == 0u) {
+ if (type_handler->get_num_entries_for_new_buffer() == 0u) {
return false;
}
assert(!getBufferState(buffer_id).getCompacting());
@@ -146,8 +146,7 @@ DataStoreBase::consider_grow_active_buffer(uint32_t type_id, size_t elems_needed
if (checked_active_buffers < min_active_buffers) {
return false;
}
- auto array_size = type_handler->getArraySize();
- if (elems_needed + min_used > type_handler->getMaxArrays() * array_size) {
+ if (entries_needed + min_used > type_handler->get_max_entries()) {
return false;
}
if (min_buffer_id != buffer_id) {
@@ -181,24 +180,22 @@ DataStoreBase::getBufferState(uint32_t buffer_id) noexcept {
}
void
-DataStoreBase::switch_or_grow_primary_buffer(uint32_t typeId, size_t elemsNeeded)
+DataStoreBase::switch_or_grow_primary_buffer(uint32_t typeId, size_t entries_needed)
{
auto typeHandler = _typeHandlers[typeId];
- uint32_t arraySize = typeHandler->getArraySize();
- size_t numArraysForNewBuffer = typeHandler->get_scaled_num_arrays_for_new_buffer();
- size_t numEntriesForNewBuffer = numArraysForNewBuffer * arraySize;
+ size_t num_entries_for_new_buffer = typeHandler->get_scaled_num_entries_for_new_buffer();
uint32_t bufferId = primary_buffer_id(typeId);
- if (elemsNeeded + getBufferState(bufferId).size() >= numEntriesForNewBuffer) {
- if (consider_grow_active_buffer(typeId, elemsNeeded)) {
+ if (entries_needed + getBufferState(bufferId).size() >= num_entries_for_new_buffer) {
+ if (consider_grow_active_buffer(typeId, entries_needed)) {
bufferId = primary_buffer_id(typeId);
- if (elemsNeeded > getBufferState(bufferId).remaining()) {
- fallbackResize(bufferId, elemsNeeded);
+ if (entries_needed > getBufferState(bufferId).remaining()) {
+ fallback_resize(bufferId, entries_needed);
}
} else {
- switch_primary_buffer(typeId, elemsNeeded);
+ switch_primary_buffer(typeId, entries_needed);
}
} else {
- fallbackResize(bufferId, elemsNeeded);
+ fallback_resize(bufferId, entries_needed);
}
}
@@ -209,7 +206,7 @@ DataStoreBase::init_primary_buffers()
for (uint32_t typeId = 0; typeId < numTypes; ++typeId) {
size_t buffer_id = getFirstFreeBufferId();
assert(buffer_id <= get_bufferid_limit_relaxed());
- onActive(buffer_id, typeId, 0u);
+ on_active(buffer_id, typeId, 0u);
_primary_buffer_ids[typeId] = buffer_id;
}
}
@@ -219,7 +216,7 @@ DataStoreBase::addType(BufferTypeBase *typeHandler)
{
uint32_t typeId = _primary_buffer_ids.size();
assert(typeId == _typeHandlers.size());
- typeHandler->clampMaxArrays(_maxArrays);
+ typeHandler->clamp_max_entries(_max_entries);
_primary_buffer_ids.push_back(0);
_typeHandlers.push_back(typeHandler);
_free_lists.emplace_back();
@@ -328,12 +325,12 @@ DataStoreBase::disableFreeLists()
}
void
-DataStoreBase::disableElemHoldList()
+DataStoreBase::disable_entry_hold_list()
{
for_each_buffer([](BufferState & state) {
- if (!state.isFree()) state.disable_elem_hold_list();
+ if (!state.isFree()) state.disable_entry_hold_list();
});
- _disableElemHoldList = true;
+ _disable_entry_hold_list = true;
}
MemoryStats
@@ -351,13 +348,13 @@ DataStoreBase::getMemStats() const
if ((state == BufferState::State::FREE) || (typeHandler == nullptr)) {
++stats._freeBuffers;
} else if (state == BufferState::State::ACTIVE) {
- size_t elementSize = typeHandler->elementSize();
+ size_t entry_size = typeHandler->entry_size();
++stats._activeBuffers;
- bState->stats().add_to_mem_stats(elementSize, stats);
+ bState->stats().add_to_mem_stats(entry_size, stats);
} else if (state == BufferState::State::HOLD) {
- size_t elementSize = typeHandler->elementSize();
+ size_t entry_size = typeHandler->entry_size();
++stats._holdBuffers;
- bState->stats().add_to_mem_stats(elementSize, stats);
+ bState->stats().add_to_mem_stats(entry_size, stats);
} else {
LOG_ABORT("should not be reached");
}
@@ -373,32 +370,30 @@ vespalib::AddressSpace
DataStoreBase::getAddressSpaceUsage() const
{
uint32_t buffer_id_limit = get_bufferid_limit_acquire();
- size_t usedArrays = 0;
- size_t deadArrays = 0;
- size_t limitArrays = size_t(_maxArrays) * (getMaxNumBuffers() - buffer_id_limit);
+ size_t used_entries = 0;
+ size_t dead_entries = 0;
+ size_t limit_entries = size_t(_max_entries) * (getMaxNumBuffers() - buffer_id_limit);
for (uint32_t bufferId = 0; bufferId < buffer_id_limit; ++bufferId) {
const BufferState * bState = _buffers[bufferId].get_state_acquire();
assert(bState != nullptr);
if (bState->isFree()) {
- limitArrays += _maxArrays;
+ limit_entries += _max_entries;
} else if (bState->isActive()) {
- uint32_t arraySize = bState->getArraySize();
- usedArrays += bState->size() / arraySize;
- deadArrays += bState->stats().dead_elems() / arraySize;
- limitArrays += bState->capacity() / arraySize;
+ used_entries += bState->size();
+ dead_entries += bState->stats().dead_entries();
+ limit_entries += bState->capacity();
} else if (bState->isOnHold()) {
- uint32_t arraySize = bState->getArraySize();
- usedArrays += bState->size() / arraySize;
- limitArrays += bState->capacity() / arraySize;
+ used_entries += bState->size();
+ limit_entries += bState->capacity();
} else {
LOG_ABORT("should not be reached");
}
}
- return {usedArrays, deadArrays, limitArrays};
+ return {used_entries, dead_entries, limit_entries};
}
void
-DataStoreBase::onActive(uint32_t bufferId, uint32_t typeId, size_t elemsNeeded)
+DataStoreBase::on_active(uint32_t bufferId, uint32_t typeId, size_t entries_needed)
{
assert(typeId < _typeHandlers.size());
assert(bufferId <= _bufferIdLimit);
@@ -407,8 +402,8 @@ DataStoreBase::onActive(uint32_t bufferId, uint32_t typeId, size_t elemsNeeded)
BufferState *state = bufferMeta.get_state_relaxed();
if (state == nullptr) {
BufferState & newState = _stash.create<BufferState>();
- if (_disableElemHoldList) {
- newState.disable_elem_hold_list();
+ if (_disable_entry_hold_list) {
+ newState.disable_entry_hold_list();
}
if ( ! _freeListsEnabled) {
newState.disable_free_list();
@@ -418,7 +413,7 @@ DataStoreBase::onActive(uint32_t bufferId, uint32_t typeId, size_t elemsNeeded)
_bufferIdLimit.store(bufferId + 1, std::memory_order_release);
}
assert(state->isFree());
- state->onActive(bufferId, typeId, _typeHandlers[typeId], elemsNeeded, bufferMeta.get_atomic_buffer());
+ state->on_active(bufferId, typeId, _typeHandlers[typeId], entries_needed, bufferMeta.get_atomic_buffer());
bufferMeta.setTypeId(typeId);
bufferMeta.setArraySize(state->getArraySize());
if (_freeListsEnabled && state->isActive() && !state->getCompacting()) {
@@ -436,17 +431,17 @@ DataStoreBase::finishCompact(const std::vector<uint32_t> &toHold)
}
void
-DataStoreBase::fallbackResize(uint32_t bufferId, size_t elemsNeeded)
+DataStoreBase::fallback_resize(uint32_t bufferId, size_t entries_needed)
{
BufferState &state = getBufferState(bufferId);
BufferState::Alloc toHoldBuffer;
- size_t oldUsedElems = state.size();
- size_t oldAllocElems = state.capacity();
- size_t elementSize = state.getTypeHandler()->elementSize();
- state.fallbackResize(bufferId, elemsNeeded, _buffers[bufferId].get_atomic_buffer(), toHoldBuffer);
- auto hold = std::make_unique<FallbackHold>(oldAllocElems * elementSize,
+ size_t old_used_entries = state.size();
+ size_t old_alloc_entries = state.capacity();
+ size_t entry_size = state.getTypeHandler()->entry_size();
+ state.fallback_resize(bufferId, entries_needed, _buffers[bufferId].get_atomic_buffer(), toHoldBuffer);
+ auto hold = std::make_unique<FallbackHold>(old_alloc_entries * entry_size,
std::move(toHoldBuffer),
- oldUsedElems,
+ old_used_entries,
state.getTypeHandler(),
state.getTypeId());
if (!_initializing) {
@@ -465,7 +460,7 @@ DataStoreBase::markCompacting(uint32_t bufferId)
}
assert(!state.getCompacting());
state.setCompacting();
- state.disable_elem_hold_list();
+ state.disable_entry_hold_list();
state.disable_free_list();
inc_compaction_count();
}
@@ -492,15 +487,15 @@ DataStoreBase::start_compact_worst_buffers(CompactionSpec compaction_spec, const
free_buffers++;
} else if (state->isActive()) {
auto typeHandler = state->getTypeHandler();
- uint32_t arraySize = typeHandler->getArraySize();
- uint32_t reservedElements = typeHandler->getReservedElements(bufferId);
- size_t used_elems = state->size();
- size_t deadElems = state->stats().dead_elems() - reservedElements;
+ uint32_t reserved_entries = typeHandler->get_reserved_entries(bufferId);
+ size_t used_entries = state->size();
+ size_t dead_entries = state->stats().dead_entries() - reserved_entries;
+ size_t entry_size = typeHandler->entry_size();
if (compaction_spec.compact_memory()) {
- elem_buffers.add(bufferId, used_elems, deadElems);
+ elem_buffers.add(bufferId, used_entries * entry_size, dead_entries * entry_size);
}
if (compaction_spec.compact_address_space()) {
- array_buffers.add(bufferId, used_elems / arraySize, deadElems / arraySize);
+ array_buffers.add(bufferId, used_entries, dead_entries);
}
}
}
diff --git a/vespalib/src/vespa/vespalib/datastore/datastorebase.h b/vespalib/src/vespa/vespalib/datastore/datastorebase.h
index 9cab7a2e375..e5a38e3fd41 100644
--- a/vespalib/src/vespa/vespalib/datastore/datastorebase.h
+++ b/vespalib/src/vespa/vespalib/datastore/datastorebase.h
@@ -35,15 +35,16 @@ public:
void init_primary_buffers();
/**
- * Ensure that the primary buffer for the given type has a given number of elements free at end.
+ * Ensure that the primary buffer for the given type has a given number of entries free at end.
* Switch to new buffer if current buffer is too full.
*
- * @param typeId Registered data type for buffer.
- * @param elemsNeeded Number of elements needed to be free.
+ * @param typeId Registered data type for buffer.
+ * @param entries_needed Number of entries needed to be free.
*/
- void ensureBufferCapacity(uint32_t typeId, size_t elemsNeeded) {
- if (elemsNeeded > getBufferState(primary_buffer_id(typeId)).remaining()) [[unlikely]] {
- switch_or_grow_primary_buffer(typeId, elemsNeeded);
+ void ensure_buffer_capacity(uint32_t typeId, size_t entries_needed) {
+ auto &state = getBufferState(primary_buffer_id(typeId));
+ if (entries_needed > state.remaining()) [[unlikely]] {
+ switch_or_grow_primary_buffer(typeId, entries_needed);
}
}
@@ -58,10 +59,10 @@ public:
* Switch to a new primary buffer, typically in preparation for compaction
* or when the current primary buffer no longer has free space.
*
- * @param typeId Registered data type for buffer.
- * @param elemsNeeded Number of elements needed to be free.
+ * @param typeId Registered data type for buffer.
+ * @param entries_needed Number of entries needed to be free.
*/
- void switch_primary_buffer(uint32_t typeId, size_t elemsNeeded);
+ void switch_primary_buffer(uint32_t typeId, size_t entries_needed);
vespalib::MemoryUsage getMemoryUsage() const;
vespalib::MemoryUsage getDynamicMemoryUsage() const;
@@ -127,7 +128,7 @@ public:
/**
* Enable free list management.
- * This only works for fixed size elements.
+ * This only works for fixed size entries.
*/
void enableFreeLists();
@@ -135,7 +136,7 @@ public:
* Disable free list management.
*/
void disableFreeLists();
- void disableElemHoldList();
+ void disable_entry_hold_list();
bool has_free_lists_enabled() const { return _freeListsEnabled; }
@@ -177,25 +178,25 @@ public:
bool has_held_buffers() const noexcept { return _hold_buffer_count != 0u; }
/**
- * Trim elem hold list, freeing elements that no longer needs to be held.
+ * Trim entry hold list, freeing entries that no longer needs to be held.
*
* @param oldest_used_gen the oldest generation that is still used.
*/
virtual void reclaim_entry_refs(generation_t oldest_used_gen) = 0;
protected:
- DataStoreBase(uint32_t numBuffers, uint32_t offset_bits, size_t maxArrays);
+ DataStoreBase(uint32_t numBuffers, uint32_t offset_bits, size_t max_entries);
virtual ~DataStoreBase();
void* getBuffer(uint32_t bufferId) { return _buffers[bufferId].get_buffer_relaxed(); }
struct EntryRefHoldElem {
EntryRef ref;
- size_t num_elems;
+ size_t num_entries;
- EntryRefHoldElem(EntryRef ref_in, size_t num_elems_in)
+ EntryRefHoldElem(EntryRef ref_in, size_t num_entries_in)
: ref(ref_in),
- num_elems(num_elems_in)
+ num_entries(num_entries_in)
{}
};
@@ -215,11 +216,11 @@ private:
{
public:
BufferState::Alloc _buffer;
- size_t _usedElems;
+ size_t _used_entries;
BufferTypeBase *_typeHandler;
uint32_t _typeId;
- FallbackHold(size_t bytesSize, BufferState::Alloc &&buffer, size_t usedElems,
+ FallbackHold(size_t bytesSize, BufferState::Alloc &&buffer, size_t used_entries,
BufferTypeBase *typeHandler, uint32_t typeId);
~FallbackHold() override;
@@ -227,8 +228,8 @@ private:
class BufferHold;
- bool consider_grow_active_buffer(uint32_t type_id, size_t elems_needed);
- void switch_or_grow_primary_buffer(uint32_t typeId, size_t elemsNeeded);
+ bool consider_grow_active_buffer(uint32_t type_id, size_t entries_needed);
+ void switch_or_grow_primary_buffer(uint32_t typeId, size_t entries_needed);
void markCompacting(uint32_t bufferId);
/**
* Hold of buffer has ended.
@@ -238,14 +239,14 @@ private:
/**
* Switch buffer state to active for the given buffer.
*
- * @param bufferId Id of buffer to be active.
- * @param typeId Registered data type for buffer.
- * @param elemsNeeded Number of elements needed to be free.
+ * @param bufferId Id of buffer to be active.
+ * @param typeId Registered data type for buffer.
+ * @param entries_needed Number of entries needed to be free.
*/
- void onActive(uint32_t bufferId, uint32_t typeId, size_t elemsNeeded);
+ void on_active(uint32_t bufferId, uint32_t typeId, size_t entries_needed);
void inc_hold_buffer_count();
- void fallbackResize(uint32_t bufferId, size_t elementsNeeded);
+ void fallback_resize(uint32_t bufferId, size_t entries_needed);
uint32_t getFirstFreeBufferId();
template<typename FuncType>
@@ -261,7 +262,7 @@ private:
std::vector<BufferAndMeta> _buffers; // For fast mapping with known types
// Provides a mapping from typeId -> primary buffer for that type.
- // The primary buffer is used for allocations of new element(s) if no available slots are found in free lists.
+ // The primary buffer is used for allocations of new entries if no available slots are found in free lists.
std::vector<uint32_t> _primary_buffer_ids;
Stash _stash;
@@ -269,12 +270,12 @@ private:
std::vector<FreeList> _free_lists;
mutable std::atomic<uint64_t> _compaction_count;
vespalib::GenerationHolder _genHolder;
- const uint32_t _maxArrays;
+ const uint32_t _max_entries;
std::atomic<uint32_t> _bufferIdLimit;
uint32_t _hold_buffer_count;
const uint8_t _offset_bits;
bool _freeListsEnabled;
- bool _disableElemHoldList;
+ bool _disable_entry_hold_list;
bool _initializing;
};
diff --git a/vespalib/src/vespa/vespalib/datastore/free_list.h b/vespalib/src/vespa/vespalib/datastore/free_list.h
index 20d4a6b96df..cd475af3104 100644
--- a/vespalib/src/vespa/vespalib/datastore/free_list.h
+++ b/vespalib/src/vespa/vespalib/datastore/free_list.h
@@ -30,7 +30,6 @@ public:
bool empty() const { return _free_lists.empty(); }
size_t size() const { return _free_lists.size(); }
- uint32_t array_size() const { return _free_lists.back()->array_size(); }
EntryRef pop_entry() {
return _free_lists.back()->pop_entry();
}
diff --git a/vespalib/src/vespa/vespalib/datastore/free_list_allocator.h b/vespalib/src/vespa/vespalib/datastore/free_list_allocator.h
index cf899a76712..dc2d1ea3c34 100644
--- a/vespalib/src/vespa/vespalib/datastore/free_list_allocator.h
+++ b/vespalib/src/vespa/vespalib/datastore/free_list_allocator.h
@@ -29,7 +29,7 @@ public:
HandleType alloc(Args && ... args);
HandleType allocArray(ConstArrayRef array);
- HandleType allocArray(size_t size);
+ HandleType allocArray();
};
}
diff --git a/vespalib/src/vespa/vespalib/datastore/free_list_allocator.hpp b/vespalib/src/vespa/vespalib/datastore/free_list_allocator.hpp
index b793e4f77a2..4e69db08a3c 100644
--- a/vespalib/src/vespa/vespalib/datastore/free_list_allocator.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/free_list_allocator.hpp
@@ -71,8 +71,9 @@ FreeListAllocator<EntryT, RefT, ReclaimerT>::allocArray(ConstArrayRef array)
if (free_list.empty()) {
return ParentType::allocArray(array);
}
- assert(free_list.array_size() == array.size());
RefT ref = free_list.pop_entry();
+ auto& state = _store.getBufferState(ref.bufferId());
+ assert(state.getArraySize() == array.size());
EntryT *buf = _store.template getEntryArray<EntryT>(ref, array.size());
for (size_t i = 0; i < array.size(); ++i) {
*(buf + i) = array[i];
@@ -82,14 +83,15 @@ FreeListAllocator<EntryT, RefT, ReclaimerT>::allocArray(ConstArrayRef array)
template <typename EntryT, typename RefT, typename ReclaimerT>
typename Allocator<EntryT, RefT>::HandleType
-FreeListAllocator<EntryT, RefT, ReclaimerT>::allocArray(size_t size)
+FreeListAllocator<EntryT, RefT, ReclaimerT>::allocArray()
{
auto& free_list = _store.getFreeList(_typeId);
if (free_list.empty()) {
- return ParentType::allocArray(size);
+ return ParentType::allocArray();
}
- assert(free_list.array_size() == size);
RefT ref = free_list.pop_entry();
+ auto& state = _store.getBufferState(ref.bufferId());
+ auto size = state.getArraySize();
EntryT *buf = _store.template getEntryArray<EntryT>(ref, size);
return HandleType(ref, buf);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.h b/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.h
index 1b71c22f0ce..29684267546 100644
--- a/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.h
+++ b/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.h
@@ -27,7 +27,7 @@ private:
public:
FreeListRawAllocator(DataStoreBase &store, uint32_t typeId);
- HandleType alloc(size_t numElems);
+ HandleType alloc(size_t num_entries);
};
}
diff --git a/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.hpp b/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.hpp
index af832955cb7..7680cd8a9a5 100644
--- a/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/free_list_raw_allocator.hpp
@@ -14,16 +14,18 @@ FreeListRawAllocator<EntryT, RefT>::FreeListRawAllocator(DataStoreBase &store, u
template <typename EntryT, typename RefT>
typename FreeListRawAllocator<EntryT, RefT>::HandleType
-FreeListRawAllocator<EntryT, RefT>::alloc(size_t numElems)
+FreeListRawAllocator<EntryT, RefT>::alloc(size_t num_entries)
{
auto& free_list = _store.getFreeList(_typeId);
if (free_list.empty()) {
- return ParentType::alloc(numElems);
+ return ParentType::alloc(num_entries);
}
- assert(free_list.array_size() == numElems);
+ assert(num_entries == 1);
RefT ref = free_list.pop_entry();
+ auto& state = _store.getBufferState(ref.bufferId());
+ auto array_size = state.getArraySize();
// We must scale the offset according to array size as it was divided when the entry ref was created.
- EntryT *entry = _store.template getEntryArray<EntryT>(ref, numElems);
+ EntryT *entry = _store.template getEntryArray<EntryT>(ref, array_size);
return HandleType(ref, entry);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h
index 600925969a3..e2718b94cd2 100644
--- a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h
+++ b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h
@@ -14,11 +14,11 @@ namespace vespalib::datastore {
/*
* Class representing buffer type for large arrays in ArrayStore
*/
-template <typename EntryT>
-class LargeArrayBufferType : public BufferType<Array<EntryT>>
+template <typename ElemT>
+class LargeArrayBufferType : public BufferType<Array<ElemT>>
{
using AllocSpec = ArrayStoreConfig::AllocSpec;
- using ArrayType = Array<EntryT>;
+ using ArrayType = Array<ElemT>;
using ParentType = BufferType<ArrayType>;
using ParentType::empty_entry;
using CleanContext = typename ParentType::CleanContext;
@@ -31,7 +31,7 @@ public:
{
}
~LargeArrayBufferType() override;
- void cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
+ void clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
diff --git a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp
index 3042bbff73f..72a2662991b 100644
--- a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp
@@ -7,32 +7,32 @@
namespace vespalib::datastore {
-template <typename EntryT>
-LargeArrayBufferType<EntryT>::LargeArrayBufferType(const AllocSpec& spec, std::shared_ptr<alloc::MemoryAllocator> memory_allocator) noexcept
- : BufferType<Array<EntryT>>(1u, spec.minArraysInBuffer, spec.maxArraysInBuffer, spec.numArraysForNewBuffer, spec.allocGrowFactor),
+template <typename ElemT>
+LargeArrayBufferType<ElemT>::LargeArrayBufferType(const AllocSpec& spec, std::shared_ptr<alloc::MemoryAllocator> memory_allocator) noexcept
+ : BufferType<Array<ElemT>>(1u, spec.min_entries_in_buffer, spec.max_entries_in_buffer, spec.num_entries_for_new_buffer, spec.allocGrowFactor),
_memory_allocator(std::move(memory_allocator))
{
}
-template <typename EntryT>
-LargeArrayBufferType<EntryT>::~LargeArrayBufferType() = default;
+template <typename ElemT>
+LargeArrayBufferType<ElemT>::~LargeArrayBufferType() = default;
-template <typename EntryT>
+template <typename ElemT>
void
-LargeArrayBufferType<EntryT>::cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx)
+LargeArrayBufferType<ElemT>::clean_hold(void* buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx)
{
ArrayType* elem = static_cast<ArrayType*>(buffer) + offset;
const auto& empty = empty_entry();
- for (size_t i = 0; i < numElems; ++i) {
- cleanCtx.extraBytesCleaned(sizeof(EntryT) * elem->size());
+ for (size_t i = 0; i < num_entries; ++i) {
+ cleanCtx.extraBytesCleaned(sizeof(ElemT) * elem->size());
*elem = empty;
++elem;
}
}
-template <typename EntryT>
+template <typename ElemT>
const vespalib::alloc::MemoryAllocator*
-LargeArrayBufferType<EntryT>::get_memory_allocator() const
+LargeArrayBufferType<ElemT>::get_memory_allocator() const
{
return _memory_allocator.get();
}
diff --git a/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp b/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp
index 8e060b4cfb4..5cb04796c5b 100644
--- a/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp
@@ -5,10 +5,10 @@
namespace vespalib::datastore {
MemoryStats::MemoryStats()
- : _allocElems(0),
- _usedElems(0),
- _deadElems(0),
- _holdElems(0),
+ : _alloc_entries(0),
+ _used_entries(0),
+ _dead_entries(0),
+ _hold_entries(0),
_allocBytes(0),
_usedBytes(0),
_deadBytes(0),
@@ -22,10 +22,10 @@ MemoryStats::MemoryStats()
MemoryStats&
MemoryStats::operator+=(const MemoryStats& rhs)
{
- _allocElems += rhs._allocElems;
- _usedElems += rhs._usedElems;
- _deadElems += rhs._deadElems;
- _holdElems += rhs._holdElems;
+ _alloc_entries += rhs._alloc_entries;
+ _used_entries += rhs._used_entries;
+ _dead_entries += rhs._dead_entries;
+ _hold_entries += rhs._hold_entries;
_allocBytes += rhs._allocBytes;
_usedBytes += rhs._usedBytes;
_deadBytes += rhs._deadBytes;
diff --git a/vespalib/src/vespa/vespalib/datastore/memory_stats.h b/vespalib/src/vespa/vespalib/datastore/memory_stats.h
index 18d7dd77559..72a570dd625 100644
--- a/vespalib/src/vespa/vespalib/datastore/memory_stats.h
+++ b/vespalib/src/vespa/vespalib/datastore/memory_stats.h
@@ -13,10 +13,10 @@ namespace vespalib::datastore {
class MemoryStats
{
public:
- size_t _allocElems;
- size_t _usedElems;
- size_t _deadElems;
- size_t _holdElems;
+ size_t _alloc_entries;
+ size_t _used_entries;
+ size_t _dead_entries;
+ size_t _hold_entries;
size_t _allocBytes;
size_t _usedBytes;
size_t _deadBytes;
diff --git a/vespalib/src/vespa/vespalib/datastore/raw_allocator.h b/vespalib/src/vespa/vespalib/datastore/raw_allocator.h
index c10c8152e72..e7a59fadcf8 100644
--- a/vespalib/src/vespa/vespalib/datastore/raw_allocator.h
+++ b/vespalib/src/vespa/vespalib/datastore/raw_allocator.h
@@ -25,10 +25,10 @@ protected:
public:
RawAllocator(DataStoreBase &store, uint32_t typeId);
- HandleType alloc(size_t numElems) {
- return alloc(numElems, 0);
+ HandleType alloc(size_t num_entries) {
+ return alloc(num_entries, 0);
}
- HandleType alloc(size_t numElems, size_t extraElems);
+ HandleType alloc(size_t num_entries, size_t extra_entries);
};
}
diff --git a/vespalib/src/vespa/vespalib/datastore/raw_allocator.hpp b/vespalib/src/vespa/vespalib/datastore/raw_allocator.hpp
index 04d99588218..9de361a8b19 100644
--- a/vespalib/src/vespa/vespalib/datastore/raw_allocator.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/raw_allocator.hpp
@@ -16,19 +16,15 @@ RawAllocator<EntryT, RefT>::RawAllocator(DataStoreBase &store, uint32_t typeId)
template <typename EntryT, typename RefT>
typename RawAllocator<EntryT, RefT>::HandleType
-RawAllocator<EntryT, RefT>::alloc(size_t numElems, size_t extraElems)
+RawAllocator<EntryT, RefT>::alloc(size_t num_entries, size_t extra_entries)
{
- _store.ensureBufferCapacity(_typeId, numElems + extraElems);
+ _store.ensure_buffer_capacity(_typeId, num_entries + extra_entries);
uint32_t buffer_id = _store.primary_buffer_id(_typeId);
BufferState &state = _store.getBufferState(buffer_id);
assert(state.isActive());
- size_t oldBufferSize = state.size();
- // Must perform scaling ourselves, according to array size
- size_t arraySize = state.getArraySize();
- assert((numElems % arraySize) == 0u);
- RefT ref((oldBufferSize / arraySize), buffer_id);
- EntryT *buffer = _store.getEntryArray<EntryT>(ref, arraySize);
- state.stats().pushed_back(numElems);
+ RefT ref(state.size(), buffer_id);
+ EntryT *buffer = _store.getEntryArray<EntryT>(ref, state.getArraySize());
+ state.stats().pushed_back(num_entries);
return HandleType(ref, buffer);
}
diff --git a/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.h b/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.h
index 676a9d3790f..6bb6601839d 100644
--- a/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.h
+++ b/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.h
@@ -13,8 +13,8 @@ namespace vespalib::datastore {
/*
* Class representing buffer type for small arrays in ArrayStore
*/
-template <typename EntryT>
-class SmallArrayBufferType : public BufferType<EntryT>
+template <typename ElemT>
+class SmallArrayBufferType : public BufferType<ElemT>
{
using AllocSpec = ArrayStoreConfig::AllocSpec;
std::shared_ptr<alloc::MemoryAllocator> _memory_allocator;
diff --git a/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.hpp b/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.hpp
index 414804417eb..c9033936bd6 100644
--- a/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/small_array_buffer_type.hpp
@@ -6,19 +6,19 @@
namespace vespalib::datastore {
-template <typename EntryT>
-SmallArrayBufferType<EntryT>::SmallArrayBufferType(uint32_t array_size, const AllocSpec& spec, std::shared_ptr<alloc::MemoryAllocator> memory_allocator) noexcept
- : BufferType<EntryT>(array_size, spec.minArraysInBuffer, spec.maxArraysInBuffer, spec.numArraysForNewBuffer, spec.allocGrowFactor),
+template <typename ElemT>
+SmallArrayBufferType<ElemT>::SmallArrayBufferType(uint32_t array_size, const AllocSpec& spec, std::shared_ptr<alloc::MemoryAllocator> memory_allocator) noexcept
+ : BufferType<ElemT>(array_size, spec.min_entries_in_buffer, spec.max_entries_in_buffer, spec.num_entries_for_new_buffer, spec.allocGrowFactor),
_memory_allocator(std::move(memory_allocator))
{
}
-template <typename EntryT>
-SmallArrayBufferType<EntryT>::~SmallArrayBufferType() = default;
+template <typename ElemT>
+SmallArrayBufferType<ElemT>::~SmallArrayBufferType() = default;
-template <typename EntryT>
+template <typename ElemT>
const vespalib::alloc::MemoryAllocator*
-SmallArrayBufferType<EntryT>::get_memory_allocator() const
+SmallArrayBufferType<ElemT>::get_memory_allocator() const
{
return _memory_allocator.get();
}
diff --git a/vespalib/src/vespa/vespalib/datastore/unique_store.hpp b/vespalib/src/vespa/vespalib/datastore/unique_store.hpp
index 52b0798543f..0efaf04b26e 100644
--- a/vespalib/src/vespa/vespalib/datastore/unique_store.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/unique_store.hpp
@@ -106,7 +106,7 @@ private:
_mapping.resize(data_store.get_bufferid_limit_relaxed());
for (const auto bufferId : _compacting_buffers->get_buffer_ids()) {
BufferState &state = data_store.getBufferState(bufferId);
- _mapping[bufferId].resize(state.get_used_arrays());
+ _mapping[bufferId].resize(state.size());
}
}
diff --git a/vespalib/src/vespa/vespalib/datastore/unique_store_allocator.hpp b/vespalib/src/vespa/vespalib/datastore/unique_store_allocator.hpp
index 8ad11b18218..49d2631e73f 100644
--- a/vespalib/src/vespa/vespalib/datastore/unique_store_allocator.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/unique_store_allocator.hpp
@@ -43,7 +43,7 @@ template <typename EntryT, typename RefT>
void
UniqueStoreAllocator<EntryT, RefT>::hold(EntryRef ref)
{
- _store.holdElem(ref, 1);
+ _store.hold_entry(ref);
}
template <typename EntryT, typename RefT>
diff --git a/vespalib/src/vespa/vespalib/datastore/unique_store_enumerator.hpp b/vespalib/src/vespa/vespalib/datastore/unique_store_enumerator.hpp
index 32513d09c72..4a517521d77 100644
--- a/vespalib/src/vespa/vespalib/datastore/unique_store_enumerator.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/unique_store_enumerator.hpp
@@ -44,7 +44,7 @@ UniqueStoreEnumerator<RefT>::allocate_enum_values(DataStoreBase & store)
{
_enumValues.resize(store.get_bufferid_limit_relaxed());
store.for_each_active_buffer([this](uint32_t buffer_id, const BufferState & state) {
- _enumValues[buffer_id].resize(state.get_used_arrays());
+ _enumValues[buffer_id].resize(state.size());
});
}
diff --git a/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.cpp b/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.cpp
index 1d3ba27d6bf..9f2105b7f08 100644
--- a/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.cpp
@@ -42,28 +42,28 @@ UniqueStoreSmallStringBufferType::UniqueStoreSmallStringBufferType(uint32_t arra
UniqueStoreSmallStringBufferType::~UniqueStoreSmallStringBufferType() = default;
void
-UniqueStoreSmallStringBufferType::destroyElements(void *, ElemCount)
+UniqueStoreSmallStringBufferType::destroy_entries(void *, EntryCount)
{
static_assert(std::is_trivially_destructible<UniqueStoreSmallStringEntry>::value,
"UniqueStoreSmallStringEntry must be trivially destructable");
}
void
-UniqueStoreSmallStringBufferType::fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems)
+UniqueStoreSmallStringBufferType::fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount num_entries)
{
static_assert(std::is_trivially_copyable<UniqueStoreSmallStringEntry>::value,
"UniqueStoreSmallStringEntry must be trivially copyable");
- if (numElems > 0) {
- memcpy(newBuffer, oldBuffer, numElems);
+ if (num_entries > 0) {
+ memcpy(newBuffer, oldBuffer, num_entries * getArraySize());
}
}
void
-UniqueStoreSmallStringBufferType::cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext)
+UniqueStoreSmallStringBufferType::clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext)
{
- void *e = static_cast<char *>(buffer) + offset;
- void *e_end = static_cast<char *>(e) + numElems;
size_t array_size = getArraySize();
+ void *e = static_cast<char *>(buffer) + offset * array_size;
+ void *e_end = static_cast<char *>(e) + num_entries * array_size;
while (e < e_end) {
static_cast<UniqueStoreSmallStringEntry *>(e)->clean_hold(array_size);
e = static_cast<char *>(e) + array_size;
@@ -86,10 +86,10 @@ UniqueStoreExternalStringBufferType::UniqueStoreExternalStringBufferType(uint32_
UniqueStoreExternalStringBufferType::~UniqueStoreExternalStringBufferType() = default;
void
-UniqueStoreExternalStringBufferType::cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx)
+UniqueStoreExternalStringBufferType::clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx)
{
UniqueStoreEntry<std::string> *elem = static_cast<UniqueStoreEntry<std::string> *>(buffer) + offset;
- for (size_t i = 0; i < numElems; ++i) {
+ for (size_t i = 0; i < num_entries; ++i) {
cleanCtx.extraBytesCleaned(elem->value().size() + 1);
std::string().swap(elem->value());
++elem;
diff --git a/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.h b/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.h
index a85b73f423d..d3348950891 100644
--- a/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.h
+++ b/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.h
@@ -62,9 +62,9 @@ class UniqueStoreSmallStringBufferType : public BufferType<char> {
public:
UniqueStoreSmallStringBufferType(uint32_t array_size, uint32_t max_arrays, std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator);
~UniqueStoreSmallStringBufferType() override;
- void destroyElements(void *, ElemCount) override;
- void fallbackCopy(void *newBuffer, const void *oldBuffer, ElemCount numElems) override;
- void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext) override;
+ void destroy_entries(void *, EntryCount) override;
+ void fallback_copy(void *newBuffer, const void *oldBuffer, EntryCount numElems) override;
+ void clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
@@ -76,7 +76,7 @@ class UniqueStoreExternalStringBufferType : public BufferType<UniqueStoreEntry<s
public:
UniqueStoreExternalStringBufferType(uint32_t array_size, uint32_t max_arrays, std::shared_ptr<vespalib::alloc::MemoryAllocator> memory_allocator);
~UniqueStoreExternalStringBufferType() override;
- void cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx) override;
+ void clean_hold(void *buffer, size_t offset, EntryCount num_entries, CleanContext cleanCtx) override;
const vespalib::alloc::MemoryAllocator* get_memory_allocator() const override;
};
diff --git a/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.hpp b/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.hpp
index 65cab4850ba..4ff8e1e1ab4 100644
--- a/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/unique_store_string_allocator.hpp
@@ -42,7 +42,7 @@ UniqueStoreStringAllocator<RefT>::allocate(const char *value)
uint32_t type_id = string_allocator::get_type_id(value_len);
if (type_id != 0) {
size_t array_size = string_allocator::array_sizes[type_id - 1];
- auto handle = _store.template freeListRawAllocator<char>(type_id).alloc(array_size);
+ auto handle = _store.template freeListRawAllocator<char>(type_id).alloc(1);
new (static_cast<void *>(handle.data)) UniqueStoreSmallStringEntry(value, value_len, array_size);
return handle.ref;
} else {
@@ -61,11 +61,10 @@ UniqueStoreStringAllocator<RefT>::hold(EntryRef ref)
RefT iRef(ref);
uint32_t type_id = _store.getTypeId(iRef.bufferId());
if (type_id != 0) {
- size_t array_size = string_allocator::array_sizes[type_id - 1];
- _store.holdElem(ref, array_size);
+ _store.hold_entry(ref);
} else {
auto &value = _store.template getEntry<WrappedExternalEntryType>(iRef)->value();
- _store.holdElem(ref, 1, value.size() + 1);
+ _store.hold_entry(ref, value.size() + 1);
}
}
@@ -79,7 +78,7 @@ UniqueStoreStringAllocator<RefT>::move_on_compact(EntryRef ref)
static_assert(std::is_trivially_copyable<UniqueStoreSmallStringEntry>::value,
"UniqueStoreSmallStringEntry must be trivially copyable");
size_t array_size = string_allocator::array_sizes[type_id - 1];
- auto handle = _store.template rawAllocator<char>(type_id).alloc(array_size);
+ auto handle = _store.template rawAllocator<char>(type_id).alloc(1);
auto orig = _store.template getEntryArray<char>(iRef, array_size);
memcpy(handle.data, orig, array_size);
return handle.ref;
diff --git a/vespalib/src/vespa/vespalib/util/CMakeLists.txt b/vespalib/src/vespa/vespalib/util/CMakeLists.txt
index 663b3b65638..8ee3957af32 100644
--- a/vespalib/src/vespa/vespalib/util/CMakeLists.txt
+++ b/vespalib/src/vespa/vespalib/util/CMakeLists.txt
@@ -100,3 +100,7 @@ vespa_add_library(vespalib_vespalib_util OBJECT
zstdcompressor.cpp
DEPENDS
)
+
+# Don't convert call to jump when returning a value from a function with
+# a compatible stack.
+set_source_files_properties(signalhandler.cpp PROPERTIES COMPILE_OPTIONS "-fno-optimize-sibling-calls")
diff --git a/vespalib/src/vespa/vespalib/util/time.cpp b/vespalib/src/vespa/vespalib/util/time.cpp
index cba26f24059..dd4972b1c21 100644
--- a/vespalib/src/vespa/vespalib/util/time.cpp
+++ b/vespalib/src/vespa/vespalib/util/time.cpp
@@ -93,7 +93,7 @@ Timer::waitAtLeast(duration dur, bool busyWait) {
}
-#if (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000) || (!defined(_LIBCPP_VERSION) && defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 12)
+#if (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000) || (!defined(_LIBCPP_VERSION) && defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 12)
// Temporary workaround until libc++ supports stream operators for duration
// Temporary workaround while using libstdc++ 11
diff --git a/vespalib/src/vespa/vespalib/util/time.h b/vespalib/src/vespa/vespalib/util/time.h
index b893661832f..10077a0b49a 100644
--- a/vespalib/src/vespa/vespalib/util/time.h
+++ b/vespalib/src/vespa/vespalib/util/time.h
@@ -101,7 +101,7 @@ duration adjustTimeoutByHz(duration timeout, long hz);
}
-#if (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000) || (!defined(_LIBCPP_VERSION) && defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 12)
+#if (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000) || (!defined(_LIBCPP_VERSION) && defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 12)
// Temporary workaround until libc++ supports stream operators for duration
// Temporary workaround while using libstdc++ 11