summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/Reindexer.java16
-rw-r--r--clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/ReindexingMaintainer.java3
-rw-r--r--clustercontroller-reindexer/src/test/java/ai/vespa/reindexing/ReindexerTest.java51
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java3
-rw-r--r--config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java7
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java1
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java7
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java17
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/search/test/SearchNodeTest.java2
-rw-r--r--configdefinitions/src/vespa/reindexing.def7
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java35
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java27
-rw-r--r--container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java17
-rw-r--r--container-search-gui/src/main/resources/gui/editarea/edit_area/plugins/autocompletion/autocompletion.js2
-rwxr-xr-xcontainer-search-gui/src/main/resources/gui/editarea/edit_area/reg_syntax/yql.js2
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java27
-rw-r--r--controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java43
-rw-r--r--controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/cd.controller.json8
-rw-r--r--controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/default.json8
-rw-r--r--controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/main.prod.us-west-1.json8
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java102
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunner.java9
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java79
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java78
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json3
-rw-r--r--eval/CMakeLists.txt24
-rw-r--r--eval/src/tests/eval/tensor_lambda/tensor_lambda_test.cpp6
-rw-r--r--eval/src/tests/eval/typed_cells/CMakeLists.txt (renamed from eval/src/tests/tensor/typed_cells/CMakeLists.txt)0
-rw-r--r--eval/src/tests/eval/typed_cells/typed_cells_test.cpp (renamed from eval/src/tests/tensor/typed_cells/typed_cells_test.cpp)0
-rw-r--r--eval/src/tests/instruction/dense_add_dimension_optimizer/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_add_dimension_optimizer/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp (renamed from eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp)5
-rw-r--r--eval/src/tests/instruction/dense_fast_rename_optimizer/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_fast_rename_optimizer/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp (renamed from eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp)5
-rw-r--r--eval/src/tests/instruction/dense_inplace_join_function/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_inplace_join_function/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_inplace_join_function/dense_inplace_join_function_test.cpp (renamed from eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp)1
-rw-r--r--eval/src/tests/instruction/dense_pow_as_map_optimizer/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp (renamed from eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp)3
-rw-r--r--eval/src/tests/instruction/dense_remove_dimension_optimizer/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_remove_dimension_optimizer/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp (renamed from eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp)5
-rw-r--r--eval/src/tests/instruction/dense_replace_type_function/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_replace_type_function/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_replace_type_function/dense_replace_type_function_test.cpp (renamed from eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp)5
-rw-r--r--eval/src/tests/instruction/dense_simple_join_function/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_simple_join_function/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_simple_join_function/dense_simple_join_function_test.cpp (renamed from eval/src/tests/tensor/dense_simple_join_function/dense_simple_join_function_test.cpp)5
-rw-r--r--eval/src/tests/instruction/dense_simple_map_function/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_simple_map_function/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_simple_map_function/dense_simple_map_function_test.cpp (renamed from eval/src/tests/tensor/dense_simple_map_function/dense_simple_map_function_test.cpp)3
-rw-r--r--eval/src/tests/instruction/dense_single_reduce_function/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_single_reduce_function/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_single_reduce_function/dense_single_reduce_function_test.cpp (renamed from eval/src/tests/tensor/dense_single_reduce_function/dense_single_reduce_function_test.cpp)3
-rw-r--r--eval/src/tests/instruction/dense_tensor_create_function/CMakeLists.txt (renamed from eval/src/tests/tensor/dense_tensor_create_function/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/dense_tensor_create_function/dense_tensor_create_function_test.cpp (renamed from eval/src/tests/tensor/dense_tensor_create_function/dense_tensor_create_function_test.cpp)3
-rw-r--r--eval/src/tests/instruction/vector_from_doubles_function/CMakeLists.txt (renamed from eval/src/tests/tensor/vector_from_doubles_function/CMakeLists.txt)0
-rw-r--r--eval/src/tests/instruction/vector_from_doubles_function/vector_from_doubles_function_test.cpp (renamed from eval/src/tests/tensor/vector_from_doubles_function/vector_from_doubles_function_test.cpp)3
-rw-r--r--eval/src/tests/tensor/dense_dimension_combiner/CMakeLists.txt9
-rw-r--r--eval/src/tests/tensor/dense_dimension_combiner/dense_dimension_combiner_test.cpp185
-rw-r--r--eval/src/tests/tensor/direct_sparse_tensor_builder/CMakeLists.txt8
-rw-r--r--eval/src/tests/tensor/direct_sparse_tensor_builder/direct_sparse_tensor_builder_test.cpp119
-rw-r--r--eval/src/tests/tensor/instruction_benchmark/.gitignore2
-rw-r--r--eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp64
-rw-r--r--eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp1
-rw-r--r--eval/src/tests/tensor/tensor_address/tensor_address_test.cpp2
-rw-r--r--eval/src/vespa/eval/eval/optimize_tensor_function.cpp20
-rw-r--r--eval/src/vespa/eval/eval/tensor_function.h3
-rw-r--r--eval/src/vespa/eval/eval/value_type.cpp2
-rw-r--r--eval/src/vespa/eval/instruction/CMakeLists.txt10
-rw-r--r--eval/src/vespa/eval/instruction/dense_add_dimension_optimizer.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp)15
-rw-r--r--eval/src/vespa/eval/instruction/dense_add_dimension_optimizer.h (renamed from eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.h)7
-rw-r--r--eval/src/vespa/eval/instruction/dense_fast_rename_optimizer.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp)14
-rw-r--r--eval/src/vespa/eval/instruction/dense_fast_rename_optimizer.h (renamed from eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.h)7
-rw-r--r--eval/src/vespa/eval/instruction/dense_lambda_peek_optimizer.cpp4
-rw-r--r--eval/src/vespa/eval/instruction/dense_pow_as_map_optimizer.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_pow_as_map_optimizer.cpp)11
-rw-r--r--eval/src/vespa/eval/instruction/dense_pow_as_map_optimizer.h (renamed from eval/src/vespa/eval/tensor/dense/dense_pow_as_map_optimizer.h)7
-rw-r--r--eval/src/vespa/eval/instruction/dense_remove_dimension_optimizer.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp)16
-rw-r--r--eval/src/vespa/eval/instruction/dense_remove_dimension_optimizer.h (renamed from eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.h)7
-rw-r--r--eval/src/vespa/eval/instruction/dense_replace_type_function.cpp48
-rw-r--r--eval/src/vespa/eval/instruction/dense_replace_type_function.h (renamed from eval/src/vespa/eval/tensor/dense/dense_replace_type_function.h)17
-rw-r--r--eval/src/vespa/eval/instruction/dense_simple_join_function.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_simple_join_function.cpp)27
-rw-r--r--eval/src/vespa/eval/instruction/dense_simple_join_function.h (renamed from eval/src/vespa/eval/tensor/dense/dense_simple_join_function.h)18
-rw-r--r--eval/src/vespa/eval/instruction/dense_simple_map_function.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_simple_map_function.cpp)24
-rw-r--r--eval/src/vespa/eval/instruction/dense_simple_map_function.h26
-rw-r--r--eval/src/vespa/eval/instruction/dense_single_reduce_function.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.cpp)27
-rw-r--r--eval/src/vespa/eval/instruction/dense_single_reduce_function.h (renamed from eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.h)24
-rw-r--r--eval/src/vespa/eval/instruction/dense_tensor_create_function.cpp (renamed from eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.cpp)28
-rw-r--r--eval/src/vespa/eval/instruction/dense_tensor_create_function.h34
-rw-r--r--eval/src/vespa/eval/instruction/generic_join.h2
-rw-r--r--eval/src/vespa/eval/instruction/generic_lambda.cpp6
-rw-r--r--eval/src/vespa/eval/instruction/generic_lambda.h2
-rw-r--r--eval/src/vespa/eval/instruction/generic_map.h2
-rw-r--r--eval/src/vespa/eval/instruction/join_with_number_function.h4
-rw-r--r--eval/src/vespa/eval/instruction/vector_from_doubles_function.cpp (renamed from eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp)31
-rw-r--r--eval/src/vespa/eval/instruction/vector_from_doubles_function.h (renamed from eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.h)22
-rw-r--r--eval/src/vespa/eval/onnx/onnx_wrapper.cpp36
-rw-r--r--eval/src/vespa/eval/onnx/onnx_wrapper.h24
-rw-r--r--eval/src/vespa/eval/tensor/dense/CMakeLists.txt10
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp54
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h25
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_tensor.cpp76
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h33
-rw-r--r--eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.cpp46
-rw-r--r--eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.h41
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java14
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java9
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java108
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java2
-rw-r--r--searchcore/src/apps/vespa-feed-bm/vespa_feed_bm.cpp16
-rw-r--r--searchlib/src/vespa/searchlib/features/onnx_feature.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/features/onnx_feature.h2
-rw-r--r--storage/src/tests/distributor/read_for_write_visitor_operation_test.cpp24
-rw-r--r--storage/src/tests/storageserver/rpc/cluster_controller_rpc_api_service_test.cpp2
-rw-r--r--storage/src/tests/storageserver/rpc/storage_api_rpc_service_test.cpp2
-rw-r--r--storage/src/vespa/storage/common/CMakeLists.txt1
-rw-r--r--storage/src/vespa/storage/common/bucketoperationlogger.cpp330
-rw-r--r--storage/src/vespa/storage/common/bucketoperationlogger.h123
-rw-r--r--storage/src/vespa/storage/config/stor-communicationmanager.def3
-rw-r--r--storage/src/vespa/storage/distributor/bucketdbupdater.cpp1
-rw-r--r--storage/src/vespa/storage/distributor/distributorcomponent.cpp1
-rw-r--r--storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.cpp28
-rw-r--r--storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.h2
-rw-r--r--storage/src/vespa/storage/distributor/operations/external/visitoroperation.cpp7
-rw-r--r--storage/src/vespa/storage/distributor/operations/external/visitoroperation.h1
-rw-r--r--storage/src/vespa/storage/distributor/operations/idealstate/splitoperation.cpp21
-rw-r--r--storage/src/vespa/storage/distributor/pending_bucket_space_db_transition.cpp1
-rw-r--r--storage/src/vespa/storage/distributor/pendingclusterstate.cpp1
-rw-r--r--storage/src/vespa/storage/distributor/statecheckers.cpp1
-rw-r--r--storage/src/vespa/storage/persistence/bucketownershipnotifier.cpp7
-rw-r--r--storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp21
-rw-r--r--storage/src/vespa/storage/persistence/simplemessagehandler.cpp3
-rw-r--r--storage/src/vespa/storage/storageserver/communicationmanager.cpp3
-rw-r--r--storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.cpp6
-rw-r--r--storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.h3
-rw-r--r--storage/src/vespa/storage/storageserver/statemanager.cpp1
-rw-r--r--vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java16
-rw-r--r--zookeeper-server/zookeeper-server-3.6.2/pom.xml15
-rw-r--r--zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java3
-rw-r--r--zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java14
-rw-r--r--zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java5
138 files changed, 988 insertions, 1654 deletions
diff --git a/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/Reindexer.java b/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/Reindexer.java
index 19dfd031dfc..fd887a4196b 100644
--- a/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/Reindexer.java
+++ b/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/Reindexer.java
@@ -49,10 +49,10 @@ public class Reindexer {
private final ReindexingMetrics metrics;
private final Clock clock;
private final Phaser phaser = new Phaser(2); // Reindexer and visitor.
+ private final double windowSizeIncrement;
- @Inject
public Reindexer(Cluster cluster, Map<DocumentType, Instant> ready, ReindexingCurator database,
- DocumentAccess access, Metric metric, Clock clock) {
+ DocumentAccess access, Metric metric, Clock clock, double windowSizeIncrement) {
this(cluster,
ready,
database,
@@ -65,11 +65,13 @@ public class Reindexer {
}
},
metric,
- clock);
+ clock,
+ windowSizeIncrement);
}
Reindexer(Cluster cluster, Map<DocumentType, Instant> ready, ReindexingCurator database,
- Function<VisitorParameters, Runnable> visitorSessions, Metric metric, Clock clock) {
+ Function<VisitorParameters, Runnable> visitorSessions, Metric metric, Clock clock,
+ double windowSizeIncrement) {
for (DocumentType type : ready.keySet())
cluster.bucketSpaceOf(type); // Verifies this is known.
@@ -79,6 +81,7 @@ public class Reindexer {
this.visitorSessions = visitorSessions;
this.metrics = new ReindexingMetrics(metric, cluster.name);
this.clock = clock;
+ this.windowSizeIncrement = windowSizeIncrement;
}
/** Lets the reindexer abort any ongoing visit session, wait for it to complete normally, then exit. */
@@ -91,6 +94,9 @@ public class Reindexer {
if (phaser.isTerminated())
throw new IllegalStateException("Already shut down");
+ // Keep metrics in sync across cluster controller containers.
+ metrics.dump(database.readReindexing(cluster.name));
+
try (Lock lock = database.lockReindexing(cluster.name())) {
AtomicReference<Reindexing> reindexing = new AtomicReference<>(database.readReindexing(cluster.name()));
reindexing.set(updateWithReady(ready, reindexing.get(), clock.instant()));
@@ -191,7 +197,7 @@ public class Reindexer {
VisitorParameters createParameters(DocumentType type, ProgressToken progress) {
VisitorParameters parameters = new VisitorParameters(type.getName());
- parameters.setThrottlePolicy(new DynamicThrottlePolicy().setWindowSizeIncrement(0.2)
+ parameters.setThrottlePolicy(new DynamicThrottlePolicy().setWindowSizeIncrement(windowSizeIncrement)
.setWindowSizeDecrementFactor(5)
.setResizeRate(10)
.setMinWindowSize(1));
diff --git a/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/ReindexingMaintainer.java b/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/ReindexingMaintainer.java
index 9a114eabbb5..8668ed037ef 100644
--- a/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/ReindexingMaintainer.java
+++ b/clustercontroller-reindexer/src/main/java/ai/vespa/reindexing/ReindexingMaintainer.java
@@ -72,7 +72,8 @@ public class ReindexingMaintainer extends AbstractComponent {
access.getDocumentTypeManager()),
access,
metric,
- clock))
+ clock,
+ reindexingConfig.windowSizeIncrement()))
.collect(toUnmodifiableList());
this.executor = new ScheduledThreadPoolExecutor(reindexingConfig.clusters().size(), new DaemonThreadFactory("reindexer-"));
if (reindexingConfig.enabled())
diff --git a/clustercontroller-reindexer/src/test/java/ai/vespa/reindexing/ReindexerTest.java b/clustercontroller-reindexer/src/test/java/ai/vespa/reindexing/ReindexerTest.java
index 7086c36af3f..9a88d8aad1f 100644
--- a/clustercontroller-reindexer/src/test/java/ai/vespa/reindexing/ReindexerTest.java
+++ b/clustercontroller-reindexer/src/test/java/ai/vespa/reindexing/ReindexerTest.java
@@ -59,17 +59,12 @@ class ReindexerTest {
@Test
void throwsWhenUnknownBuckets() {
assertThrows(NullPointerException.class,
- () -> new Reindexer(new Cluster("cluster", "id", Map.of()),
- Map.of(music, Instant.EPOCH),
- database,
- failIfCalled,
- metric,
- clock));
+ () -> new Reindexer(new Cluster("cluster", "id", Map.of()), Map.of(music, Instant.EPOCH), database, failIfCalled, metric, clock, 0.2));
}
@Test
void throwsWhenLockHeldElsewhere() throws InterruptedException, ExecutionException {
- Reindexer reindexer = new Reindexer(cluster, Map.of(music, Instant.EPOCH), database, failIfCalled, metric, clock);
+ Reindexer reindexer = new Reindexer(cluster, Map.of(music, Instant.EPOCH), database, failIfCalled, metric, clock, 0.2);
Executors.newSingleThreadExecutor().submit(() -> database.lockReindexing("cluster")).get();
assertThrows(ReindexingLockException.class, reindexer::reindex);
}
@@ -77,13 +72,13 @@ class ReindexerTest {
@Test
@Timeout(10)
void nothingToDoWithEmptyConfig() throws ReindexingLockException {
- new Reindexer(cluster, Map.of(), database, failIfCalled, metric, clock).reindex();
+ new Reindexer(cluster, Map.of(), database, failIfCalled, metric, clock, 0.2).reindex();
assertEquals(Map.of(), metric.metrics());
}
@Test
void testParameters() {
- Reindexer reindexer = new Reindexer(cluster, Map.of(), database, failIfCalled, metric, clock);
+ Reindexer reindexer = new Reindexer(cluster, Map.of(), database, failIfCalled, metric, clock, 0.2);
ProgressToken token = new ProgressToken();
VisitorParameters parameters = reindexer.createParameters(music, token);
assertEquals("music:[document]", parameters.getFieldSet());
@@ -100,7 +95,7 @@ class ReindexerTest {
void testReindexing() throws ReindexingLockException {
// Reindexer is told to update "music" documents no earlier than EPOCH, which is just now.
// Since "music" is a new document type, it is stored as just reindexed, and nothing else happens.
- new Reindexer(cluster, Map.of(music, Instant.EPOCH), database, failIfCalled, metric, clock).reindex();
+ new Reindexer(cluster, Map.of(music, Instant.EPOCH), database, failIfCalled, metric, clock, 0.2).reindex();
Reindexing reindexing = Reindexing.empty().with(music, Status.ready(Instant.EPOCH).running().successful(Instant.EPOCH));
assertEquals(reindexing, database.readReindexing("cluster"));
assertEquals(Map.of("reindexing.progress", Map.of(Map.of("documenttype", "music",
@@ -124,7 +119,7 @@ class ReindexerTest {
// New config tells reindexer to reindex "music" documents no earlier than at 10 millis after EPOCH, which isn't yet.
// Nothing happens, since it's not yet time. This isn't supposed to happen unless high clock skew.
clock.advance(Duration.ofMillis(5));
- new Reindexer(cluster, Map.of(music, Instant.ofEpochMilli(10)), database, failIfCalled, metric, clock).reindex();
+ new Reindexer(cluster, Map.of(music, Instant.ofEpochMilli(10)), database, failIfCalled, metric, clock, 0.2).reindex();
assertEquals(reindexing, database.readReindexing("cluster"));
// It's time to reindex the "music" documents — let this complete successfully.
@@ -132,10 +127,10 @@ class ReindexerTest {
AtomicBoolean shutDown = new AtomicBoolean();
Executor executor = Executors.newSingleThreadExecutor();
new Reindexer(cluster, Map.of(music, Instant.ofEpochMilli(10)), database, parameters -> {
- database.writeReindexing(Reindexing.empty(), "cluster"); // Wipe database to verify we write data from reindexer.
- executor.execute(() -> parameters.getControlHandler().onDone(VisitorControlHandler.CompletionCode.SUCCESS, "OK"));
- return () -> shutDown.set(true);
- }, metric, clock).reindex();
+ database.writeReindexing(Reindexing.empty(), "cluster"); // Wipe database to verify we write data from reindexer.
+ executor.execute(() -> parameters.getControlHandler().onDone(VisitorControlHandler.CompletionCode.SUCCESS, "OK"));
+ return () -> shutDown.set(true);
+ }, metric, clock, 0.2).reindex();
reindexing = reindexing.with(music, Status.ready(clock.instant()).running().successful(clock.instant()));
assertEquals(reindexing, database.readReindexing("cluster"));
assertTrue(shutDown.get(), "Session was shut down");
@@ -146,14 +141,14 @@ class ReindexerTest {
shutDown.set(false);
AtomicReference<Reindexer> aborted = new AtomicReference<>();
aborted.set(new Reindexer(cluster, Map.of(music, Instant.ofEpochMilli(20)), database, parameters -> {
- database.writeReindexing(Reindexing.empty(), "cluster"); // Wipe database to verify we write data from reindexer.
- parameters.getControlHandler().onProgress(new ProgressToken());
- aborted.get().shutdown();
- return () -> {
- shutDown.set(true);
- parameters.getControlHandler().onDone(VisitorControlHandler.CompletionCode.ABORTED, "Shut down");
- };
- }, metric, clock));
+ database.writeReindexing(Reindexing.empty(), "cluster"); // Wipe database to verify we write data from reindexer.
+ parameters.getControlHandler().onProgress(new ProgressToken());
+ aborted.get().shutdown();
+ return () -> {
+ shutDown.set(true);
+ parameters.getControlHandler().onDone(VisitorControlHandler.CompletionCode.ABORTED, "Shut down");
+ };
+ }, metric, clock, 0.2));
aborted.get().reindex();
reindexing = reindexing.with(music, Status.ready(clock.instant()).running().progressed(new ProgressToken()).halted());
assertEquals(reindexing, database.readReindexing("cluster"));
@@ -168,16 +163,16 @@ class ReindexerTest {
clock.advance(Duration.ofMillis(10));
shutDown.set(false);
new Reindexer(cluster, Map.of(music, Instant.ofEpochMilli(30)), database, parameters -> {
- database.writeReindexing(Reindexing.empty(), "cluster"); // Wipe database to verify we write data from reindexer.
- executor.execute(() -> parameters.getControlHandler().onDone(VisitorControlHandler.CompletionCode.FAILURE, "Error"));
- return () -> shutDown.set(true);
- }, metric, clock).reindex();
+ database.writeReindexing(Reindexing.empty(), "cluster"); // Wipe database to verify we write data from reindexer.
+ executor.execute(() -> parameters.getControlHandler().onDone(VisitorControlHandler.CompletionCode.FAILURE, "Error"));
+ return () -> shutDown.set(true);
+ }, metric, clock, 0.2).reindex();
reindexing = reindexing.with(music, Status.ready(clock.instant()).running().failed(clock.instant(), "Error"));
assertEquals(reindexing, database.readReindexing("cluster"));
assertTrue(shutDown.get(), "Session was shut down");
// Document type is ignored in next run, as it has failed fatally.
- new Reindexer(cluster, Map.of(music, Instant.ofEpochMilli(30)), database, failIfCalled, metric, clock).reindex();
+ new Reindexer(cluster, Map.of(music, Instant.ofEpochMilli(30)), database, failIfCalled, metric, clock, 0.2).reindex();
assertEquals(reindexing, database.readReindexing("cluster"));
}
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
index 3e0561a315a..381f0ace69e 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
@@ -65,9 +65,11 @@ public interface ModelContext {
*/
interface FeatureFlags {
@ModelFeatureFlag(owners = {"bjorncs", "jonmv"}) default boolean enableAutomaticReindexing() { return false; }
+ @ModelFeatureFlag(owners = {"bjorncs", "jonmv"}) default double reindexerWindowSizeIncrement() { return 0.2; }
@ModelFeatureFlag(owners = {"baldersheim"}, comment = "Revisit in May or June 2020") default double defaultTermwiseLimit() { throw new UnsupportedOperationException("TODO specify default value"); }
@ModelFeatureFlag(owners = {"vekterli"}) default boolean useThreePhaseUpdates() { throw new UnsupportedOperationException("TODO specify default value"); }
@ModelFeatureFlag(owners = {"geirst"}, comment = "Remove on 7.XXX when this is default on") default boolean useDirectStorageApiRpc() { throw new UnsupportedOperationException("TODO specify default value"); }
+ @ModelFeatureFlag(owners = {"geirst"}, comment = "Remove on 7.XXX when this is default on") default boolean useFastValueTensorImplementation() { throw new UnsupportedOperationException("TODO specify default value"); }
@ModelFeatureFlag(owners = {"baldersheim"}, comment = "Select sequencer type use while feeding") default String feedSequencerType() { throw new UnsupportedOperationException("TODO specify default value"); }
@ModelFeatureFlag(owners = {"baldersheim"}) default String responseSequencerType() { throw new UnsupportedOperationException("TODO specify default value"); }
@ModelFeatureFlag(owners = {"baldersheim"}) default int defaultNumResponseThreads() { return 2; }
@@ -125,6 +127,7 @@ public interface ModelContext {
@Deprecated double feedConcurrency();
@Deprecated boolean useThreePhaseUpdates();
@Deprecated boolean useDirectStorageApiRpc();
+ @Deprecated boolean useFastValueTensorImplementation();
@Deprecated default boolean useAccessControlTlsHandshakeClientAuth() { return false; }
}
diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
index 3a90c335c48..2b819b731a1 100644
--- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
+++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java
@@ -38,6 +38,7 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
private boolean useDedicatedNodeForLogserver = false;
private boolean useThreePhaseUpdates = false;
private boolean useDirectStorageApiRpc = false;
+ private boolean useFastValueTensorImplementation = false;
private double defaultTermwiseLimit = 1.0;
private String jvmGCOptions = null;
private String sequencerType = "LATENCY";
@@ -73,6 +74,7 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
@Override public double defaultTermwiseLimit() { return defaultTermwiseLimit; }
@Override public boolean useThreePhaseUpdates() { return useThreePhaseUpdates; }
@Override public boolean useDirectStorageApiRpc() { return useDirectStorageApiRpc; }
+ @Override public boolean useFastValueTensorImplementation() { return useFastValueTensorImplementation; }
@Override public Optional<AthenzDomain> athenzDomain() { return Optional.ofNullable(athenzDomain); }
@Override public Optional<ApplicationRoles> applicationRoles() { return Optional.ofNullable(applicationRoles); }
@Override public String responseSequencerType() { return responseSequencerType; }
@@ -138,6 +140,11 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea
return this;
}
+ public TestProperties setUseFastValueTensorImplementation(boolean useFastValueTensorImplementation) {
+ this.useFastValueTensorImplementation = useFastValueTensorImplementation;
+ return this;
+ }
+
public TestProperties setApplicationId(ApplicationId applicationId) {
this.applicationId = applicationId;
return this;
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java
index f8932b415b1..14fbeb17aaf 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java
@@ -155,6 +155,7 @@ public class ClusterControllerContainer extends Container implements
}
builder.enabled(ctx.reindexing().enabled());
+ builder.windowSizeIncrement(ctx.windowSizeIncrement());
for (String clusterId : ctx.clusterIds()) {
ReindexingConfig.Clusters.Builder clusterBuilder = new ReindexingConfig.Clusters.Builder();
for (NewDocumentType type : ctx.documentTypesForCluster(clusterId)) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java
index 63fc0b4515f..3fe6ce3ff27 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainerCluster.java
@@ -35,7 +35,7 @@ public class ClusterControllerContainerCluster extends ContainerCluster<ClusterC
Reindexing reindexing = deployState.featureFlags().enableAutomaticReindexing()
? deployState.reindexing().orElse(Reindexing.DISABLED_INSTANCE)
: Reindexing.DISABLED_INSTANCE;
- return new ReindexingContext(reindexing);
+ return new ReindexingContext(reindexing, deployState.featureFlags().reindexerWindowSizeIncrement());
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java
index 712498f78cb..7380b950fb2 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ReindexingContext.java
@@ -21,9 +21,11 @@ public class ReindexingContext {
private final Object monitor = new Object();
private final Map<String, Set<NewDocumentType>> documentTypesPerCluster = new HashMap<>();
private final Reindexing reindexing;
+ private final double windowSizeIncrement;
- public ReindexingContext(Reindexing reindexing) {
+ public ReindexingContext(Reindexing reindexing, double windowSizeIncrement) {
this.reindexing = Objects.requireNonNull(reindexing);
+ this.windowSizeIncrement = windowSizeIncrement;
}
public void addDocumentType(String clusterId, NewDocumentType type) {
@@ -46,4 +48,7 @@ public class ReindexingContext {
}
public Reindexing reindexing() { return reindexing; }
+
+ public double windowSizeIncrement() { return windowSizeIncrement; }
+
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java
index 4b82ba92b0e..1998be3c262 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java
@@ -220,6 +220,8 @@ public class VespaMetricSet {
addMetric(metrics, "jdisc.http.filtering.response.handled", List.of("rate"));
addMetric(metrics, "jdisc.http.filtering.response.unhandled", List.of("rate"));
+ addMetric(metrics, "jdisc.application.failed_component_graphs", List.of("rate"));
+
return metrics;
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
index b4ad8cb1267..bc1d138b6d5 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentSearchCluster.java
@@ -267,7 +267,7 @@ public class ContentSearchCluster extends AbstractConfigProducer implements Prot
TransactionLogServer tls;
Optional<Tuning> tuning = Optional.ofNullable(this.tuning);
if (element == null) {
- searchNode = SearchNode.create(parent, "" + node.getDistributionKey(), node.getDistributionKey(), spec,
+ searchNode = SearchNode.create(deployState.getProperties(), parent, "" + node.getDistributionKey(), node.getDistributionKey(), spec,
clusterName, node, flushOnShutdown, tuning, resourceLimits, parentGroup.isHosted(), combined);
searchNode.setHostResource(node.getHostResource());
searchNode.initService(deployState.getDeployLogger());
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java b/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java
index 16302ddff49..9d3505e932f 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/search/SearchNode.java
@@ -69,6 +69,7 @@ public class SearchNode extends AbstractService implements
private AbstractService serviceLayerService;
private final Optional<Tuning> tuning;
private final Optional<ResourceLimits> resourceLimits;
+ private final boolean useFastValueTensorImplementation;
/** Whether this search node is co-located with a container node on a hosted system */
private final boolean combined;
@@ -99,31 +100,31 @@ public class SearchNode extends AbstractService implements
@Override
protected SearchNode doBuild(DeployState deployState, AbstractConfigProducer ancestor, Element producerSpec) {
- return new SearchNode(ancestor, name, contentNode.getDistributionKey(), nodeSpec, clusterName, contentNode,
+ return new SearchNode(deployState.getProperties(), ancestor, name, contentNode.getDistributionKey(), nodeSpec, clusterName, contentNode,
flushOnShutdown, tuning, resourceLimits, deployState.isHosted(), combined);
}
}
- public static SearchNode create(AbstractConfigProducer parent, String name, int distributionKey, NodeSpec nodeSpec,
+ public static SearchNode create(ModelContext.Properties props, AbstractConfigProducer parent, String name, int distributionKey, NodeSpec nodeSpec,
String clusterName, AbstractService serviceLayerService, boolean flushOnShutdown,
Optional<Tuning> tuning, Optional<ResourceLimits> resourceLimits, boolean isHostedVespa,
boolean combined) {
- return new SearchNode(parent, name, distributionKey, nodeSpec, clusterName, serviceLayerService,
+ return new SearchNode(props, parent, name, distributionKey, nodeSpec, clusterName, serviceLayerService,
flushOnShutdown, tuning, resourceLimits, isHostedVespa, combined);
}
- private SearchNode(AbstractConfigProducer parent, String name, int distributionKey, NodeSpec nodeSpec,
+ private SearchNode(ModelContext.Properties props, AbstractConfigProducer parent, String name, int distributionKey, NodeSpec nodeSpec,
String clusterName, AbstractService serviceLayerService, boolean flushOnShutdown,
Optional<Tuning> tuning, Optional<ResourceLimits> resourceLimits, boolean isHostedVespa,
boolean combined) {
- this(parent, name, nodeSpec, clusterName, flushOnShutdown, tuning, resourceLimits, isHostedVespa, combined);
+ this(props, parent, name, nodeSpec, clusterName, flushOnShutdown, tuning, resourceLimits, isHostedVespa, combined);
this.distributionKey = distributionKey;
this.serviceLayerService = serviceLayerService;
setPropertiesElastic(clusterName, distributionKey);
}
- private SearchNode(AbstractConfigProducer parent, String name, NodeSpec nodeSpec, String clusterName,
+ private SearchNode(ModelContext.Properties props, AbstractConfigProducer parent, String name, NodeSpec nodeSpec, String clusterName,
boolean flushOnShutdown, Optional<Tuning> tuning, Optional<ResourceLimits> resourceLimits, boolean isHostedVespa,
boolean combined) {
super(parent, name);
@@ -141,6 +142,7 @@ public class SearchNode extends AbstractService implements
// Properties are set in DomSearchBuilder
this.tuning = tuning;
this.resourceLimits = resourceLimits;
+ this.useFastValueTensorImplementation = props.featureFlags().useFastValueTensorImplementation();
}
private void setPropertiesElastic(String clusterName, int distributionKey) {
@@ -295,6 +297,9 @@ public class SearchNode extends AbstractService implements
tuning.ifPresent(t -> t.getConfig(builder));
resourceLimits.ifPresent(l -> l.getConfig(builder));
}
+ if (useFastValueTensorImplementation) {
+ builder.tensor_implementation(ProtonConfig.Tensor_implementation.FAST_VALUE);
+ }
}
@Override
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/search/test/SearchNodeTest.java b/config-model/src/test/java/com/yahoo/vespa/model/search/test/SearchNodeTest.java
index e270c81fe78..e4dabfaddae 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/search/test/SearchNodeTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/search/test/SearchNodeTest.java
@@ -53,7 +53,7 @@ public class SearchNodeTest {
private static SearchNode createSearchNode(MockRoot root, String name, int distributionKey,
NodeSpec nodeSpec, boolean flushOnShutDown, boolean isHosted, boolean combined) {
- return SearchNode.create(root, name, distributionKey, nodeSpec, "mycluster", null, flushOnShutDown, Optional.empty(), Optional.empty(), isHosted, combined);
+ return SearchNode.create(root.getDeployState().getProperties(), root, name, distributionKey, nodeSpec, "mycluster", null, flushOnShutDown, Optional.empty(), Optional.empty(), isHosted, combined);
}
private static SearchNode createSearchNode(MockRoot root) {
diff --git a/configdefinitions/src/vespa/reindexing.def b/configdefinitions/src/vespa/reindexing.def
index e020aec3f65..93dc767fed0 100644
--- a/configdefinitions/src/vespa/reindexing.def
+++ b/configdefinitions/src/vespa/reindexing.def
@@ -6,13 +6,16 @@ namespace=vespa.config.content.reindexing
# Whether reindexing should run at all
enabled bool default=false
-# TODO jonmv: remove after 7.310 is gone
+# TODO jonmv: remove after 7.324 is gone
# The name of the content cluster to reindex documents from
clusterName string default=""
-# TODO jonmv: remove after 7.310 is gone
+# TODO jonmv: remove after 7.324 is gone
# Epoch millis after which latest reprocessing may begin, per document type
status{}.readyAtMillis long
# Epoch millis after which latest reprocessing may begin, per document type, per cluster
clusters{}.documentTypes{}.readyAtMillis long
+
+# Window size increment used for the dynamic throttling policy of the reindexing visitor session
+windowSizeIncrement double default=0.2
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
index 4a6fb4bd6bf..2d96c92bd88 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
@@ -149,9 +149,11 @@ public class ModelContextImpl implements ModelContext {
public static class FeatureFlags implements ModelContext.FeatureFlags {
private final boolean enableAutomaticReindexing;
+ private final double reindexerWindowSizeIncrement;
private final double defaultTermwiseLimit;
private final boolean useThreePhaseUpdates;
private final boolean useDirectStorageApiRpc;
+ private final boolean useFastValueTensorImplementation;
private final String feedSequencer;
private final String responseSequencer;
private final int numResponseThreads;
@@ -166,26 +168,30 @@ public class ModelContextImpl implements ModelContext {
public FeatureFlags(FlagSource source, ApplicationId appId) {
this.enableAutomaticReindexing = flagValue(source, appId, Flags.ENABLE_AUTOMATIC_REINDEXING);
- defaultTermwiseLimit = flagValue(source, appId, Flags.DEFAULT_TERM_WISE_LIMIT);
- useThreePhaseUpdates = flagValue(source, appId, Flags.USE_THREE_PHASE_UPDATES);
- useDirectStorageApiRpc = flagValue(source, appId, Flags.USE_DIRECT_STORAGE_API_RPC);
- feedSequencer = flagValue(source, appId, Flags.FEED_SEQUENCER_TYPE);
- responseSequencer = flagValue(source, appId, Flags.RESPONSE_SEQUENCER_TYPE);
- numResponseThreads = flagValue(source, appId, Flags.RESPONSE_NUM_THREADS);
- skipCommunicationManagerThread = flagValue(source, appId, Flags.SKIP_COMMUNICATIONMANAGER_THREAD);
- skipMbusRequestThread = flagValue(source, appId, Flags.SKIP_MBUS_REQUEST_THREAD);
- skipMbusReplyThread = flagValue(source, appId, Flags.SKIP_MBUS_REPLY_THREAD);
+ this.reindexerWindowSizeIncrement = flagValue(source, appId, Flags.REINDEXER_WINDOW_SIZE_INCREMENT);
+ this.defaultTermwiseLimit = flagValue(source, appId, Flags.DEFAULT_TERM_WISE_LIMIT);
+ this.useThreePhaseUpdates = flagValue(source, appId, Flags.USE_THREE_PHASE_UPDATES);
+ this.useDirectStorageApiRpc = flagValue(source, appId, Flags.USE_DIRECT_STORAGE_API_RPC);
+ this.useFastValueTensorImplementation = flagValue(source, appId, Flags.USE_FAST_VALUE_TENSOR_IMPLEMENTATION);
+ this.feedSequencer = flagValue(source, appId, Flags.FEED_SEQUENCER_TYPE);
+ this.responseSequencer = flagValue(source, appId, Flags.RESPONSE_SEQUENCER_TYPE);
+ this.numResponseThreads = flagValue(source, appId, Flags.RESPONSE_NUM_THREADS);
+ this.skipCommunicationManagerThread = flagValue(source, appId, Flags.SKIP_COMMUNICATIONMANAGER_THREAD);
+ this.skipMbusRequestThread = flagValue(source, appId, Flags.SKIP_MBUS_REQUEST_THREAD);
+ this.skipMbusReplyThread = flagValue(source, appId, Flags.SKIP_MBUS_REPLY_THREAD);
this.useAccessControlTlsHandshakeClientAuth = flagValue(source, appId, Flags.USE_ACCESS_CONTROL_CLIENT_AUTHENTICATION);
- useAsyncMessageHandlingOnSchedule = flagValue(source, appId, Flags.USE_ASYNC_MESSAGE_HANDLING_ON_SCHEDULE);
- contentNodeBucketDBStripeBits = flagValue(source, appId, Flags.CONTENT_NODE_BUCKET_DB_STRIPE_BITS);
- mergeChunkSize = flagValue(source, appId, Flags.MERGE_CHUNK_SIZE);
- feedConcurrency = flagValue(source, appId, Flags.FEED_CONCURRENCY);
+ this.useAsyncMessageHandlingOnSchedule = flagValue(source, appId, Flags.USE_ASYNC_MESSAGE_HANDLING_ON_SCHEDULE);
+ this.contentNodeBucketDBStripeBits = flagValue(source, appId, Flags.CONTENT_NODE_BUCKET_DB_STRIPE_BITS);
+ this.mergeChunkSize = flagValue(source, appId, Flags.MERGE_CHUNK_SIZE);
+ this.feedConcurrency = flagValue(source, appId, Flags.FEED_CONCURRENCY);
}
@Override public boolean enableAutomaticReindexing() { return enableAutomaticReindexing; }
+ @Override public double reindexerWindowSizeIncrement() { return reindexerWindowSizeIncrement; }
@Override public double defaultTermwiseLimit() { return defaultTermwiseLimit; }
@Override public boolean useThreePhaseUpdates() { return useThreePhaseUpdates; }
@Override public boolean useDirectStorageApiRpc() { return useDirectStorageApiRpc; }
+ @Override public boolean useFastValueTensorImplementation() { return useFastValueTensorImplementation; }
@Override public String feedSequencerType() { return feedSequencer; }
@Override public String responseSequencerType() { return responseSequencer; }
@Override public int defaultNumResponseThreads() { return numResponseThreads; }
@@ -232,6 +238,7 @@ public class ModelContextImpl implements ModelContext {
private final double defaultTermwiseLimit;
private final boolean useThreePhaseUpdates;
private final boolean useDirectStorageApiRpc;
+ private final boolean useFastValueTensorImplementation;
private final String feedSequencer;
private final String responseSequencer;
private final int numResponseThreads;
@@ -278,6 +285,7 @@ public class ModelContextImpl implements ModelContext {
defaultTermwiseLimit = flagValue(flagSource, applicationId, Flags.DEFAULT_TERM_WISE_LIMIT);
useThreePhaseUpdates = flagValue(flagSource, applicationId, Flags.USE_THREE_PHASE_UPDATES);
useDirectStorageApiRpc = flagValue(flagSource, applicationId, Flags.USE_DIRECT_STORAGE_API_RPC);
+ useFastValueTensorImplementation = flagValue(flagSource, applicationId, Flags.USE_FAST_VALUE_TENSOR_IMPLEMENTATION);
feedSequencer = flagValue(flagSource, applicationId, Flags.FEED_SEQUENCER_TYPE);
responseSequencer = flagValue(flagSource, applicationId, Flags.RESPONSE_SEQUENCER_TYPE);
numResponseThreads = flagValue(flagSource, applicationId, Flags.RESPONSE_NUM_THREADS);
@@ -349,6 +357,7 @@ public class ModelContextImpl implements ModelContext {
@Override public double defaultTermwiseLimit() { return defaultTermwiseLimit; }
@Override public boolean useThreePhaseUpdates() { return useThreePhaseUpdates; }
@Override public boolean useDirectStorageApiRpc() { return useDirectStorageApiRpc; }
+ @Override public boolean useFastValueTensorImplementation() { return useFastValueTensorImplementation; }
@Override public String feedSequencerType() { return feedSequencer; }
@Override public String responseSequencerType() { return responseSequencer; }
@Override public int defaultNumResponseThreads() { return numResponseThreads; }
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 aa709b3bf37..7ccdf161f82 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
@@ -78,9 +78,9 @@ public class ApplicationPackageMaintainer extends ConfigServerMaintainer {
}
@Override
- public void close() {
+ public void awaitShutdown() {
connectionPool.close();
- super.close();
+ super.awaitShutdown();
}
private void createLocalSessionIfMissing(ApplicationId applicationId, long sessionId) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java
index 21462bc4fec..837f025ec2b 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java
@@ -4,7 +4,7 @@ package com.yahoo.vespa.config.server.maintenance;
import com.google.inject.Inject;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.component.AbstractComponent;
-import com.yahoo.jdisc.Metric;
+import com.yahoo.concurrent.maintenance.Maintainer;
import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.ConfigServerBootstrap;
import com.yahoo.vespa.config.server.application.ConfigConvergenceChecker;
@@ -13,6 +13,8 @@ import com.yahoo.vespa.flags.FlagSource;
import java.time.Clock;
import java.time.Duration;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* Maintenance jobs of the config server.
@@ -24,11 +26,7 @@ import java.time.Duration;
*/
public class ConfigServerMaintenance extends AbstractComponent {
- private final TenantsMaintainer tenantsMaintainer;
- private final FileDistributionMaintainer fileDistributionMaintainer;
- private final SessionsMaintainer sessionsMaintainer;
- private final ApplicationPackageMaintainer applicationPackageMaintainer;
- private final ReindexingMaintainer reindexingMaintainer;
+ private final List<Maintainer> maintainers = new CopyOnWriteArrayList<>();
@Inject
public ConfigServerMaintenance(ConfigServerBootstrap configServerBootstrap,
@@ -38,20 +36,17 @@ public class ConfigServerMaintenance extends AbstractComponent {
FlagSource flagSource,
ConfigConvergenceChecker convergence) {
DefaultTimes defaults = new DefaultTimes(configserverConfig);
- tenantsMaintainer = new TenantsMaintainer(applicationRepository, curator, flagSource, defaults.defaultInterval, Clock.systemUTC());
- fileDistributionMaintainer = new FileDistributionMaintainer(applicationRepository, curator, defaults.defaultInterval, flagSource);
- sessionsMaintainer = new SessionsMaintainer(applicationRepository, curator, Duration.ofSeconds(30), flagSource);
- applicationPackageMaintainer = new ApplicationPackageMaintainer(applicationRepository, curator, Duration.ofSeconds(30), flagSource);
- reindexingMaintainer = new ReindexingMaintainer(applicationRepository, curator, flagSource, Duration.ofMinutes(3), convergence, Clock.systemUTC());
+ maintainers.add(new TenantsMaintainer(applicationRepository, curator, flagSource, defaults.defaultInterval, Clock.systemUTC()));
+ maintainers.add(new FileDistributionMaintainer(applicationRepository, curator, defaults.defaultInterval, flagSource));
+ maintainers.add(new SessionsMaintainer(applicationRepository, curator, Duration.ofSeconds(30), flagSource));
+ maintainers.add(new ApplicationPackageMaintainer(applicationRepository, curator, Duration.ofSeconds(30), flagSource));
+ maintainers.add(new ReindexingMaintainer(applicationRepository, curator, flagSource, Duration.ofMinutes(3), convergence, Clock.systemUTC()));
}
@Override
public void deconstruct() {
- fileDistributionMaintainer.close();
- sessionsMaintainer.close();
- applicationPackageMaintainer.close();
- tenantsMaintainer.close();
- reindexingMaintainer.close();
+ maintainers.forEach(Maintainer::shutdown);
+ maintainers.forEach(Maintainer::awaitShutdown);
}
/*
diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java b/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java
index f32d7dfbb02..835326e0904 100644
--- a/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java
+++ b/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java
@@ -9,7 +9,6 @@ import com.yahoo.component.provider.ComponentRegistry;
import com.yahoo.concurrent.DaemonThreadFactory;
import com.yahoo.config.ConfigInstance;
import com.yahoo.config.subscription.ConfigInterruptedException;
-import com.yahoo.config.subscription.ConfigSubscriber;
import com.yahoo.container.Container;
import com.yahoo.container.QrConfig;
import com.yahoo.container.core.ChainsConfig;
@@ -38,7 +37,6 @@ import com.yahoo.jrt.Supervisor;
import com.yahoo.jrt.Transport;
import com.yahoo.jrt.slobrok.api.Register;
import com.yahoo.jrt.slobrok.api.SlobrokList;
-import java.util.logging.Level;
import com.yahoo.log.LogSetup;
import com.yahoo.messagebus.network.rpc.SlobrokConfigSubscriber;
import com.yahoo.net.HostName;
@@ -271,11 +269,12 @@ public final class ConfiguredApplication implements Application {
} catch (ConfigInterruptedException e) {
break;
} catch (Exception | LinkageError e) { // LinkageError: OSGi problems
+ tryReportFailedComponentGraphConstructionMetric(configurer, e);
log.log(Level.SEVERE,
"Reconfiguration failed, your application package must be fixed, unless this is a " +
"JNI reload issue: " + Exceptions.toMessageString(e), e);
} catch (Error e) {
- com.yahoo.protect.Process.logAndDie("java.lang.Error on reconfiguration: We are probably in " +
+ com.yahoo.protect.Process.logAndDie("java.lang.Error on reconfiguration: We are probably in " +
"a bad state and will terminate", e);
}
}
@@ -284,6 +283,18 @@ public final class ConfiguredApplication implements Application {
reconfigurerThread.start();
}
+ private static void tryReportFailedComponentGraphConstructionMetric(HandlersConfigurerDi configurer, Throwable error) {
+ try {
+ // We need the Metric instance from previous component graph to report metric values
+ // Metric may not be available if this is the initial component graph (since metric wiring is done through the config model)
+ Metric metric = configurer.getComponent(Metric.class);
+ Metric.Context metricContext = metric.createContext(Map.of("exception", error.getClass().getSimpleName()));
+ metric.add("jdisc.application.failed_component_graphs", 1L, metricContext);
+ } catch (Exception e) {
+ log.log(Level.WARNING, "Failed to report metric for failed component graph: " + e.getMessage(), e);
+ }
+ }
+
private static void installServerProviders(ContainerBuilder builder) {
List<ServerProvider> serverProviders = Container.get().getServerProviderRegistry().allComponents();
for (ServerProvider server : serverProviders) {
diff --git a/container-search-gui/src/main/resources/gui/editarea/edit_area/plugins/autocompletion/autocompletion.js b/container-search-gui/src/main/resources/gui/editarea/edit_area/plugins/autocompletion/autocompletion.js
index 5531a2a4f69..762e0882ff4 100644
--- a/container-search-gui/src/main/resources/gui/editarea/edit_area/plugins/autocompletion/autocompletion.js
+++ b/container-search-gui/src/main/resources/gui/editarea/edit_area/plugins/autocompletion/autocompletion.js
@@ -277,7 +277,7 @@ var EditArea_autocompletion= {
nbMatch = 0;
for( i =0; i<limit ; i++ )
{
- if( line_string.substring( limit - i - 1, limit ) == content.substring( 0, i + 1 ) )
+ if( line_string.substring( limit - i - 1, limit ).toUpperCase() === content.substring( 0, i + 1 ).toUpperCase() )
nbMatch = i + 1;
}
// if characters match, we should include them in the selection that will be replaced
diff --git a/container-search-gui/src/main/resources/gui/editarea/edit_area/reg_syntax/yql.js b/container-search-gui/src/main/resources/gui/editarea/edit_area/reg_syntax/yql.js
index 0a7dae862f3..545927a833a 100755
--- a/container-search-gui/src/main/resources/gui/editarea/edit_area/reg_syntax/yql.js
+++ b/container-search-gui/src/main/resources/gui/editarea/edit_area/reg_syntax/yql.js
@@ -72,7 +72,7 @@ editAreaLoader.load_syntax["yql"] = {
,"CASE_SENSITIVE": false
,"MAX_TEXT_LENGTH": 50 // the maximum length of the text being analyzed before the cursor position
,"KEYWORDS": {
- '': [ // the prefix of thoses items
+ '': [ // the prefix of these items
/**
* 0 : the keyword the user is typing
* 1 : (optionnal) the string inserted in code ("{@}" being the new position of the cursor, "§" beeing the equivalent to the value the typed string indicated if the previous )
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java
index 8f91a8127bd..57dafcd3291 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchive.java
@@ -12,6 +12,7 @@ import com.yahoo.vespa.flags.FetchVector;
import com.yahoo.vespa.flags.FlagId;
import com.yahoo.vespa.flags.json.DimensionHelper;
import com.yahoo.vespa.flags.json.FlagData;
+import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import java.io.BufferedInputStream;
import java.io.IOException;
@@ -71,7 +72,7 @@ public class SystemFlagsDataArchive {
if (!entry.isDirectory() && name.startsWith("flags/")) {
Path filePath = Paths.get(name);
String rawData = new String(zipIn.readAllBytes(), StandardCharsets.UTF_8);
- addFile(builder, rawData, filePath);
+ addFile(builder, rawData, filePath, Set.of());
}
}
return builder.build();
@@ -80,7 +81,14 @@ public class SystemFlagsDataArchive {
}
}
- public static SystemFlagsDataArchive fromDirectory(Path directory) {
+ public static SystemFlagsDataArchive fromDirectoryAndSystem(Path directory, ZoneRegistry systemDefinition) {
+ return fromDirectory(directory, systemDefinition);
+ }
+
+ public static SystemFlagsDataArchive fromDirectory(Path directory) { return fromDirectory(directory, null); }
+
+ private static SystemFlagsDataArchive fromDirectory(Path directory, ZoneRegistry systemDefinition) {
+ Set<String> filenamesForSystem = getFilenamesForSystem(systemDefinition);
Path root = directory.toAbsolutePath();
Path flagsDirectory = directory.resolve("flags");
if (!Files.isDirectory(flagsDirectory)) {
@@ -93,7 +101,7 @@ public class SystemFlagsDataArchive {
if (!Files.isDirectory(absolutePath) &&
relativePath.startsWith("flags")) {
String rawData = uncheck(() -> Files.readString(absolutePath, StandardCharsets.UTF_8));
- addFile(builder, rawData, relativePath);
+ addFile(builder, rawData, relativePath, filenamesForSystem);
}
});
return builder.build();
@@ -102,6 +110,7 @@ public class SystemFlagsDataArchive {
}
}
+
public void toZip(OutputStream out) {
ZipOutputStream zipOut = new ZipOutputStream(out);
files.forEach((flagId, fileMap) -> {
@@ -152,11 +161,21 @@ public class SystemFlagsDataArchive {
});
}
- private static void addFile(Builder builder, String rawData, Path filePath) {
+ private static Set<String> getFilenamesForSystem(ZoneRegistry systemDefinition) {
+ if (systemDefinition == null) return Set.of();
+ return FlagsTarget.getAllTargetsInSystem(systemDefinition).stream()
+ .flatMap(target -> target.flagDataFilesPrioritized().stream())
+ .collect(Collectors.toSet());
+ }
+
+ private static void addFile(Builder builder, String rawData, Path filePath, Set<String> filenamesForSystem) {
String filename = filePath.getFileName().toString();
if (filename.startsWith(".")) {
return; // Ignore files starting with '.'
}
+ if (!filenamesForSystem.isEmpty() && !filenamesForSystem.contains(filename)) {
+ return; // Ignore files irrelevant for system
+ }
if (!filename.endsWith(".json")) {
throw new IllegalArgumentException(String.format("Only JSON files are allowed in 'flags/' directory (found '%s')", filePath.toString()));
}
diff --git a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java
index 771e42e85f9..d29657035c4 100644
--- a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java
+++ b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/systemflags/v1/SystemFlagsDataArchiveTest.java
@@ -2,16 +2,20 @@
package com.yahoo.vespa.hosted.controller.api.systemflags.v1;
+import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
+import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.config.provision.zone.ZoneList;
import com.yahoo.text.JSON;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.flags.FetchVector;
import com.yahoo.vespa.flags.FlagId;
import com.yahoo.vespa.flags.RawFlag;
import com.yahoo.vespa.flags.json.FlagData;
+import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -26,6 +30,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
@@ -35,6 +40,9 @@ import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
/**
* @author bjorncs
@@ -52,6 +60,7 @@ public class SystemFlagsDataArchiveTest {
public final ExpectedException expectedException = ExpectedException.none();
private static final FlagsTarget mainControllerTarget = FlagsTarget.forController(SYSTEM);
+ private static final FlagsTarget cdControllerTarget = FlagsTarget.forController(SystemName.cd);
private static final FlagsTarget prodUsWestCfgTarget = createConfigserverTarget(Environment.prod, "us-west-1");
private static final FlagsTarget prodUsEast3CfgTarget = createConfigserverTarget(Environment.prod, "us-east-3");
private static final FlagsTarget devUsEast1CfgTarget = createConfigserverTarget(Environment.dev, "us-east-1");
@@ -260,6 +269,30 @@ public class SystemFlagsDataArchiveTest {
}
}
+ @Test
+ public void ignores_files_not_related_to_specified_system_definition() {
+ ZoneRegistry registry = createZoneRegistryMock();
+ Path testDirectory = Paths.get("src/test/resources/system-flags-for-multiple-systems/");
+ var archive = SystemFlagsDataArchive.fromDirectoryAndSystem(testDirectory, registry);
+ assertFlagDataHasValue(archive, MY_TEST_FLAG, cdControllerTarget, "default"); // Would be 'cd.controller' if files for CD system were included
+ assertFlagDataHasValue(archive, MY_TEST_FLAG, mainControllerTarget, "default");
+ assertFlagDataHasValue(archive, MY_TEST_FLAG, prodUsWestCfgTarget, "main.prod.us-west-1");
+ }
+
+ @SuppressWarnings("unchecked") // workaround for mocking a method for generic return type
+ private static ZoneRegistry createZoneRegistryMock() {
+ // Cannot use the standard registry mock as it's located in controller-server module
+ ZoneRegistry registryMock = mock(ZoneRegistry.class);
+ when(registryMock.system()).thenReturn(SystemName.main);
+ when(registryMock.getConfigServerVipUri(any())).thenReturn(URI.create("http://localhost:8080/"));
+ when(registryMock.getConfigServerHttpsIdentity(any())).thenReturn(new AthenzService("domain", "servicename"));
+ ZoneList zoneListMock = mock(ZoneList.class);
+ when(zoneListMock.reachable()).thenReturn(zoneListMock);
+ when(zoneListMock.zones()).thenReturn((List)List.of(new SimpleZone("prod.us-west-1"), new SimpleZone("prod.us-east-3")));
+ when(registryMock.zones()).thenReturn(zoneListMock);
+ return registryMock;
+ }
+
private static void assertArchiveReturnsCorrectTestFlagDataForTarget(SystemFlagsDataArchive archive) {
assertFlagDataHasValue(archive, MY_TEST_FLAG, mainControllerTarget, "main.controller");
assertFlagDataHasValue(archive, MY_TEST_FLAG, prodUsWestCfgTarget, "main.prod.us-west-1");
@@ -286,4 +319,14 @@ public class SystemFlagsDataArchiveTest {
.collect(toList());
}
+ private static class SimpleZone implements ZoneApi {
+ final ZoneId zoneId;
+ SimpleZone(String zoneId) { this.zoneId = ZoneId.from(zoneId); }
+
+ @Override public SystemName getSystemName() { return SystemName.main; }
+ @Override public ZoneId getId() { return zoneId; }
+ @Override public CloudName getCloudName() { throw new UnsupportedOperationException(); }
+ @Override public String getCloudNativeRegionName() { throw new UnsupportedOperationException(); }
+ }
+
} \ No newline at end of file
diff --git a/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/cd.controller.json b/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/cd.controller.json
new file mode 100644
index 00000000000..ce3cdd43889
--- /dev/null
+++ b/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/cd.controller.json
@@ -0,0 +1,8 @@
+{
+ "id" : "my-test-flag",
+ "rules" : [
+ {
+ "value" : "cd.controller"
+ }
+ ]
+} \ No newline at end of file
diff --git a/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/default.json b/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/default.json
new file mode 100644
index 00000000000..5924eb860c0
--- /dev/null
+++ b/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/default.json
@@ -0,0 +1,8 @@
+{
+ "id" : "my-test-flag",
+ "rules" : [
+ {
+ "value" : "default"
+ }
+ ]
+} \ No newline at end of file
diff --git a/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/main.prod.us-west-1.json b/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/main.prod.us-west-1.json
new file mode 100644
index 00000000000..45989773df8
--- /dev/null
+++ b/controller-api/src/test/resources/system-flags-for-multiple-systems/flags/my-test-flag/main.prod.us-west-1.json
@@ -0,0 +1,8 @@
+{
+ "id" : "my-test-flag",
+ "rules" : [
+ {
+ "value" : "main.prod.us-west-1"
+ }
+ ]
+} \ No newline at end of file
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 1dd84cfc7b4..ff2a1963967 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
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.controller.maintenance;
import com.google.inject.Inject;
import com.yahoo.component.AbstractComponent;
+import com.yahoo.concurrent.maintenance.Maintainer;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.jdisc.Metric;
@@ -13,6 +14,7 @@ import java.time.temporal.TemporalUnit;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import static java.time.temporal.ChronoUnit.HOURS;
@@ -28,89 +30,47 @@ import static java.time.temporal.ChronoUnit.SECONDS;
*/
public class ControllerMaintenance extends AbstractComponent {
- private final DeploymentExpirer deploymentExpirer;
- private final DeploymentIssueReporter deploymentIssueReporter;
- private final MetricsReporter metricsReporter;
- private final OutstandingChangeDeployer outstandingChangeDeployer;
- private final VersionStatusUpdater versionStatusUpdater;
private final Upgrader upgrader;
- private final ReadyJobsTrigger readyJobsTrigger;
- private final DeploymentMetricsMaintainer deploymentMetricsMaintainer;
- private final ApplicationOwnershipConfirmer applicationOwnershipConfirmer;
- private final SystemUpgrader systemUpgrader;
- private final List<OsUpgrader> osUpgraders;
- private final OsVersionStatusUpdater osVersionStatusUpdater;
- private final JobRunner jobRunner;
- private final ContactInformationMaintainer contactInformationMaintainer;
- private final CostReportMaintainer costReportMaintainer;
- private final ResourceMeterMaintainer resourceMeterMaintainer;
- private final NameServiceDispatcher nameServiceDispatcher;
- private final CloudEventReporter cloudEventReporter;
- private final RotationStatusUpdater rotationStatusUpdater;
- private final ResourceTagMaintainer resourceTagMaintainer;
- private final SystemRoutingPolicyMaintainer systemRoutingPolicyMaintainer;
- private final ApplicationMetaDataGarbageCollector applicationMetaDataGarbageCollector;
- private final ContainerImageExpirer containerImageExpirer;
- private final HostSwitchUpdater hostSwitchUpdater;
+ private final List<Maintainer> maintainers = new CopyOnWriteArrayList<>();
@Inject
@SuppressWarnings("unused") // instantiated by Dependency Injection
public ControllerMaintenance(Controller controller, Metric metric) {
Intervals intervals = new Intervals(controller.system());
- deploymentExpirer = new DeploymentExpirer(controller, intervals.defaultInterval);
- deploymentIssueReporter = new DeploymentIssueReporter(controller, controller.serviceRegistry().deploymentIssues(), intervals.defaultInterval);
- metricsReporter = new MetricsReporter(controller, metric);
- outstandingChangeDeployer = new OutstandingChangeDeployer(controller, intervals.outstandingChangeDeployer);
- versionStatusUpdater = new VersionStatusUpdater(controller, intervals.versionStatusUpdater);
upgrader = new Upgrader(controller, intervals.defaultInterval);
- readyJobsTrigger = new ReadyJobsTrigger(controller, intervals.readyJobsTrigger);
- deploymentMetricsMaintainer = new DeploymentMetricsMaintainer(controller, intervals.deploymentMetricsMaintainer);
- applicationOwnershipConfirmer = new ApplicationOwnershipConfirmer(controller, intervals.applicationOwnershipConfirmer, controller.serviceRegistry().ownershipIssues());
- systemUpgrader = new SystemUpgrader(controller, intervals.systemUpgrader);
- jobRunner = new JobRunner(controller, intervals.jobRunner);
- osUpgraders = osUpgraders(controller, intervals.osUpgrader);
- osVersionStatusUpdater = new OsVersionStatusUpdater(controller, intervals.defaultInterval);
- contactInformationMaintainer = new ContactInformationMaintainer(controller, intervals.contactInformationMaintainer);
- nameServiceDispatcher = new NameServiceDispatcher(controller, intervals.nameServiceDispatcher);
- costReportMaintainer = new CostReportMaintainer(controller, intervals.costReportMaintainer, controller.serviceRegistry().costReportConsumer());
- resourceMeterMaintainer = new ResourceMeterMaintainer(controller, intervals.resourceMeterMaintainer, metric, controller.serviceRegistry().meteringService());
- cloudEventReporter = new CloudEventReporter(controller, intervals.cloudEventReporter, metric);
- rotationStatusUpdater = new RotationStatusUpdater(controller, intervals.defaultInterval);
- resourceTagMaintainer = new ResourceTagMaintainer(controller, intervals.resourceTagMaintainer, controller.serviceRegistry().resourceTagger());
- systemRoutingPolicyMaintainer = new SystemRoutingPolicyMaintainer(controller, intervals.systemRoutingPolicyMaintainer);
- applicationMetaDataGarbageCollector = new ApplicationMetaDataGarbageCollector(controller, intervals.applicationMetaDataGarbageCollector);
- containerImageExpirer = new ContainerImageExpirer(controller, intervals.containerImageExpirer);
- hostSwitchUpdater = new HostSwitchUpdater(controller, intervals.hostSwitchUpdater);
+ maintainers.add(upgrader);
+ maintainers.addAll(osUpgraders(controller, intervals.osUpgrader));
+ maintainers.add(new DeploymentExpirer(controller, intervals.defaultInterval));
+ maintainers.add(new DeploymentIssueReporter(controller, controller.serviceRegistry().deploymentIssues(), intervals.defaultInterval));
+ maintainers.add(new MetricsReporter(controller, metric));
+ maintainers.add(new OutstandingChangeDeployer(controller, intervals.outstandingChangeDeployer));
+ maintainers.add(new VersionStatusUpdater(controller, intervals.versionStatusUpdater));
+ maintainers.add(new ReadyJobsTrigger(controller, intervals.readyJobsTrigger));
+ maintainers.add(new DeploymentMetricsMaintainer(controller, intervals.deploymentMetricsMaintainer));
+ maintainers.add(new ApplicationOwnershipConfirmer(controller, intervals.applicationOwnershipConfirmer, controller.serviceRegistry().ownershipIssues()));
+ maintainers.add(new SystemUpgrader(controller, intervals.systemUpgrader));
+ maintainers.add(new JobRunner(controller, intervals.jobRunner));
+ maintainers.add(new OsVersionStatusUpdater(controller, intervals.defaultInterval));
+ maintainers.add(new ContactInformationMaintainer(controller, intervals.contactInformationMaintainer));
+ maintainers.add(new NameServiceDispatcher(controller, intervals.nameServiceDispatcher));
+ maintainers.add(new CostReportMaintainer(controller, intervals.costReportMaintainer, controller.serviceRegistry().costReportConsumer()));
+ maintainers.add(new ResourceMeterMaintainer(controller, intervals.resourceMeterMaintainer, metric, controller.serviceRegistry().meteringService()));
+ maintainers.add(new CloudEventReporter(controller, intervals.cloudEventReporter, metric));
+ maintainers.add(new RotationStatusUpdater(controller, intervals.defaultInterval));
+ maintainers.add(new ResourceTagMaintainer(controller, intervals.resourceTagMaintainer, controller.serviceRegistry().resourceTagger()));
+ maintainers.add(new SystemRoutingPolicyMaintainer(controller, intervals.systemRoutingPolicyMaintainer));
+ maintainers.add(new ApplicationMetaDataGarbageCollector(controller, intervals.applicationMetaDataGarbageCollector));
+ maintainers.add(new ContainerImageExpirer(controller, intervals.containerImageExpirer));
+ maintainers.add(new HostSwitchUpdater(controller, intervals.hostSwitchUpdater));
+ maintainers.add(new ReindexingTriggerer(controller, intervals.reindexingTriggerer));
}
public Upgrader upgrader() { return upgrader; }
@Override
public void deconstruct() {
- deploymentExpirer.close();
- deploymentIssueReporter.close();
- metricsReporter.close();
- outstandingChangeDeployer.close();
- versionStatusUpdater.close();
- upgrader.close();
- readyJobsTrigger.close();
- deploymentMetricsMaintainer.close();
- applicationOwnershipConfirmer.close();
- systemUpgrader.close();
- osUpgraders.forEach(ControllerMaintainer::close);
- osVersionStatusUpdater.close();
- jobRunner.close();
- contactInformationMaintainer.close();
- costReportMaintainer.close();
- resourceMeterMaintainer.close();
- nameServiceDispatcher.close();
- cloudEventReporter.close();
- rotationStatusUpdater.close();
- resourceTagMaintainer.close();
- systemRoutingPolicyMaintainer.close();
- applicationMetaDataGarbageCollector.close();
- containerImageExpirer.close();
- hostSwitchUpdater.close();
+ maintainers.forEach(Maintainer::shutdown);
+ maintainers.forEach(Maintainer::awaitShutdown);
}
/** Create one OS upgrader per cloud found in the zone registry of controller */
@@ -148,6 +108,7 @@ public class ControllerMaintenance extends AbstractComponent {
private final Duration applicationMetaDataGarbageCollector;
private final Duration containerImageExpirer;
private final Duration hostSwitchUpdater;
+ private final Duration reindexingTriggerer;
public Intervals(SystemName system) {
this.system = Objects.requireNonNull(system);
@@ -170,6 +131,7 @@ public class ControllerMaintenance extends AbstractComponent {
this.applicationMetaDataGarbageCollector = duration(12, HOURS);
this.containerImageExpirer = duration(2, HOURS);
this.hostSwitchUpdater = duration(12, HOURS);
+ this.reindexingTriggerer = duration(1, HOURS);
}
private Duration duration(long amount, TemporalUnit unit) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunner.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunner.java
index f08a23ab8ed..d6739581c79 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunner.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunner.java
@@ -56,9 +56,14 @@ public class JobRunner extends ControllerMaintainer {
}
@Override
- public void close() {
- super.close();
+ public void shutdown() {
+ super.shutdown();
executors.shutdown();
+ }
+
+ @Override
+ public void awaitShutdown() {
+ super.awaitShutdown();
try {
if ( ! executors.awaitTermination(10, TimeUnit.SECONDS)) {
executors.shutdownNow();
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
new file mode 100644
index 00000000000..96e9f087a67
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java
@@ -0,0 +1,79 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.maintenance;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.Application;
+import com.yahoo.vespa.hosted.controller.Controller;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.ApplicationReindexing;
+import com.yahoo.vespa.hosted.controller.application.Deployment;
+import com.yahoo.yolean.Exceptions;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Periodically triggers reindexing for all hosted Vespa applications.
+ *
+ * Since reindexing is meant to be a background effort, exactly when things are triggered is not critical,
+ * and a hash of id of each deployment is used to spread triggering out across the reindexing period.
+ * Only deployments within a window of opportunity of two maintainer periods are considered in each run.
+ * Reindexing is triggered for a deployment if it was last triggered more than half a period ago, and
+ * if no reindexing is currently ongoing. This means an application may skip reindexing during a period
+ * if it happens to reindex, e.g., a particular document type in its window of opportunity. This is fine.
+ *
+ * @author jonmv
+ */
+public class ReindexingTriggerer extends ControllerMaintainer {
+
+ static final Duration reindexingPeriod = Duration.ofDays(91); // 13 weeks — four times a year.
+
+ private static final Logger log = Logger.getLogger(ReindexingTriggerer.class.getName());
+
+ public ReindexingTriggerer(Controller controller, Duration duration) {
+ super(controller, duration);
+ }
+
+ @Override
+ protected boolean maintain() {
+ try {
+ Instant now = controller().clock().instant();
+ for (Application application : controller().applications().asList())
+ application.productionDeployments().forEach((name, deployments) -> {
+ ApplicationId id = application.id().instance(name);
+ for (Deployment deployment : deployments)
+ if ( inWindowOfOpportunity(now, interval(), id, deployment.zone())
+ && reindexingIsReady(controller().applications().applicationReindexing(id, deployment.zone()), now))
+ controller().applications().reindex(id, deployment.zone(), List.of(), List.of());
+ });
+ return true;
+ }
+ catch (RuntimeException e) {
+ log.log(Level.WARNING, "Failed to trigger reindexing: " + Exceptions.toMessageString(e));
+ return false;
+ }
+ }
+
+ static boolean inWindowOfOpportunity(Instant now, Duration interval, ApplicationId id, ZoneId zone) {
+ long lastPeriodStartMillis = now.toEpochMilli() - (now.toEpochMilli() % reindexingPeriod.toMillis());
+ Instant windowCenter = Instant.ofEpochMilli(lastPeriodStartMillis).plus(offset(id, zone));
+ return windowCenter.minus(interval).isBefore(now) && now.isBefore(windowCenter.plus(interval));
+ }
+
+ static Duration offset(ApplicationId id, ZoneId zone) {
+ double relativeOffset = ((id.serializedForm() + zone.value()).hashCode() & (-1 >>> 1)) / (double) (-1 >>> 1);
+ return Duration.ofMillis((long) (reindexingPeriod.toMillis() * relativeOffset));
+ }
+
+ static boolean reindexingIsReady(ApplicationReindexing reindexing, Instant now) {
+ if (reindexing.clusters().values().stream().flatMap(cluster -> cluster.ready().values().stream())
+ .anyMatch(status -> status.startedAt().isPresent() && status.endedAt().isEmpty()))
+ return false;
+
+ return reindexing.common().readyAt().orElse(Instant.EPOCH).isBefore(now.minus(reindexingPeriod.dividedBy(2)));
+ }
+
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java
new file mode 100644
index 00000000000..c12b82524e4
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java
@@ -0,0 +1,78 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.maintenance;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.ApplicationReindexing;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.ApplicationReindexing.Cluster;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.ApplicationReindexing.Status;
+import org.junit.Test;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Map;
+
+import static com.yahoo.vespa.hosted.controller.maintenance.ReindexingTriggerer.inWindowOfOpportunity;
+import static com.yahoo.vespa.hosted.controller.maintenance.ReindexingTriggerer.reindexingIsReady;
+import static com.yahoo.vespa.hosted.controller.maintenance.ReindexingTriggerer.reindexingPeriod;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ReindexingTriggererTest {
+
+ @Test
+ public void testWindowOfOpportunity() {
+ Duration interval = Duration.ofHours(1);
+ Instant now = Instant.now();
+ Instant doom = now.plus(ReindexingTriggerer.reindexingPeriod);
+ int triggered = 0;
+ while (now.isBefore(doom)) {
+ if (inWindowOfOpportunity(now, interval, ApplicationId.defaultId(), ZoneId.defaultId()))
+ triggered++;
+ now = now.plus(interval);
+ }
+ assertEquals("Should be in window of opportunity exactly twice each period", 2, triggered);
+ }
+
+ @Test
+ public void testReindexingIsReady() {
+ Instant then = Instant.now();
+ ApplicationReindexing reindexing = new ApplicationReindexing(true,
+ new Status(then),
+ Map.of());
+
+ Instant now = then;
+ assertFalse("Should not be ready less than one half-period after last triggering",
+ reindexingIsReady(reindexing, now));
+
+ now = now.plus(reindexingPeriod.dividedBy(2));
+ assertFalse("Should not be ready one half-period after last triggering",
+ reindexingIsReady(reindexing, now));
+
+ now = now.plusMillis(1);
+ assertTrue("Should be ready more than one half-period after last triggering",
+ reindexingIsReady(reindexing, now));
+
+ reindexing = new ApplicationReindexing(true,
+ new Status(then),
+ Map.of("cluster",
+ new Cluster(new Status(then),
+ Map.of(),
+ Map.of("type",
+ new Status(then, then, null, null, null, null)))));
+ assertFalse("Should not be ready when reindexing is already running",
+ reindexingIsReady(reindexing, now));
+
+ reindexing = new ApplicationReindexing(true,
+ new Status(then),
+ Map.of("cluster",
+ new Cluster(new Status(then),
+ Map.of("type", 123L),
+ Map.of("type",
+ new Status(then, then, now, null, null, null)))));
+ assertTrue("Should be ready when reindexing is no longer running",
+ reindexingIsReady(reindexing, now));
+ }
+
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json
index b6b45bd76e0..5af91e17bb7 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json
@@ -52,6 +52,9 @@
"name": "ReadyJobsTrigger"
},
{
+ "name": "ReindexingTriggerer"
+ },
+ {
"name": "ResourceMeterMaintainer"
},
{
diff --git a/eval/CMakeLists.txt b/eval/CMakeLists.txt
index 36796faa2fe..c2dd847e715 100644
--- a/eval/CMakeLists.txt
+++ b/eval/CMakeLists.txt
@@ -36,6 +36,7 @@ vespa_define_module(
src/tests/eval/value_cache
src/tests/eval/value_codec
src/tests/eval/value_type
+ src/tests/eval/typed_cells
src/tests/gp/ponder_nov2017
src/tests/instruction/dense_xw_product_function
src/tests/instruction/generic_concat
@@ -53,22 +54,21 @@ vespa_define_module(
src/tests/instruction/dense_tensor_peek_function
src/tests/instruction/index_lookup_table
src/tests/instruction/join_with_number
+ src/tests/instruction/dense_add_dimension_optimizer
+ src/tests/instruction/dense_fast_rename_optimizer
+ src/tests/instruction/dense_inplace_join_function
+ src/tests/instruction/dense_pow_as_map_optimizer
+ src/tests/instruction/dense_remove_dimension_optimizer
+ src/tests/instruction/dense_replace_type_function
+ src/tests/instruction/dense_simple_join_function
+ src/tests/instruction/dense_simple_map_function
+ src/tests/instruction/dense_single_reduce_function
+ src/tests/instruction/dense_tensor_create_function
+ src/tests/instruction/vector_from_doubles_function
src/tests/streamed/value
- src/tests/tensor/dense_add_dimension_optimizer
- src/tests/tensor/dense_fast_rename_optimizer
- src/tests/tensor/dense_inplace_join_function
- src/tests/tensor/dense_pow_as_map_optimizer
- src/tests/tensor/dense_remove_dimension_optimizer
- src/tests/tensor/dense_replace_type_function
- src/tests/tensor/dense_simple_join_function
- src/tests/tensor/dense_simple_map_function
- src/tests/tensor/dense_single_reduce_function
- src/tests/tensor/dense_tensor_create_function
src/tests/tensor/instruction_benchmark
src/tests/tensor/onnx_wrapper
src/tests/tensor/tensor_conformance
- src/tests/tensor/typed_cells
- src/tests/tensor/vector_from_doubles_function
LIBS
src/vespa/eval
diff --git a/eval/src/tests/eval/tensor_lambda/tensor_lambda_test.cpp b/eval/src/tests/eval/tensor_lambda/tensor_lambda_test.cpp
index 73a3648a34c..7094686e399 100644
--- a/eval/src/tests/eval/tensor_lambda/tensor_lambda_test.cpp
+++ b/eval/src/tests/eval/tensor_lambda/tensor_lambda_test.cpp
@@ -4,10 +4,10 @@
#include <vespa/eval/eval/tensor_function.h>
#include <vespa/eval/eval/simple_value.h>
#include <vespa/eval/eval/fast_value.h>
-#include <vespa/eval/tensor/dense/dense_replace_type_function.h>
+#include <vespa/eval/instruction/dense_replace_type_function.h>
#include <vespa/eval/instruction/dense_cell_range_function.h>
#include <vespa/eval/instruction/dense_lambda_peek_function.h>
-#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h>
+#include <vespa/eval/instruction/dense_fast_rename_optimizer.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/eval/eval/test/eval_fixture.h>
#include <vespa/eval/eval/tensor_nodes.h>
@@ -62,7 +62,7 @@ void verify_generic(const vespalib::string &expr, const vespalib::string &expect
}
void verify_reshape(const vespalib::string &expr, const vespalib::string &expect) {
- verify_impl<tensor::DenseReplaceTypeFunction>(expr, expect);
+ verify_impl<DenseReplaceTypeFunction>(expr, expect);
}
void verify_range(const vespalib::string &expr, const vespalib::string &expect) {
diff --git a/eval/src/tests/tensor/typed_cells/CMakeLists.txt b/eval/src/tests/eval/typed_cells/CMakeLists.txt
index d57ff33eda6..d57ff33eda6 100644
--- a/eval/src/tests/tensor/typed_cells/CMakeLists.txt
+++ b/eval/src/tests/eval/typed_cells/CMakeLists.txt
diff --git a/eval/src/tests/tensor/typed_cells/typed_cells_test.cpp b/eval/src/tests/eval/typed_cells/typed_cells_test.cpp
index ccb522fd496..ccb522fd496 100644
--- a/eval/src/tests/tensor/typed_cells/typed_cells_test.cpp
+++ b/eval/src/tests/eval/typed_cells/typed_cells_test.cpp
diff --git a/eval/src/tests/tensor/dense_add_dimension_optimizer/CMakeLists.txt b/eval/src/tests/instruction/dense_add_dimension_optimizer/CMakeLists.txt
index 1bc9f93b1a2..1bc9f93b1a2 100644
--- a/eval/src/tests/tensor/dense_add_dimension_optimizer/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_add_dimension_optimizer/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp b/eval/src/tests/instruction/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp
index 0e8e50daae5..e7660ce8933 100644
--- a/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp
+++ b/eval/src/tests/instruction/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp
@@ -3,8 +3,8 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/fast_value.h>
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/dense_replace_type_function.h>
-#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h>
+#include <vespa/eval/instruction/dense_replace_type_function.h>
+#include <vespa/eval/instruction/dense_fast_rename_optimizer.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/eval/eval/test/eval_fixture.h>
@@ -14,7 +14,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_fast_rename_optimizer/CMakeLists.txt b/eval/src/tests/instruction/dense_fast_rename_optimizer/CMakeLists.txt
index 32cf6c45d1e..32cf6c45d1e 100644
--- a/eval/src/tests/tensor/dense_fast_rename_optimizer/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_fast_rename_optimizer/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp b/eval/src/tests/instruction/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp
index 52afde0e92c..043c8814c72 100644
--- a/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp
+++ b/eval/src/tests/instruction/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp
@@ -2,8 +2,8 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/dense_replace_type_function.h>
-#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h>
+#include <vespa/eval/instruction/dense_replace_type_function.h>
+#include <vespa/eval/instruction/dense_fast_rename_optimizer.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/eval/eval/test/eval_fixture.h>
@@ -13,7 +13,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_inplace_join_function/CMakeLists.txt b/eval/src/tests/instruction/dense_inplace_join_function/CMakeLists.txt
index 2808675bc78..2808675bc78 100644
--- a/eval/src/tests/tensor/dense_inplace_join_function/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_inplace_join_function/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp b/eval/src/tests/instruction/dense_inplace_join_function/dense_inplace_join_function_test.cpp
index 853607ae76d..68aa72428b9 100644
--- a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp
+++ b/eval/src/tests/instruction/dense_inplace_join_function/dense_inplace_join_function_test.cpp
@@ -11,7 +11,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt b/eval/src/tests/instruction/dense_pow_as_map_optimizer/CMakeLists.txt
index d6ce9f1924c..d6ce9f1924c 100644
--- a/eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_pow_as_map_optimizer/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp b/eval/src/tests/instruction/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp
index d00744bcfaf..67567b4e289 100644
--- a/eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp
+++ b/eval/src/tests/instruction/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp
@@ -2,7 +2,7 @@
#include <vespa/eval/eval/fast_value.h>
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/dense_simple_map_function.h>
+#include <vespa/eval/instruction/dense_simple_map_function.h>
#include <vespa/eval/eval/test/eval_fixture.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/vespalib/gtest/gtest.h>
@@ -11,7 +11,6 @@ using namespace vespalib::eval::operation;
using namespace vespalib::eval::tensor_function;
using namespace vespalib::eval::test;
using namespace vespalib::eval;
-using namespace vespalib::tensor;
//using namespace vespalib;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_remove_dimension_optimizer/CMakeLists.txt b/eval/src/tests/instruction/dense_remove_dimension_optimizer/CMakeLists.txt
index c945bd31609..c945bd31609 100644
--- a/eval/src/tests/tensor/dense_remove_dimension_optimizer/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_remove_dimension_optimizer/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp b/eval/src/tests/instruction/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp
index 69910e27b4b..4c3c86be7f8 100644
--- a/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp
+++ b/eval/src/tests/instruction/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp
@@ -2,8 +2,8 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/dense_replace_type_function.h>
-#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h>
+#include <vespa/eval/instruction/dense_replace_type_function.h>
+#include <vespa/eval/instruction/dense_fast_rename_optimizer.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/eval/eval/test/eval_fixture.h>
@@ -13,7 +13,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_replace_type_function/CMakeLists.txt b/eval/src/tests/instruction/dense_replace_type_function/CMakeLists.txt
index dd4a8a58082..dd4a8a58082 100644
--- a/eval/src/tests/tensor/dense_replace_type_function/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_replace_type_function/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp b/eval/src/tests/instruction/dense_replace_type_function/dense_replace_type_function_test.cpp
index 2612869e72f..6b8e6faecf4 100644
--- a/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp
+++ b/eval/src/tests/instruction/dense_replace_type_function/dense_replace_type_function_test.cpp
@@ -4,18 +4,17 @@
#include <vespa/eval/eval/fast_value.h>
#include <vespa/eval/eval/value_codec.h>
#include <vespa/eval/eval/interpreted_function.h>
-#include <vespa/eval/tensor/dense/dense_replace_type_function.h>
+#include <vespa/eval/instruction/dense_replace_type_function.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
using namespace vespalib::eval::tensor_function;
using namespace vespalib::eval::test;
using namespace vespalib::eval;
-using namespace vespalib::tensor;
using namespace vespalib;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
-TypedCells getCellsRef(const eval::Value &value) {
+TypedCells getCellsRef(const Value &value) {
return value.cells();
}
diff --git a/eval/src/tests/tensor/dense_simple_join_function/CMakeLists.txt b/eval/src/tests/instruction/dense_simple_join_function/CMakeLists.txt
index 8a2df392145..8a2df392145 100644
--- a/eval/src/tests/tensor/dense_simple_join_function/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_simple_join_function/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_simple_join_function/dense_simple_join_function_test.cpp b/eval/src/tests/instruction/dense_simple_join_function/dense_simple_join_function_test.cpp
index 6ad60d2e3f5..2186d49385e 100644
--- a/eval/src/tests/tensor/dense_simple_join_function/dense_simple_join_function_test.cpp
+++ b/eval/src/tests/instruction/dense_simple_join_function/dense_simple_join_function_test.cpp
@@ -2,7 +2,7 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/dense_simple_join_function.h>
+#include <vespa/eval/instruction/dense_simple_join_function.h>
#include <vespa/eval/eval/test/eval_fixture.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
@@ -11,7 +11,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
using vespalib::make_string_short::fmt;
@@ -19,7 +18,7 @@ using vespalib::make_string_short::fmt;
using Primary = DenseSimpleJoinFunction::Primary;
using Overlap = DenseSimpleJoinFunction::Overlap;
-namespace vespalib::tensor {
+namespace vespalib::eval {
std::ostream &operator<<(std::ostream &os, Primary primary)
{
diff --git a/eval/src/tests/tensor/dense_simple_map_function/CMakeLists.txt b/eval/src/tests/instruction/dense_simple_map_function/CMakeLists.txt
index 8d3bb8c92aa..8d3bb8c92aa 100644
--- a/eval/src/tests/tensor/dense_simple_map_function/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_simple_map_function/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_simple_map_function/dense_simple_map_function_test.cpp b/eval/src/tests/instruction/dense_simple_map_function/dense_simple_map_function_test.cpp
index 53164ad59c8..13a24c13a2e 100644
--- a/eval/src/tests/tensor/dense_simple_map_function/dense_simple_map_function_test.cpp
+++ b/eval/src/tests/instruction/dense_simple_map_function/dense_simple_map_function_test.cpp
@@ -1,7 +1,7 @@
// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/dense_simple_map_function.h>
+#include <vespa/eval/instruction/dense_simple_map_function.h>
#include <vespa/eval/eval/test/eval_fixture.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/vespalib/gtest/gtest.h>
@@ -10,7 +10,6 @@ using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
using namespace vespalib::eval::tensor_function;
-using namespace vespalib::tensor;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_single_reduce_function/CMakeLists.txt b/eval/src/tests/instruction/dense_single_reduce_function/CMakeLists.txt
index 42b00699c31..42b00699c31 100644
--- a/eval/src/tests/tensor/dense_single_reduce_function/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_single_reduce_function/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_single_reduce_function/dense_single_reduce_function_test.cpp b/eval/src/tests/instruction/dense_single_reduce_function/dense_single_reduce_function_test.cpp
index 347228269cf..c6da0b94de3 100644
--- a/eval/src/tests/tensor/dense_single_reduce_function/dense_single_reduce_function_test.cpp
+++ b/eval/src/tests/instruction/dense_single_reduce_function/dense_single_reduce_function_test.cpp
@@ -3,7 +3,7 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/tensor_function.h>
#include <vespa/eval/eval/operation.h>
-#include <vespa/eval/tensor/dense/dense_single_reduce_function.h>
+#include <vespa/eval/instruction/dense_single_reduce_function.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/eval/eval/test/eval_fixture.h>
@@ -13,7 +13,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_tensor_create_function/CMakeLists.txt b/eval/src/tests/instruction/dense_tensor_create_function/CMakeLists.txt
index 883f331bda8..883f331bda8 100644
--- a/eval/src/tests/tensor/dense_tensor_create_function/CMakeLists.txt
+++ b/eval/src/tests/instruction/dense_tensor_create_function/CMakeLists.txt
diff --git a/eval/src/tests/tensor/dense_tensor_create_function/dense_tensor_create_function_test.cpp b/eval/src/tests/instruction/dense_tensor_create_function/dense_tensor_create_function_test.cpp
index edf999e97b3..25bbe5b422c 100644
--- a/eval/src/tests/tensor/dense_tensor_create_function/dense_tensor_create_function_test.cpp
+++ b/eval/src/tests/instruction/dense_tensor_create_function/dense_tensor_create_function_test.cpp
@@ -2,7 +2,7 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/dense_tensor_create_function.h>
+#include <vespa/eval/instruction/dense_tensor_create_function.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/eval/eval/test/eval_fixture.h>
@@ -12,7 +12,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/vector_from_doubles_function/CMakeLists.txt b/eval/src/tests/instruction/vector_from_doubles_function/CMakeLists.txt
index 5b2e47ec498..5b2e47ec498 100644
--- a/eval/src/tests/tensor/vector_from_doubles_function/CMakeLists.txt
+++ b/eval/src/tests/instruction/vector_from_doubles_function/CMakeLists.txt
diff --git a/eval/src/tests/tensor/vector_from_doubles_function/vector_from_doubles_function_test.cpp b/eval/src/tests/instruction/vector_from_doubles_function/vector_from_doubles_function_test.cpp
index c3e1f2f248e..4f4829c3ae1 100644
--- a/eval/src/tests/tensor/vector_from_doubles_function/vector_from_doubles_function_test.cpp
+++ b/eval/src/tests/instruction/vector_from_doubles_function/vector_from_doubles_function_test.cpp
@@ -2,7 +2,7 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/eval/tensor_function.h>
-#include <vespa/eval/tensor/dense/vector_from_doubles_function.h>
+#include <vespa/eval/instruction/vector_from_doubles_function.h>
#include <vespa/eval/eval/test/tensor_model.hpp>
#include <vespa/eval/eval/test/eval_fixture.h>
@@ -12,7 +12,6 @@
using namespace vespalib;
using namespace vespalib::eval;
using namespace vespalib::eval::test;
-using namespace vespalib::tensor;
using namespace vespalib::eval::tensor_function;
const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get();
diff --git a/eval/src/tests/tensor/dense_dimension_combiner/CMakeLists.txt b/eval/src/tests/tensor/dense_dimension_combiner/CMakeLists.txt
deleted file mode 100644
index eaee8ebb4e4..00000000000
--- a/eval/src/tests/tensor/dense_dimension_combiner/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-vespa_add_executable(eval_dense_dimension_combiner_test_app TEST
- SOURCES
- dense_dimension_combiner_test.cpp
- DEPENDS
- vespaeval
-)
-vespa_add_test(NAME eval_dense_dimension_combiner_test_app COMMAND eval_dense_dimension_combiner_test_app)
diff --git a/eval/src/tests/tensor/dense_dimension_combiner/dense_dimension_combiner_test.cpp b/eval/src/tests/tensor/dense_dimension_combiner/dense_dimension_combiner_test.cpp
deleted file mode 100644
index b8949e3a7e6..00000000000
--- a/eval/src/tests/tensor/dense_dimension_combiner/dense_dimension_combiner_test.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include <vespa/vespalib/testkit/test_kit.h>
-#include <vespa/eval/tensor/dense/dense_dimension_combiner.h>
-
-using namespace vespalib;
-using namespace vespalib::eval;
-using namespace vespalib::tensor;
-
-void verifyLeft(DenseDimensionCombiner &d, size_t last) {
- d.commonReset();
- d.leftReset();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_EQUAL(d.leftIdx(), 0u);
- size_t expect = 0;
- while (d.leftInRange()) {
- d.stepLeft();
- EXPECT_GREATER(d.leftIdx(), expect);
- expect = d.leftIdx();
- }
- EXPECT_FALSE(d.leftInRange());
- EXPECT_EQUAL(expect, last);
- d.leftReset();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_EQUAL(d.leftIdx(), 0u);
-}
-
-void verifyRight(DenseDimensionCombiner &d, size_t last) {
- d.commonReset();
- d.rightReset();
- EXPECT_TRUE(d.rightInRange());
- EXPECT_EQUAL(d.rightIdx(), 0u);
- size_t expect = 0;
- while (d.rightInRange()) {
- d.stepRight();
- EXPECT_GREATER(d.rightIdx(), expect);
- expect = d.rightIdx();
- }
- EXPECT_FALSE(d.rightInRange());
- EXPECT_EQUAL(expect, last);
- d.rightReset();
- EXPECT_TRUE(d.rightInRange());
- EXPECT_EQUAL(d.rightIdx(), 0u);
-}
-
-
-TEST("require that one left, one common, one right dimension works") {
- ValueType t12_lc = ValueType::tensor_type({{"d1_l", 3},{"d2_c", 4}});
- ValueType t23_cr = ValueType::tensor_type({{"d2_c", 4},{"d3_r", 5}});
-
- DenseDimensionCombiner d(t12_lc, t23_cr);
-
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 0u);
- EXPECT_EQUAL(d.rightIdx(), 0u);
- EXPECT_EQUAL(d.outputIdx(), 0u);
-
- d.stepCommon();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 1u);
- EXPECT_EQUAL(d.rightIdx(), 5u);
- EXPECT_EQUAL(d.outputIdx(), 5u);
-
- d.stepRight();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 1u);
- EXPECT_EQUAL(d.rightIdx(), 6u);
- EXPECT_EQUAL(d.outputIdx(), 6u);
-
- d.stepLeft();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 5u);
- EXPECT_EQUAL(d.rightIdx(), 6u);
- EXPECT_EQUAL(d.outputIdx(), 26u);
-
- d.stepLeft();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 9u);
- EXPECT_EQUAL(d.rightIdx(), 6u);
- EXPECT_EQUAL(d.outputIdx(), 46u);
-
- d.stepLeft();
- EXPECT_FALSE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 13u);
- EXPECT_EQUAL(d.rightIdx(), 6u);
- EXPECT_EQUAL(d.outputIdx(), 6u);
-
- d.leftReset();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 1u);
- EXPECT_EQUAL(d.rightIdx(), 6u);
- EXPECT_EQUAL(d.outputIdx(), 6u);
-
- d.stepCommon();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 2u);
- EXPECT_EQUAL(d.rightIdx(), 11u);
- EXPECT_EQUAL(d.outputIdx(), 11u);
-
- d.stepRight();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 2u);
- EXPECT_EQUAL(d.rightIdx(), 12u);
- EXPECT_EQUAL(d.outputIdx(), 12u);
-
- TEST_DO(verifyLeft(d, 12));
- TEST_DO(verifyRight(d, 20));
-}
-
-TEST("require that two left, no common, two right dimensions works") {
- ValueType t12_ll = ValueType::tensor_type({{"d1_l", 3},{"d2_l", 4}});
- ValueType t34_rr = ValueType::tensor_type({{"d3_r", 5},{"d4_r", 2}});
-
- DenseDimensionCombiner d(t12_ll, t34_rr);
-
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 0u);
- EXPECT_EQUAL(d.rightIdx(), 0u);
- EXPECT_EQUAL(d.outputIdx(), 0u);
-
- d.stepCommon();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_FALSE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 0u);
- EXPECT_EQUAL(d.rightIdx(), 0u);
- EXPECT_EQUAL(d.outputIdx(), 120u);
-
- d.commonReset();
- d.stepRight();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 0u);
- EXPECT_EQUAL(d.rightIdx(), 1u);
- EXPECT_EQUAL(d.outputIdx(), 1u);
-
- d.stepLeft();
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 1u);
- EXPECT_EQUAL(d.rightIdx(), 1u);
- EXPECT_EQUAL(d.outputIdx(), 11u);
-
- d.stepLeft();
- d.stepLeft();
- d.stepLeft();
- d.stepLeft();
- d.stepLeft();
- d.stepLeft();
- d.stepLeft();
-
- EXPECT_TRUE(d.leftInRange());
- EXPECT_TRUE(d.rightInRange());
- EXPECT_TRUE(d.commonInRange());
- EXPECT_EQUAL(d.leftIdx(), 8u);
- EXPECT_EQUAL(d.rightIdx(), 1u);
- EXPECT_EQUAL(d.outputIdx(), 81u);
-
- TEST_DO(verifyLeft(d, 12));
- TEST_DO(verifyRight(d, 10));
-}
-
-TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/eval/src/tests/tensor/direct_sparse_tensor_builder/CMakeLists.txt b/eval/src/tests/tensor/direct_sparse_tensor_builder/CMakeLists.txt
deleted file mode 100644
index 00ff230fadd..00000000000
--- a/eval/src/tests/tensor/direct_sparse_tensor_builder/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_executable(eval_direct_sparse_tensor_builder_test_app TEST
- SOURCES
- direct_sparse_tensor_builder_test.cpp
- DEPENDS
- vespaeval
-)
-vespa_add_test(NAME eval_direct_sparse_tensor_builder_test_app COMMAND eval_direct_sparse_tensor_builder_test_app)
diff --git a/eval/src/tests/tensor/direct_sparse_tensor_builder/direct_sparse_tensor_builder_test.cpp b/eval/src/tests/tensor/direct_sparse_tensor_builder/direct_sparse_tensor_builder_test.cpp
deleted file mode 100644
index bcee6471f76..00000000000
--- a/eval/src/tests/tensor/direct_sparse_tensor_builder/direct_sparse_tensor_builder_test.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include <vespa/vespalib/testkit/test_kit.h>
-#include <vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h>
-#include <vespa/eval/tensor/sparse/sparse_tensor_address_combiner.h>
-#include <vespa/vespalib/test/insertion_operators.h>
-
-using namespace vespalib::tensor;
-using namespace vespalib::tensor::sparse;
-using vespalib::eval::TensorSpec;
-using vespalib::eval::CellType;
-using vespalib::eval::ValueType;
-
-void
-assertCellValue(double expValue, const TensorAddress &address,
- const ValueType &type,
- const SparseTensor &tensor)
-{
- SparseTensorAddressBuilder addressBuilder;
- auto dimsItr = type.dimensions().cbegin();
- auto dimsItrEnd = type.dimensions().cend();
- for (const auto &element : address.elements()) {
- while ((dimsItr < dimsItrEnd) && (dimsItr->name < element.dimension())) {
- addressBuilder.add("");
- ++dimsItr;
- }
- assert((dimsItr != dimsItrEnd) && (dimsItr->name == element.dimension()));
- addressBuilder.add(element.label());
- ++dimsItr;
- }
- while (dimsItr < dimsItrEnd) {
- addressBuilder.add("");
- ++dimsItr;
- }
- SparseTensorAddressRef addressRef(addressBuilder.getAddressRef());
- size_t idx;
- bool found = tensor.index().lookup_address(addressRef, idx);
- EXPECT_TRUE(found);
- auto cells = tensor.cells();
- if (EXPECT_TRUE(cells.type == CellType::DOUBLE)) {
- auto arr = cells.typify<double>();
- EXPECT_EQUAL(expValue, arr[idx]);
- }
-}
-
-Tensor::UP
-buildTensor()
-{
- DirectSparseTensorBuilder<double> builder(ValueType::from_spec("tensor(a{},b{},c{},d{})"));
- SparseTensorAddressBuilder address;
- address.set({"1", "2", "", ""});
- builder.insertCell(address, 10);
- address.set({"", "", "3", "4"});
- builder.insertCell(address, 20);
- return builder.build();
-}
-
-TEST("require that tensor can be constructed")
-{
- Tensor::UP tensor = buildTensor();
- const SparseTensor &sparseTensor = dynamic_cast<const SparseTensor &>(*tensor);
- const ValueType &type = sparseTensor.type();
- const auto & index = sparseTensor.index();
- EXPECT_EQUAL(2u, index.size());
- assertCellValue(10, TensorAddress({{"a","1"},{"b","2"}}), type, sparseTensor);
- assertCellValue(20, TensorAddress({{"c","3"},{"d","4"}}), type, sparseTensor);
-}
-
-TEST("require that tensor can be converted to tensor spec")
-{
- Tensor::UP tensor = buildTensor();
- TensorSpec expSpec("tensor(a{},b{},c{},d{})");
- expSpec.add({{"a", "1"}, {"b", "2"}, {"c", ""}, {"d", ""}}, 10).
- add({{"a", ""},{"b",""},{"c", "3"}, {"d", "4"}}, 20);
- TensorSpec actSpec = tensor->toSpec();
- EXPECT_EQUAL(expSpec, actSpec);
-}
-
-TEST("require that dimensions are extracted")
-{
- Tensor::UP tensor = buildTensor();
- const SparseTensor &sparseTensor = dynamic_cast<const SparseTensor &>(*tensor);
- const auto &dims = sparseTensor.type().dimensions();
- EXPECT_EQUAL(4u, dims.size());
- EXPECT_EQUAL("a", dims[0].name);
- EXPECT_EQUAL("b", dims[1].name);
- EXPECT_EQUAL("c", dims[2].name);
- EXPECT_EQUAL("d", dims[3].name);
- EXPECT_EQUAL("tensor(a{},b{},c{},d{})", sparseTensor.type().to_spec());
-}
-
-void verifyAddressCombiner(const ValueType & a, const ValueType & b, size_t numDim, size_t numOverlapping) {
- TensorAddressCombiner combiner(a, b);
- EXPECT_EQUAL(numDim, combiner.numDimensions());
- EXPECT_EQUAL(numOverlapping, combiner.numOverlappingDimensions());
-}
-TEST("Test sparse tensor address combiner") {
- verifyAddressCombiner(ValueType::tensor_type({{"a"}}), ValueType::tensor_type({{"b"}}), 2, 0);
- verifyAddressCombiner(ValueType::tensor_type({{"a"}, {"b"}}), ValueType::tensor_type({{"b"}}), 2, 1);
- verifyAddressCombiner(ValueType::tensor_type({{"a"}, {"b"}}), ValueType::tensor_type({{"b"}, {"c"}}), 3, 1);
-
-}
-
-TEST("Test essential object sizes") {
- EXPECT_EQUAL(16u, sizeof(SparseTensorAddressRef));
- EXPECT_EQUAL(24u, sizeof(std::pair<SparseTensorAddressRef, double>));
- EXPECT_EQUAL(32u, sizeof(vespalib::hash_node<std::pair<SparseTensorAddressRef, double>>));
- Tensor::UP tensor = buildTensor();
- size_t used = tensor->get_memory_usage().usedBytes();
- EXPECT_GREATER(used, sizeof(SparseTensor));
- EXPECT_LESS(used, 10000u);
- size_t allocated = tensor->get_memory_usage().allocatedBytes();
- EXPECT_GREATER(allocated, used);
- EXPECT_LESS(allocated, 50000u);
- fprintf(stderr, "tensor using %zu bytes of %zu allocated\n",
- used, allocated);
-}
-
-TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/eval/src/tests/tensor/instruction_benchmark/.gitignore b/eval/src/tests/tensor/instruction_benchmark/.gitignore
index dc5c408cf29..5b3eab59ff6 100644
--- a/eval/src/tests/tensor/instruction_benchmark/.gitignore
+++ b/eval/src/tests/tensor/instruction_benchmark/.gitignore
@@ -1 +1,3 @@
vespa-tensor-instructions-benchmark
+/result.json
+/ghost.json
diff --git a/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp b/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp
index 3bddf69f53f..aa1da07bc91 100644
--- a/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp
+++ b/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp
@@ -39,15 +39,20 @@
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/util/stash.h>
#include <vespa/vespalib/gtest/gtest.h>
+#include <vespa/vespalib/io/mapped_file_input.h>
+#include <vespa/vespalib/io/fileutil.h>
+#include <vespa/vespalib/data/slime/slime.h>
+#include <vespa/vespalib/data/smart_buffer.h>
#include <optional>
#include <algorithm>
using namespace vespalib;
using namespace vespalib::eval;
-using namespace vespalib::tensor;
using namespace vespalib::eval::instruction;
using vespalib::make_string_short::fmt;
+using vespalib::slime::JsonFormat;
+
using Instruction = InterpretedFunction::Instruction;
using EvalSingle = InterpretedFunction::EvalSingle;
@@ -256,6 +261,8 @@ Impl optimized_fast_value_impl(0, " Optimized FastValue", "
Impl fast_value_impl(1, " FastValue", " FastV", FastValueBuilderFactory::get(), false);
Impl simple_value_impl(2, " SimpleValue", " SimpleV", SimpleValueBuilderFactory::get(), false);
vespalib::string short_header("--------");
+vespalib::string ghost_name(" loaded from ghost.json");
+vespalib::string ghost_short_name(" ghost");
constexpr double budget = 5.0;
constexpr double best_limit = 0.95; // everything within 95% of best performance gets a star
@@ -266,6 +273,10 @@ std::vector<CREF<Impl>> impl_list = {simple_value_impl,
optimized_fast_value_impl,
fast_value_impl};
+Slime ghost; // loaded from 'ghost.json'
+bool has_ghost = false;
+Slime prod_result; // saved to 'result.json'
+
//-----------------------------------------------------------------------------
struct BenchmarkHeader {
@@ -275,6 +286,9 @@ struct BenchmarkHeader {
for (const Impl &impl: impl_list) {
short_names[impl.order] = impl.short_name;
}
+ if (has_ghost) {
+ short_names.push_back(ghost_short_name);
+ }
}
void print_header(const vespalib::string &desc) const {
for (const auto &name: short_names) {
@@ -300,12 +314,17 @@ struct BenchmarkResult {
~BenchmarkResult();
void sample(size_t order, double time) {
relative_perf[order] = time;
- if (order == 1) {
- if (ref_time.has_value()) {
- ref_time = std::min(ref_time.value(), time);
- } else {
- ref_time = time;
+ if (order == 0) {
+ prod_result.get().setDouble(desc, time);
+ if (has_ghost && (relative_perf.size() == impl_list.size())) {
+ double ghost_time = ghost.get()[desc].asDouble();
+ size_t ghost_order = relative_perf.size();
+ fprintf(stderr, " %s(%s): %10.3f us\n", ghost_name.c_str(), ghost_short_name.c_str(), ghost_time);
+ relative_perf.resize(ghost_order + 1);
+ return sample(ghost_order, ghost_time);
}
+ } else if (order == 1) {
+ ref_time = time;
}
}
void normalize() {
@@ -333,6 +352,23 @@ std::vector<BenchmarkResult> benchmark_results;
//-----------------------------------------------------------------------------
+void load_ghost(const vespalib::string &file_name) {
+ MappedFileInput input(file_name);
+ has_ghost = JsonFormat::decode(input, ghost);
+}
+
+void save_result(const vespalib::string &file_name) {
+ SmartBuffer output(4096);
+ JsonFormat::encode(prod_result, output, false);
+ Memory memory = output.obtain();
+ File file(file_name);
+ file.open(File::CREATE | File::TRUNC);
+ file.write(memory.data, memory.size, 0);
+ file.close();
+}
+
+//-----------------------------------------------------------------------------
+
struct MyParam : LazyParams {
Value::UP my_value;
MyParam() : my_value() {}
@@ -433,8 +469,8 @@ void benchmark(const vespalib::string &desc, const std::vector<EvalOp::UP> &list
}
for (const auto &eval: list) {
double time = eval->estimate_cost_us(loop_cnt[eval->impl.order], loop_cnt[1]);
- result.sample(eval->impl.order, time);
fprintf(stderr, " %s(%s): %10.3f us\n", eval->impl.name.c_str(), eval->impl.short_name.c_str(), time);
+ result.sample(eval->impl.order, time);
}
result.normalize();
benchmark_results.push_back(result);
@@ -674,9 +710,9 @@ void benchmark_encode_decode(const vespalib::string &desc, const TensorSpec &pro
}
double encode_us = encode_timer.min_time() * 1000.0 * 1000.0 / double(loop_cnt);
double decode_us = decode_timer.min_time() * 1000.0 * 1000.0 / double(loop_cnt);
- fprintf(stderr, " %s (%s) <encode>: %10.3f us\n", impl.name.c_str(), impl.short_name.c_str(), encode_us);
- fprintf(stderr, " %s (%s) <decode>: %10.3f us\n", impl.name.c_str(), impl.short_name.c_str(), decode_us);
+ fprintf(stderr, " %s(%s): %10.3f us <encode>\n", impl.name.c_str(), impl.short_name.c_str(), encode_us);
encode_result.sample(impl.order, encode_us);
+ fprintf(stderr, " %s(%s): %10.3f us <decode>\n", impl.name.c_str(), impl.short_name.c_str(), decode_us);
decode_result.sample(impl.order, decode_us);
}
encode_result.normalize();
@@ -1077,16 +1113,26 @@ void print_summary() {
}
int main(int argc, char **argv) {
+ prod_result.setObject();
+ load_ghost("ghost.json");
const std::string run_only_prod_option = "--limit-implementations";
+ const std::string ghost_mode_option = "--ghost-mode";
if ((argc > 1) && (argv[1] == run_only_prod_option )) {
impl_list.clear();
impl_list.push_back(optimized_fast_value_impl);
impl_list.push_back(fast_value_impl);
++argv;
--argc;
+ } else if ((argc > 1) && (argv[1] == ghost_mode_option )) {
+ impl_list.clear();
+ impl_list.push_back(optimized_fast_value_impl);
+ has_ghost = true;
+ ++argv;
+ --argc;
}
::testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
+ save_result("result.json");
print_summary();
return result;
}
diff --git a/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp b/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp
index 7e204f1ea06..b474d2458b9 100644
--- a/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp
+++ b/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp
@@ -6,7 +6,6 @@
#include <vespa/vespalib/gtest/gtest.h>
using namespace vespalib::eval;
-using namespace vespalib::tensor;
using vespalib::make_string_short::fmt;
using TensorInfo = Onnx::TensorInfo;
diff --git a/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp b/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp
index c12b7071d02..a0a062c4322 100644
--- a/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp
+++ b/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp
@@ -3,8 +3,6 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/tensor/tensor_address.h>
-using namespace vespalib::tensor;
-
void
assertSortOrder(const TensorAddress::Elements &exp,
const TensorAddress::Elements &input)
diff --git a/eval/src/vespa/eval/eval/optimize_tensor_function.cpp b/eval/src/vespa/eval/eval/optimize_tensor_function.cpp
index ed0b122196d..cbd4192a84f 100644
--- a/eval/src/vespa/eval/eval/optimize_tensor_function.cpp
+++ b/eval/src/vespa/eval/eval/optimize_tensor_function.cpp
@@ -8,18 +8,18 @@
#include <vespa/eval/instruction/dense_xw_product_function.h>
#include <vespa/eval/instruction/dense_matmul_function.h>
#include <vespa/eval/instruction/dense_multi_matmul_function.h>
-#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h>
-#include <vespa/eval/tensor/dense/dense_add_dimension_optimizer.h>
-#include <vespa/eval/tensor/dense/dense_single_reduce_function.h>
-#include <vespa/eval/tensor/dense/dense_remove_dimension_optimizer.h>
+#include <vespa/eval/instruction/dense_fast_rename_optimizer.h>
+#include <vespa/eval/instruction/dense_add_dimension_optimizer.h>
+#include <vespa/eval/instruction/dense_single_reduce_function.h>
+#include <vespa/eval/instruction/dense_remove_dimension_optimizer.h>
#include <vespa/eval/instruction/dense_lambda_peek_optimizer.h>
#include <vespa/eval/instruction/dense_simple_expand_function.h>
-#include <vespa/eval/tensor/dense/dense_simple_join_function.h>
+#include <vespa/eval/instruction/dense_simple_join_function.h>
#include <vespa/eval/instruction/join_with_number_function.h>
-#include <vespa/eval/tensor/dense/dense_pow_as_map_optimizer.h>
-#include <vespa/eval/tensor/dense/dense_simple_map_function.h>
-#include <vespa/eval/tensor/dense/vector_from_doubles_function.h>
-#include <vespa/eval/tensor/dense/dense_tensor_create_function.h>
+#include <vespa/eval/instruction/dense_pow_as_map_optimizer.h>
+#include <vespa/eval/instruction/dense_simple_map_function.h>
+#include <vespa/eval/instruction/vector_from_doubles_function.h>
+#include <vespa/eval/instruction/dense_tensor_create_function.h>
#include <vespa/eval/instruction/dense_tensor_peek_function.h>
#include <vespa/log/log.h>
@@ -29,8 +29,6 @@ namespace vespalib::eval {
namespace {
-using namespace vespalib::tensor;
-
const TensorFunction &optimize_for_factory(const ValueBuilderFactory &factory, const TensorFunction &expr, Stash &stash) {
if (&factory == &SimpleValueBuilderFactory::get()) {
// never optimize simple value evaluation
diff --git a/eval/src/vespa/eval/eval/tensor_function.h b/eval/src/vespa/eval/eval/tensor_function.h
index 26d28bac350..ed1106cccc1 100644
--- a/eval/src/vespa/eval/eval/tensor_function.h
+++ b/eval/src/vespa/eval/eval/tensor_function.h
@@ -21,9 +21,6 @@ namespace vespalib {
class Stash;
class ObjectVisitor;
-// TODO: remove this type injection when the 'tensor' namespace is removed
-namespace tensor { using ValueBuilderFactory = vespalib::eval::ValueBuilderFactory; }
-
namespace eval {
class Tensor;
diff --git a/eval/src/vespa/eval/eval/value_type.cpp b/eval/src/vespa/eval/eval/value_type.cpp
index 05ec65bf292..a5960a8de4b 100644
--- a/eval/src/vespa/eval/eval/value_type.cpp
+++ b/eval/src/vespa/eval/eval/value_type.cpp
@@ -138,7 +138,7 @@ struct Renamer {
bool matched_all() const { return (match_cnt == from.size()); }
};
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
constexpr ValueType::Dimension::size_type ValueType::Dimension::npos;
diff --git a/eval/src/vespa/eval/instruction/CMakeLists.txt b/eval/src/vespa/eval/instruction/CMakeLists.txt
index 4f2c59e34e1..42f88c0ee52 100644
--- a/eval/src/vespa/eval/instruction/CMakeLists.txt
+++ b/eval/src/vespa/eval/instruction/CMakeLists.txt
@@ -22,4 +22,14 @@ vespa_add_library(eval_instruction OBJECT
generic_rename.cpp
index_lookup_table.cpp
join_with_number_function.cpp
+ dense_add_dimension_optimizer.cpp
+ dense_fast_rename_optimizer.cpp
+ dense_pow_as_map_optimizer.cpp
+ dense_remove_dimension_optimizer.cpp
+ dense_replace_type_function.cpp
+ dense_simple_join_function.cpp
+ dense_simple_map_function.cpp
+ dense_single_reduce_function.cpp
+ dense_tensor_create_function.cpp
+ vector_from_doubles_function.cpp
)
diff --git a/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp b/eval/src/vespa/eval/instruction/dense_add_dimension_optimizer.cpp
index 9cd7cc88907..ccccb595c6d 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.cpp
+++ b/eval/src/vespa/eval/instruction/dense_add_dimension_optimizer.cpp
@@ -8,13 +8,10 @@
#include <vespa/log/log.h>
LOG_SETUP(".eval.tensor.dense.add_dimension_optimizer");
-namespace vespalib::tensor {
+namespace vespalib::eval {
-using eval::ValueType;
-using eval::TensorFunction;
-using eval::as;
-using namespace eval::tensor_function;
-using namespace eval::operation;
+using namespace tensor_function;
+using namespace operation;
namespace {
@@ -34,10 +31,10 @@ bool is_unit_constant(const TensorFunction &node) {
return false;
}
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
const TensorFunction &
-DenseAddDimensionOptimizer::optimize(const eval::TensorFunction &expr, Stash &stash)
+DenseAddDimensionOptimizer::optimize(const TensorFunction &expr, Stash &stash)
{
if (auto join = as<Join>(expr)) {
const TensorFunction &lhs = join->lhs();
@@ -57,4 +54,4 @@ DenseAddDimensionOptimizer::optimize(const eval::TensorFunction &expr, Stash &st
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.h b/eval/src/vespa/eval/instruction/dense_add_dimension_optimizer.h
index 4b5cf296292..99ab20614a2 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_add_dimension_optimizer.h
+++ b/eval/src/vespa/eval/instruction/dense_add_dimension_optimizer.h
@@ -4,14 +4,15 @@
#include <vespa/eval/eval/tensor_function.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Tensor function optimizer for efficient adding of dimensions with
* size 1 for dense tensors.
+ * TODO: extend to mixed tensors.
**/
struct DenseAddDimensionOptimizer {
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp b/eval/src/vespa/eval/instruction/dense_fast_rename_optimizer.cpp
index bd84fc4c51a..a4ef32f4701 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.cpp
+++ b/eval/src/vespa/eval/instruction/dense_fast_rename_optimizer.cpp
@@ -4,13 +4,9 @@
#include "dense_replace_type_function.h"
#include <vespa/eval/eval/value.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
-using eval::Value;
-using eval::ValueType;
-using eval::TensorFunction;
-using eval::as;
-using namespace eval::tensor_function;
+using namespace tensor_function;
namespace {
@@ -35,10 +31,10 @@ bool is_dense_stable_rename(const ValueType &from_type, const ValueType &to_type
return true;
}
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
const TensorFunction &
-DenseFastRenameOptimizer::optimize(const eval::TensorFunction &expr, Stash &stash)
+DenseFastRenameOptimizer::optimize(const TensorFunction &expr, Stash &stash)
{
if (auto rename = as<Rename>(expr)) {
const ValueType &from_type = rename->child().result_type();
@@ -51,4 +47,4 @@ DenseFastRenameOptimizer::optimize(const eval::TensorFunction &expr, Stash &stas
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.h b/eval/src/vespa/eval/instruction/dense_fast_rename_optimizer.h
index bbcb38e1f80..2882cdf6f30 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_fast_rename_optimizer.h
+++ b/eval/src/vespa/eval/instruction/dense_fast_rename_optimizer.h
@@ -4,14 +4,15 @@
#include <vespa/eval/eval/tensor_function.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Tensor function optimizer for efficient non-transposing rename of a
* dense tensor.
+ * TODO: extend to mixed tensors.
**/
struct DenseFastRenameOptimizer {
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/instruction/dense_lambda_peek_optimizer.cpp b/eval/src/vespa/eval/instruction/dense_lambda_peek_optimizer.cpp
index 6853b1a078f..f8ce886ae1f 100644
--- a/eval/src/vespa/eval/instruction/dense_lambda_peek_optimizer.cpp
+++ b/eval/src/vespa/eval/instruction/dense_lambda_peek_optimizer.cpp
@@ -3,7 +3,7 @@
#include "dense_lambda_peek_optimizer.h"
#include "dense_lambda_peek_function.h"
#include "dense_cell_range_function.h"
-#include <vespa/eval/tensor/dense/dense_replace_type_function.h>
+#include <vespa/eval/instruction/dense_replace_type_function.h>
#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/node_tools.h>
#include <vespa/eval/eval/basic_nodes.h>
@@ -182,7 +182,7 @@ DenseLambdaPeekOptimizer::optimize(const TensorFunction &expr, Stash &stash)
if (result.cell_range && (dst_type.cell_type() == src_type.cell_type())) {
auto cell_range = result.cell_range.value();
if (cell_range.is_full(src_type.dense_subspace_size())) {
- return tensor::DenseReplaceTypeFunction::create_compact(dst_type, get_param, stash);
+ return DenseReplaceTypeFunction::create_compact(dst_type, get_param, stash);
} else {
return stash.create<DenseCellRangeFunction>(dst_type, get_param,
cell_range.offset, cell_range.length);
diff --git a/eval/src/vespa/eval/tensor/dense/dense_pow_as_map_optimizer.cpp b/eval/src/vespa/eval/instruction/dense_pow_as_map_optimizer.cpp
index f78c23c80ac..61ef2243480 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_pow_as_map_optimizer.cpp
+++ b/eval/src/vespa/eval/instruction/dense_pow_as_map_optimizer.cpp
@@ -4,13 +4,10 @@
#include "dense_simple_map_function.h"
#include <vespa/eval/eval/operation.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
-using eval::TensorFunction;
-using eval::as;
-
-using namespace eval::tensor_function;
-using namespace eval::operation;
+using namespace tensor_function;
+using namespace operation;
const TensorFunction &
DensePowAsMapOptimizer::optimize(const TensorFunction &expr, Stash &stash)
@@ -35,4 +32,4 @@ DensePowAsMapOptimizer::optimize(const TensorFunction &expr, Stash &stash)
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_pow_as_map_optimizer.h b/eval/src/vespa/eval/instruction/dense_pow_as_map_optimizer.h
index 4849a10c070..e61069b87b0 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_pow_as_map_optimizer.h
+++ b/eval/src/vespa/eval/instruction/dense_pow_as_map_optimizer.h
@@ -4,15 +4,16 @@
#include <vespa/eval/eval/tensor_function.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Tensor function optimizer for converting join expressions on the
* form 'join(tensor,<small integer constant>,f(x,y)(pow(x,y))' to
* expressions on the form 'map(tensor,f(x)(x*x...))'.
+ * TODO: extend to mixed tensors.
**/
struct DensePowAsMapOptimizer {
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp b/eval/src/vespa/eval/instruction/dense_remove_dimension_optimizer.cpp
index a48527e83f5..fc7f31fb421 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.cpp
+++ b/eval/src/vespa/eval/instruction/dense_remove_dimension_optimizer.cpp
@@ -4,13 +4,9 @@
#include "dense_replace_type_function.h"
#include <vespa/eval/eval/value_type.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
-using eval::Aggr;
-using eval::ValueType;
-using eval::TensorFunction;
-using eval::as;
-using namespace eval::tensor_function;
+using namespace tensor_function;
namespace {
@@ -25,16 +21,16 @@ bool is_trivial_dim_list(const ValueType &type, const std::vector<vespalib::stri
return true;
}
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
const TensorFunction &
-DenseRemoveDimensionOptimizer::optimize(const eval::TensorFunction &expr, Stash &stash)
+DenseRemoveDimensionOptimizer::optimize(const TensorFunction &expr, Stash &stash)
{
if (auto reduce = as<Reduce>(expr)) {
const TensorFunction &child = reduce->child();
if (expr.result_type().is_dense() &&
child.result_type().is_dense() &&
- eval::aggr::is_ident(reduce->aggr()) &&
+ aggr::is_ident(reduce->aggr()) &&
is_trivial_dim_list(child.result_type(), reduce->dimensions()))
{
assert(expr.result_type().cell_type() == child.result_type().cell_type());
@@ -44,4 +40,4 @@ DenseRemoveDimensionOptimizer::optimize(const eval::TensorFunction &expr, Stash
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.h b/eval/src/vespa/eval/instruction/dense_remove_dimension_optimizer.h
index 64b057a62d8..2b4e3588caf 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_remove_dimension_optimizer.h
+++ b/eval/src/vespa/eval/instruction/dense_remove_dimension_optimizer.h
@@ -4,14 +4,15 @@
#include <vespa/eval/eval/tensor_function.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Tensor function optimizer for efficient removal of dimensions with
* size 1 for dense tensors.
+ * TODO: extend to mixed tensors.
**/
struct DenseRemoveDimensionOptimizer {
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/instruction/dense_replace_type_function.cpp b/eval/src/vespa/eval/instruction/dense_replace_type_function.cpp
new file mode 100644
index 00000000000..81d3ca67880
--- /dev/null
+++ b/eval/src/vespa/eval/instruction/dense_replace_type_function.cpp
@@ -0,0 +1,48 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "dense_replace_type_function.h"
+#include <vespa/eval/eval/value.h>
+
+namespace vespalib::eval {
+
+using namespace tensor_function;
+
+namespace {
+
+void my_replace_type_op(InterpretedFunction::State &state, uint64_t param) {
+ const ValueType &type = unwrap_param<ValueType>(param);
+ TypedCells cells = state.peek(0).cells();
+ state.pop_push(state.stash.create<DenseValueView>(type, cells));
+}
+
+} // namespace vespalib::eval::<unnamed>
+
+DenseReplaceTypeFunction::DenseReplaceTypeFunction(const ValueType &result_type,
+ const TensorFunction &child)
+ : tensor_function::Op1(result_type, child)
+{
+}
+
+DenseReplaceTypeFunction::~DenseReplaceTypeFunction()
+{
+}
+
+InterpretedFunction::Instruction
+DenseReplaceTypeFunction::compile_self(const ValueBuilderFactory &, Stash &) const
+{
+ return InterpretedFunction::Instruction(my_replace_type_op, wrap_param<ValueType>(result_type()));
+}
+
+const DenseReplaceTypeFunction &
+DenseReplaceTypeFunction::create_compact(const ValueType &result_type,
+ const TensorFunction &child,
+ Stash &stash)
+{
+ if (auto replace = as<DenseReplaceTypeFunction>(child)) {
+ return stash.create<DenseReplaceTypeFunction>(result_type, replace->child());
+ } else {
+ return stash.create<DenseReplaceTypeFunction>(result_type, child);
+ }
+}
+
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.h b/eval/src/vespa/eval/instruction/dense_replace_type_function.h
index adf5023b0cb..78ce163aceb 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.h
+++ b/eval/src/vespa/eval/instruction/dense_replace_type_function.h
@@ -4,23 +4,24 @@
#include <vespa/eval/eval/tensor_function.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Tensor function for efficient type-only modification of dense
* tensor.
+ * TODO: extend to handling any tensor, dense/mixed/sparse.
**/
-class DenseReplaceTypeFunction : public eval::tensor_function::Op1
+class DenseReplaceTypeFunction : public tensor_function::Op1
{
public:
- DenseReplaceTypeFunction(const eval::ValueType &result_type,
- const eval::TensorFunction &child);
+ DenseReplaceTypeFunction(const ValueType &result_type,
+ const TensorFunction &child);
~DenseReplaceTypeFunction();
- eval::InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
+ InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
bool result_is_mutable() const override { return child().result_is_mutable(); }
- static const DenseReplaceTypeFunction &create_compact(const eval::ValueType &result_type,
- const eval::TensorFunction &child,
+ static const DenseReplaceTypeFunction &create_compact(const ValueType &result_type,
+ const TensorFunction &child,
Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.cpp b/eval/src/vespa/eval/instruction/dense_simple_join_function.cpp
index 21b47b67291..76d020eef9d 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.cpp
+++ b/eval/src/vespa/eval/instruction/dense_simple_join_function.cpp
@@ -9,28 +9,19 @@
#include <optional>
#include <algorithm>
-namespace vespalib::tensor {
+namespace vespalib::eval {
using vespalib::ArrayRef;
-using eval::CellType;
-using eval::DenseValueView;
-using eval::TensorFunction;
-using eval::TypedCells;
-using eval::TypifyCellType;
-using eval::Value;
-using eval::ValueType;
-using eval::as;
-
-using namespace eval::operation;
-using namespace eval::tensor_function;
+using namespace operation;
+using namespace tensor_function;
using Primary = DenseSimpleJoinFunction::Primary;
using Overlap = DenseSimpleJoinFunction::Overlap;
-using op_function = eval::InterpretedFunction::op_function;
-using Instruction = eval::InterpretedFunction::Instruction;
-using State = eval::InterpretedFunction::State;
+using op_function = InterpretedFunction::op_function;
+using Instruction = InterpretedFunction::Instruction;
+using State = InterpretedFunction::State;
namespace {
@@ -67,7 +58,7 @@ template <typename LCT, typename RCT, typename Fun, bool swap, Overlap overlap,
void my_simple_join_op(State &state, uint64_t param) {
using PCT = typename std::conditional<swap,RCT,LCT>::type;
using SCT = typename std::conditional<swap,LCT,RCT>::type;
- using OCT = typename eval::UnifyCellTypes<PCT,SCT>::type;
+ using OCT = typename UnifyCellTypes<PCT,SCT>::type;
using OP = typename std::conditional<swap,SwapArgs2<Fun>,Fun>::type;
const JoinParams &params = unwrap_param<JoinParams>(param);
OP my_op(params.function);
@@ -151,7 +142,7 @@ std::optional<Overlap> detect_overlap(const TensorFunction &lhs, const TensorFun
return (primary == Primary::LHS) ? detect_overlap(lhs, rhs) : detect_overlap(rhs, lhs);
}
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
//-----------------------------------------------------------------------------
@@ -221,4 +212,4 @@ DenseSimpleJoinFunction::optimize(const TensorFunction &expr, Stash &stash)
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.h b/eval/src/vespa/eval/instruction/dense_simple_join_function.h
index 4cb4a0fc4ff..8fa0be9d021 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_simple_join_function.h
+++ b/eval/src/vespa/eval/instruction/dense_simple_join_function.h
@@ -5,23 +5,25 @@
#include <vespa/eval/eval/tensor_function.h>
#include <vespa/eval/eval/operation.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Tensor function for simple join operations on dense tensors.
+ * TODO: consider if this is useful anymore, maybe we just need
+ * to handle inplace.
**/
-class DenseSimpleJoinFunction : public eval::tensor_function::Join
+class DenseSimpleJoinFunction : public tensor_function::Join
{
- using Super = eval::tensor_function::Join;
+ using Super = tensor_function::Join;
public:
enum class Primary : uint8_t { LHS, RHS };
enum class Overlap : uint8_t { INNER, OUTER, FULL };
- using join_fun_t = vespalib::eval::operation::op2_t;
+ using join_fun_t = operation::op2_t;
private:
Primary _primary;
Overlap _overlap;
public:
- DenseSimpleJoinFunction(const eval::ValueType &result_type,
+ DenseSimpleJoinFunction(const ValueType &result_type,
const TensorFunction &lhs,
const TensorFunction &rhs,
join_fun_t function_in,
@@ -32,8 +34,8 @@ public:
Overlap overlap() const { return _overlap; }
bool primary_is_mutable() const;
size_t factor() const;
- eval::InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
+ InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.cpp b/eval/src/vespa/eval/instruction/dense_simple_map_function.cpp
index 5227b67dd92..ec7d2014436 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.cpp
+++ b/eval/src/vespa/eval/instruction/dense_simple_map_function.cpp
@@ -6,24 +6,16 @@
#include <vespa/eval/eval/operation.h>
#include <vespa/eval/eval/inline_operation.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
using vespalib::ArrayRef;
-using eval::DenseValueView;
-using eval::TensorFunction;
-using eval::TypedCells;
-using eval::TypifyCellType;
-using eval::Value;
-using eval::ValueType;
-using eval::as;
+using namespace operation;
+using namespace tensor_function;
-using namespace eval::operation;
-using namespace eval::tensor_function;
-
-using op_function = eval::InterpretedFunction::op_function;
-using Instruction = eval::InterpretedFunction::Instruction;
-using State = eval::InterpretedFunction::State;
+using op_function = InterpretedFunction::op_function;
+using Instruction = InterpretedFunction::Instruction;
+using State = InterpretedFunction::State;
namespace {
@@ -58,7 +50,7 @@ struct MyGetFun {
using MyTypify = TypifyValue<TypifyCellType,TypifyOp1,TypifyBool>;
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
//-----------------------------------------------------------------------------
@@ -90,4 +82,4 @@ DenseSimpleMapFunction::optimize(const TensorFunction &expr, Stash &stash)
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/instruction/dense_simple_map_function.h b/eval/src/vespa/eval/instruction/dense_simple_map_function.h
new file mode 100644
index 00000000000..40432f35c58
--- /dev/null
+++ b/eval/src/vespa/eval/instruction/dense_simple_map_function.h
@@ -0,0 +1,26 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include <vespa/eval/eval/tensor_function.h>
+
+namespace vespalib::eval {
+
+/**
+ * Tensor function for simple map operations on dense tensors.
+ * TODO: Fix generic map to handle inplace, and remove this.
+ **/
+class DenseSimpleMapFunction : public tensor_function::Map
+{
+public:
+ using map_fun_t = operation::op1_t;
+ DenseSimpleMapFunction(const ValueType &result_type,
+ const TensorFunction &child,
+ map_fun_t function_in);
+ ~DenseSimpleMapFunction() override;
+ bool inplace() const { return child().result_is_mutable(); }
+ InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
+};
+
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.cpp b/eval/src/vespa/eval/instruction/dense_single_reduce_function.cpp
index c10fd6c0fe7..53e91f729ee 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.cpp
+++ b/eval/src/vespa/eval/instruction/dense_single_reduce_function.cpp
@@ -5,21 +5,10 @@
#include <vespa/eval/eval/value.h>
#include <cassert>
-namespace vespalib::tensor {
+namespace vespalib::eval {
-using eval::Aggr;
-using eval::DenseValueView;
-using eval::InterpretedFunction;
-using eval::TensorFunction;
-using eval::Value;
-using eval::ValueType;
-using eval::TypedCells;
-using eval::TypifyCellType;
-using eval::TypifyAggr;
-using eval::as;
-
-using namespace eval::tensor_function;
-using namespace eval::aggr;
+using namespace tensor_function;
+using namespace aggr;
namespace {
@@ -166,7 +155,7 @@ template <typename T> struct VectorLookupLoop {
const T &get() const { return list[index]; }
};
-DenseSingleReduceSpec extract_next(const eval::ValueType &type, eval::Aggr aggr,
+DenseSingleReduceSpec extract_next(const ValueType &type, Aggr aggr,
std::vector<vespalib::string> &todo)
{
size_t outer_size = 1;
@@ -200,10 +189,10 @@ DenseSingleReduceSpec extract_next(const eval::ValueType &type, eval::Aggr aggr,
return {type.reduce(do_now), outer_size, reduce_size, inner_size, aggr};
}
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
std::vector<DenseSingleReduceSpec>
-make_dense_single_reduce_list(const eval::ValueType &type, eval::Aggr aggr,
+make_dense_single_reduce_list(const ValueType &type, Aggr aggr,
const std::vector<vespalib::string> &reduce_dims)
{
auto res_type = type.reduce(reduce_dims);
@@ -217,7 +206,7 @@ make_dense_single_reduce_list(const eval::ValueType &type, eval::Aggr aggr,
curr_type = list.back().result_type;
}
assert(curr_type == res_type);
- if ((list.size() > 1) && !eval::aggr::is_simple(aggr)) {
+ if ((list.size() > 1) && !aggr::is_simple(aggr)) {
return {};
}
return list;
@@ -261,4 +250,4 @@ DenseSingleReduceFunction::optimize(const TensorFunction &expr, Stash &stash)
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.h b/eval/src/vespa/eval/instruction/dense_single_reduce_function.h
index 8bdcf82d4ab..ed68bd48c15 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_single_reduce_function.h
+++ b/eval/src/vespa/eval/instruction/dense_single_reduce_function.h
@@ -4,14 +4,14 @@
#include <vespa/eval/eval/tensor_function.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
struct DenseSingleReduceSpec {
- eval::ValueType result_type;
+ ValueType result_type;
size_t outer_size;
size_t reduce_size;
size_t inner_size;
- eval::Aggr aggr;
+ Aggr aggr;
};
/**
@@ -20,7 +20,7 @@ struct DenseSingleReduceSpec {
* fails.
**/
std::vector<DenseSingleReduceSpec>
-make_dense_single_reduce_list(const eval::ValueType &type, eval::Aggr aggr,
+make_dense_single_reduce_list(const ValueType &type, Aggr aggr,
const std::vector<vespalib::string> &reduce_dims);
/**
@@ -30,26 +30,28 @@ make_dense_single_reduce_list(const eval::ValueType &type, eval::Aggr aggr,
* operation. Adjacent reduced dimensions will be handled is if they
* were a single dimension. Trivial dimensions will be trivially
* reduced along with any other dimension.
+ * TODO: consider if we should extend this to handling mixed tensors
+ * (handling the spare part as a batch dimension).
**/
-class DenseSingleReduceFunction : public eval::tensor_function::Op1
+class DenseSingleReduceFunction : public tensor_function::Op1
{
private:
size_t _outer_size;
size_t _reduce_size;
size_t _inner_size;
- eval::Aggr _aggr;
+ Aggr _aggr;
public:
DenseSingleReduceFunction(const DenseSingleReduceSpec &spec,
- const eval::TensorFunction &child);
+ const TensorFunction &child);
~DenseSingleReduceFunction() override;
size_t outer_size() const { return _outer_size; }
size_t reduce_size() const { return _reduce_size; }
size_t inner_size() const { return _inner_size; }
- eval::Aggr aggr() const { return _aggr; }
+ Aggr aggr() const { return _aggr; }
bool result_is_mutable() const override { return true; }
- eval::InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
+ InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.cpp b/eval/src/vespa/eval/instruction/dense_tensor_create_function.cpp
index c233a51a473..0f41158c36e 100644
--- a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.cpp
+++ b/eval/src/vespa/eval/instruction/dense_tensor_create_function.cpp
@@ -3,23 +3,15 @@
#include "dense_tensor_create_function.h"
#include <vespa/eval/eval/value.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
-using eval::DenseValueView;
-using eval::DoubleValue;
-using eval::TensorFunction;
-using eval::TensorSpec;
-using eval::TypedCells;
-using eval::Value;
-using eval::ValueType;
-using Child = eval::TensorFunction::Child;
-using eval::as;
-using namespace eval::tensor_function;
+using Child = TensorFunction::Child;
+using namespace tensor_function;
namespace {
template <typename CT>
-void my_tensor_create_op(eval::InterpretedFunction::State &state, uint64_t param) {
+void my_tensor_create_op(InterpretedFunction::State &state, uint64_t param) {
const auto &self = unwrap_param<DenseTensorCreateFunction::Self>(param);
size_t pending_cells = self.result_size;
ArrayRef<CT> cells = state.stash.create_uninitialized_array<CT>(pending_cells);
@@ -48,7 +40,7 @@ size_t get_index(const TensorSpec::Address &addr, const ValueType &type) {
return cell_idx;
}
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
DenseTensorCreateFunction::DenseTensorCreateFunction(const ValueType &res_type, std::vector<Child> children)
: TensorFunction(),
@@ -67,16 +59,16 @@ DenseTensorCreateFunction::push_children(std::vector<Child::CREF> &target) const
}
}
-eval::InterpretedFunction::Instruction
+InterpretedFunction::Instruction
DenseTensorCreateFunction::compile_self(const ValueBuilderFactory &, Stash &) const
{
- using MyTypify = eval::TypifyCellType;
+ using MyTypify = TypifyCellType;
auto op = typify_invoke<1,MyTypify,MyTensorCreateOp>(result_type().cell_type());
- return eval::InterpretedFunction::Instruction(op, wrap_param<DenseTensorCreateFunction::Self>(_self));
+ return InterpretedFunction::Instruction(op, wrap_param<DenseTensorCreateFunction::Self>(_self));
}
const TensorFunction &
-DenseTensorCreateFunction::optimize(const eval::TensorFunction &expr, Stash &stash)
+DenseTensorCreateFunction::optimize(const TensorFunction &expr, Stash &stash)
{
if (auto create = as<Create>(expr)) {
if (expr.result_type().is_dense()) {
@@ -94,4 +86,4 @@ DenseTensorCreateFunction::optimize(const eval::TensorFunction &expr, Stash &sta
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/instruction/dense_tensor_create_function.h b/eval/src/vespa/eval/instruction/dense_tensor_create_function.h
new file mode 100644
index 00000000000..9af912ba788
--- /dev/null
+++ b/eval/src/vespa/eval/instruction/dense_tensor_create_function.h
@@ -0,0 +1,34 @@
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include <vespa/eval/eval/tensor_function.h>
+
+namespace vespalib::eval {
+
+/**
+ * Tensor function for creating a dense tensor from double values.
+ * TODO: benchmark how useful this is, maybe we can just drop it.
+ */
+class DenseTensorCreateFunction : public TensorFunction
+{
+public:
+ struct Self {
+ ValueType result_type;
+ size_t result_size;
+ Self(const ValueType &r, size_t n) : result_type(r), result_size(n) {}
+ };
+private:
+ Self _self;
+ std::vector<Child> _children;
+public:
+ DenseTensorCreateFunction(const ValueType &res_type, std::vector<Child> children);
+ ~DenseTensorCreateFunction();
+ const ValueType &result_type() const override { return _self.result_type; }
+ void push_children(std::vector<Child::CREF> &children) const override;
+ InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
+ bool result_is_mutable() const override { return true; }
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
+};
+
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/instruction/generic_join.h b/eval/src/vespa/eval/instruction/generic_join.h
index e5ddf388211..988286be980 100644
--- a/eval/src/vespa/eval/instruction/generic_join.h
+++ b/eval/src/vespa/eval/instruction/generic_join.h
@@ -12,7 +12,7 @@ namespace vespalib::eval { struct ValueBuilderFactory; }
namespace vespalib::eval::instruction {
-using join_fun_t = vespalib::eval::operation::op2_t;
+using join_fun_t = operation::op2_t;
//-----------------------------------------------------------------------------
diff --git a/eval/src/vespa/eval/instruction/generic_lambda.cpp b/eval/src/vespa/eval/instruction/generic_lambda.cpp
index 5685f199b9e..f4f8c84a257 100644
--- a/eval/src/vespa/eval/instruction/generic_lambda.cpp
+++ b/eval/src/vespa/eval/instruction/generic_lambda.cpp
@@ -59,7 +59,7 @@ struct CompiledParams {
};
template <typename CT>
-void my_compiled_lambda_op(eval::InterpretedFunction::State &state, uint64_t param) {
+void my_compiled_lambda_op(InterpretedFunction::State &state, uint64_t param) {
const CompiledParams &params = unwrap_param<CompiledParams>(param);
std::vector<double> args(params.result_type.dimensions().size() + params.bindings.size(), 0.0);
double *bind_next = &args[params.result_type.dimensions().size()];
@@ -98,7 +98,7 @@ struct InterpretedParams {
};
template <typename CT>
-void my_interpreted_lambda_op(eval::InterpretedFunction::State &state, uint64_t param) {
+void my_interpreted_lambda_op(InterpretedFunction::State &state, uint64_t param) {
const InterpretedParams &params = unwrap_param<InterpretedParams>(param);
std::vector<double> labels(params.result_type.dimensions().size(), 0.0);
ParamProxy param_proxy(labels, *state.params, params.bindings);
@@ -121,7 +121,7 @@ struct MyInterpretedLambdaOp {
} // namespace <unnamed>
Instruction
-GenericLambda::make_instruction(const eval::tensor_function::Lambda &lambda_in,
+GenericLambda::make_instruction(const tensor_function::Lambda &lambda_in,
const ValueBuilderFactory &factory, Stash &stash)
{
const ValueType & result_type = lambda_in.result_type();
diff --git a/eval/src/vespa/eval/instruction/generic_lambda.h b/eval/src/vespa/eval/instruction/generic_lambda.h
index a9a490f0957..a5f4c10e214 100644
--- a/eval/src/vespa/eval/instruction/generic_lambda.h
+++ b/eval/src/vespa/eval/instruction/generic_lambda.h
@@ -10,7 +10,7 @@ namespace vespalib::eval::instruction {
struct GenericLambda {
static InterpretedFunction::Instruction
- make_instruction(const eval::tensor_function::Lambda &lambda_in,
+ make_instruction(const tensor_function::Lambda &lambda_in,
const ValueBuilderFactory &factory, Stash &stash);
};
diff --git a/eval/src/vespa/eval/instruction/generic_map.h b/eval/src/vespa/eval/instruction/generic_map.h
index ad29d2c1073..2c03512a922 100644
--- a/eval/src/vespa/eval/instruction/generic_map.h
+++ b/eval/src/vespa/eval/instruction/generic_map.h
@@ -10,7 +10,7 @@ namespace vespalib::eval { struct ValueBuilderFactory; }
namespace vespalib::eval::instruction {
-using map_fun_t = vespalib::eval::operation::op1_t;
+using map_fun_t = operation::op1_t;
struct GenericMap {
static InterpretedFunction::Instruction
diff --git a/eval/src/vespa/eval/instruction/join_with_number_function.h b/eval/src/vespa/eval/instruction/join_with_number_function.h
index 351f9b005cb..546ff75b175 100644
--- a/eval/src/vespa/eval/instruction/join_with_number_function.h
+++ b/eval/src/vespa/eval/instruction/join_with_number_function.h
@@ -20,7 +20,7 @@ private:
tensor_function::join_fun_t _function;
public:
- JoinWithNumberFunction(const vespalib::eval::tensor_function::Join &original_join, bool number_on_left);
+ JoinWithNumberFunction(const tensor_function::Join &original_join, bool number_on_left);
~JoinWithNumberFunction();
Primary primary() const { return _primary; }
bool inplace() const;
@@ -31,5 +31,5 @@ public:
static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp b/eval/src/vespa/eval/instruction/vector_from_doubles_function.cpp
index 19c95c9418d..40bd9e25dfc 100644
--- a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.cpp
+++ b/eval/src/vespa/eval/instruction/vector_from_doubles_function.cpp
@@ -3,24 +3,17 @@
#include "vector_from_doubles_function.h"
#include <vespa/eval/eval/value.h>
-namespace vespalib::tensor {
-
-using eval::CellType;
-using eval::DenseValueView;
-using eval::TensorFunction;
-using eval::TypedCells;
-using eval::Value;
-using eval::ValueType;
-using Child = eval::TensorFunction::Child;
-using eval::as;
-using namespace eval::tensor_function;
+namespace vespalib::eval {
+
+using Child = TensorFunction::Child;
+using namespace tensor_function;
namespace {
struct CallVectorFromDoubles {
template <typename CT>
static TypedCells
- invoke(eval::InterpretedFunction::State &state, size_t numCells) {
+ invoke(InterpretedFunction::State &state, size_t numCells) {
ArrayRef<CT> outputCells = state.stash.create_uninitialized_array<CT>(numCells);
for (size_t i = numCells; i-- > 0; ) {
outputCells[i] = (CT) state.peek(0).as_double();
@@ -30,11 +23,11 @@ struct CallVectorFromDoubles {
}
};
-void my_vector_from_doubles_op(eval::InterpretedFunction::State &state, uint64_t param) {
+void my_vector_from_doubles_op(InterpretedFunction::State &state, uint64_t param) {
const auto &self = unwrap_param<VectorFromDoublesFunction::Self>(param);
CellType ct = self.resultType.cell_type();
size_t numCells = self.resultSize;
- using MyTypify = eval::TypifyCellType;
+ using MyTypify = TypifyCellType;
TypedCells cells = typify_invoke<1,MyTypify,CallVectorFromDoubles>(ct, state, numCells);
const Value &result = state.stash.create<DenseValueView>(self.resultType, cells);
state.stack.emplace_back(result);
@@ -72,7 +65,7 @@ std::vector<Child> flatten(const TensorFunction &lhs, const TensorFunction &rhs)
return vec;
}
-} // namespace vespalib::tensor::<unnamed>
+} // namespace vespalib::eval::<unnamed>
VectorFromDoublesFunction::VectorFromDoublesFunction(std::vector<Child> children, const ValueType &res_type)
@@ -92,14 +85,14 @@ VectorFromDoublesFunction::push_children(std::vector<Child::CREF> &target) const
}
}
-eval::InterpretedFunction::Instruction
+InterpretedFunction::Instruction
VectorFromDoublesFunction::compile_self(const ValueBuilderFactory &, Stash &) const
{
- return eval::InterpretedFunction::Instruction(my_vector_from_doubles_op, wrap_param<VectorFromDoublesFunction::Self>(_self));
+ return InterpretedFunction::Instruction(my_vector_from_doubles_op, wrap_param<VectorFromDoublesFunction::Self>(_self));
}
const TensorFunction &
-VectorFromDoublesFunction::optimize(const eval::TensorFunction &expr, Stash &stash)
+VectorFromDoublesFunction::optimize(const TensorFunction &expr, Stash &stash)
{
if (auto concat = as<Concat>(expr)) {
const vespalib::string &dimension = concat->dimension();
@@ -114,4 +107,4 @@ VectorFromDoublesFunction::optimize(const eval::TensorFunction &expr, Stash &sta
return expr;
}
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.h b/eval/src/vespa/eval/instruction/vector_from_doubles_function.h
index d21a339e7d9..c22ea99f41a 100644
--- a/eval/src/vespa/eval/tensor/dense/vector_from_doubles_function.h
+++ b/eval/src/vespa/eval/instruction/vector_from_doubles_function.h
@@ -4,35 +4,37 @@
#include <vespa/eval/eval/tensor_function.h>
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Tensor function for a concat forming a vector from double values
+ * TODO: consider removing this, since the user can write a tensor
+ * create expression instead.
*/
-class VectorFromDoublesFunction : public eval::TensorFunction
+class VectorFromDoublesFunction : public TensorFunction
{
public:
struct Self {
- const eval::ValueType resultType;
+ const ValueType resultType;
size_t resultSize;
- Self(const eval::ValueType &r, size_t n) : resultType(r), resultSize(n) {}
+ Self(const ValueType &r, size_t n) : resultType(r), resultSize(n) {}
};
private:
Self _self;
std::vector<Child> _children;
- void add(const eval::TensorFunction &child);
+ void add(const TensorFunction &child);
public:
- VectorFromDoublesFunction(std::vector<Child> children, const eval::ValueType &res_type);
+ VectorFromDoublesFunction(std::vector<Child> children, const ValueType &res_type);
~VectorFromDoublesFunction();
- const eval::ValueType &result_type() const override { return _self.resultType; }
+ const ValueType &result_type() const override { return _self.resultType; }
void push_children(std::vector<Child::CREF> &children) const override;
const vespalib::string &dimension() const {
return _self.resultType.dimensions()[0].name;
}
size_t size() const { return _self.resultSize; }
- eval::InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
+ InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
bool result_is_mutable() const override { return true; }
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
+ static const TensorFunction &optimize(const TensorFunction &expr, Stash &stash);
};
-} // namespace vespalib::tensor
+} // namespace vespalib::eval
diff --git a/eval/src/vespa/eval/onnx/onnx_wrapper.cpp b/eval/src/vespa/eval/onnx/onnx_wrapper.cpp
index 521d2382666..d9c0d659b1e 100644
--- a/eval/src/vespa/eval/onnx/onnx_wrapper.cpp
+++ b/eval/src/vespa/eval/onnx/onnx_wrapper.cpp
@@ -18,16 +18,10 @@ LOG_SETUP(".eval.onnx_wrapper");
using vespalib::ArrayRef;
using vespalib::ConstArrayRef;
-using vespalib::eval::CellType;
-using vespalib::eval::DenseValueView;
-using vespalib::eval::DenseCellsValue;
-using vespalib::eval::TypedCells;
-using vespalib::eval::TypifyCellType;
-using vespalib::eval::ValueType;
using vespalib::make_string_short::fmt;
-namespace vespalib::tensor {
+namespace vespalib::eval {
namespace {
@@ -72,23 +66,23 @@ struct CreateOnnxTensor {
};
struct CreateVespaTensorRef {
- template <typename T> static eval::Value::UP invoke(const eval::ValueType &type_ref, Ort::Value &value) {
+ template <typename T> static Value::UP invoke(const ValueType &type_ref, Ort::Value &value) {
size_t num_cells = type_ref.dense_subspace_size();
ConstArrayRef<T> cells(value.GetTensorMutableData<T>(), num_cells);
return std::make_unique<DenseValueView>(type_ref, TypedCells(cells));
}
- eval::Value::UP operator()(const eval::ValueType &type_ref, Ort::Value &value) {
+ Value::UP operator()(const ValueType &type_ref, Ort::Value &value) {
return typify_invoke<1,MyTypify,CreateVespaTensorRef>(type_ref.cell_type(), type_ref, value);
}
};
struct CreateVespaTensor {
- template <typename T> static eval::Value::UP invoke(const eval::ValueType &type) {
+ template <typename T> static Value::UP invoke(const ValueType &type) {
size_t num_cells = type.dense_subspace_size();
std::vector<T> cells(num_cells, T{});
return std::make_unique<DenseCellsValue<T>>(type, std::move(cells));
}
- eval::Value::UP operator()(const eval::ValueType &type) {
+ Value::UP operator()(const ValueType &type) {
return typify_invoke<1,MyTypify,CreateVespaTensor>(type.cell_type(), type);
}
};
@@ -205,7 +199,7 @@ Onnx::TensorInfo make_tensor_info(const OnnxString &name, const Ort::TypeInfo &t
return Onnx::TensorInfo{vespalib::string(name.get()), make_dimensions(tensor_info), make_element_type(element_type)};
}
-std::vector<int64_t> extract_sizes(const eval::ValueType &type) {
+std::vector<int64_t> extract_sizes(const ValueType &type) {
std::vector<int64_t> sizes;
for (const auto &dim: type.dimensions()) {
sizes.push_back(dim.size);
@@ -246,7 +240,7 @@ Onnx::WireInfo::~WireInfo() = default;
Onnx::WirePlanner::~WirePlanner() = default;
bool
-Onnx::WirePlanner::bind_input_type(const eval::ValueType &vespa_in, const TensorInfo &onnx_in)
+Onnx::WirePlanner::bind_input_type(const ValueType &vespa_in, const TensorInfo &onnx_in)
{
const auto &type = vespa_in;
const auto &name = onnx_in.name;
@@ -275,7 +269,7 @@ Onnx::WirePlanner::bind_input_type(const eval::ValueType &vespa_in, const Tensor
return true;
}
-eval::ValueType
+ValueType
Onnx::WirePlanner::make_output_type(const TensorInfo &onnx_out) const
{
const auto &dimensions = onnx_out.dimensions;
@@ -347,7 +341,7 @@ Ort::AllocatorWithDefaultOptions Onnx::EvalContext::_alloc;
template <typename T>
void
-Onnx::EvalContext::adapt_param(EvalContext &self, size_t idx, const eval::Value &param)
+Onnx::EvalContext::adapt_param(EvalContext &self, size_t idx, const Value &param)
{
const auto &cells_ref = param.cells();
auto cells = unconstify(cells_ref.typify<T>());
@@ -357,7 +351,7 @@ Onnx::EvalContext::adapt_param(EvalContext &self, size_t idx, const eval::Value
template <typename SRC, typename DST>
void
-Onnx::EvalContext::convert_param(EvalContext &self, size_t idx, const eval::Value &param)
+Onnx::EvalContext::convert_param(EvalContext &self, size_t idx, const Value &param)
{
auto cells = param.cells().typify<SRC>();
size_t n = cells.size();
@@ -384,21 +378,21 @@ Onnx::EvalContext::convert_result(EvalContext &self, size_t idx)
struct Onnx::EvalContext::SelectAdaptParam {
template <typename ...Ts> static auto invoke() { return adapt_param<Ts...>; }
- auto operator()(eval::CellType ct) {
+ auto operator()(CellType ct) {
return typify_invoke<1,MyTypify,SelectAdaptParam>(ct);
}
};
struct Onnx::EvalContext::SelectConvertParam {
template <typename ...Ts> static auto invoke() { return convert_param<Ts...>; }
- auto operator()(eval::CellType ct, Onnx::ElementType et) {
+ auto operator()(CellType ct, Onnx::ElementType et) {
return typify_invoke<2,MyTypify,SelectConvertParam>(ct, et);
}
};
struct Onnx::EvalContext::SelectConvertResult {
template <typename ...Ts> static auto invoke() { return convert_result<Ts...>; }
- auto operator()(Onnx::ElementType et, eval::CellType ct) {
+ auto operator()(Onnx::ElementType et, CellType ct) {
return typify_invoke<2,MyTypify,SelectConvertResult>(et, ct);
}
};
@@ -452,7 +446,7 @@ Onnx::EvalContext::EvalContext(const Onnx &model, const WireInfo &wire_info)
Onnx::EvalContext::~EvalContext() = default;
void
-Onnx::EvalContext::bind_param(size_t i, const eval::Value &param)
+Onnx::EvalContext::bind_param(size_t i, const Value &param)
{
_param_binders[i](*this, i, param);
}
@@ -470,7 +464,7 @@ Onnx::EvalContext::eval()
}
}
-const eval::Value &
+const Value &
Onnx::EvalContext::get_result(size_t i) const
{
return *_results[i];
diff --git a/eval/src/vespa/eval/onnx/onnx_wrapper.h b/eval/src/vespa/eval/onnx/onnx_wrapper.h
index f42b926d17e..68c31f04cdc 100644
--- a/eval/src/vespa/eval/onnx/onnx_wrapper.h
+++ b/eval/src/vespa/eval/onnx/onnx_wrapper.h
@@ -16,7 +16,7 @@
namespace vespalib::eval { struct Value; }
-namespace vespalib::tensor {
+namespace vespalib::eval {
/**
* Wrapper around an ONNX model handeled by onnxruntime.
@@ -72,24 +72,24 @@ public:
// how the model should be wired with inputs/outputs
struct WireInfo {
- std::vector<eval::ValueType> vespa_inputs;
+ std::vector<ValueType> vespa_inputs;
std::vector<Onnx::TensorType> onnx_inputs;
std::vector<Onnx::TensorType> onnx_outputs;
- std::vector<eval::ValueType> vespa_outputs;
+ std::vector<ValueType> vespa_outputs;
~WireInfo();
};
// planning how we should wire the model based on input types
class WirePlanner {
private:
- std::map<vespalib::string,eval::ValueType> _input_types;
+ std::map<vespalib::string,ValueType> _input_types;
std::map<vespalib::string,size_t> _symbolic_sizes;
std::set<size_t> _bound_unknown_sizes;
public:
WirePlanner() : _input_types(), _symbolic_sizes(), _bound_unknown_sizes() {}
~WirePlanner();
- bool bind_input_type(const eval::ValueType &vespa_in, const TensorInfo &onnx_in);
- eval::ValueType make_output_type(const TensorInfo &onnx_out) const;
+ bool bind_input_type(const ValueType &vespa_in, const TensorInfo &onnx_in);
+ ValueType make_output_type(const TensorInfo &onnx_out) const;
WireInfo get_wire_info(const Onnx &model) const;
};
@@ -98,7 +98,7 @@ public:
// output values are pre-allocated and will not change
class EvalContext {
private:
- using param_fun_t = void (*)(EvalContext &, size_t i, const eval::Value &);
+ using param_fun_t = void (*)(EvalContext &, size_t i, const Value &);
using result_fun_t = void (*)(EvalContext &, size_t i);
static Ort::AllocatorWithDefaultOptions _alloc;
@@ -108,15 +108,15 @@ public:
Ort::MemoryInfo _cpu_memory;
std::vector<Ort::Value> _param_values;
std::vector<Ort::Value> _result_values;
- std::vector<eval::Value::UP> _results;
+ std::vector<Value::UP> _results;
std::vector<param_fun_t> _param_binders;
std::vector<std::pair<size_t,result_fun_t>> _result_converters;
template <typename T>
- static void adapt_param(EvalContext &self, size_t idx, const eval::Value &param);
+ static void adapt_param(EvalContext &self, size_t idx, const Value &param);
template <typename SRC, typename DST>
- static void convert_param(EvalContext &self, size_t idx, const eval::Value &param);
+ static void convert_param(EvalContext &self, size_t idx, const Value &param);
template <typename SRC, typename DST>
static void convert_result(EvalContext &self, size_t idx);
@@ -130,9 +130,9 @@ public:
~EvalContext();
size_t num_params() const { return _param_values.size(); }
size_t num_results() const { return _result_values.size(); }
- void bind_param(size_t i, const eval::Value &param);
+ void bind_param(size_t i, const Value &param);
void eval();
- const eval::Value &get_result(size_t i) const;
+ const Value &get_result(size_t i) const;
};
private:
diff --git a/eval/src/vespa/eval/tensor/dense/CMakeLists.txt b/eval/src/vespa/eval/tensor/dense/CMakeLists.txt
index 8e506890b20..d561df80d14 100644
--- a/eval/src/vespa/eval/tensor/dense/CMakeLists.txt
+++ b/eval/src/vespa/eval/tensor/dense/CMakeLists.txt
@@ -1,15 +1,5 @@
# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(eval_tensor_dense OBJECT
SOURCES
- dense_add_dimension_optimizer.cpp
- dense_fast_rename_optimizer.cpp
- dense_pow_as_map_optimizer.cpp
- dense_remove_dimension_optimizer.cpp
- dense_replace_type_function.cpp
- dense_simple_join_function.cpp
- dense_simple_map_function.cpp
- dense_single_reduce_function.cpp
- dense_tensor_create_function.cpp
mutable_dense_tensor_view.cpp
- vector_from_doubles_function.cpp
)
diff --git a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp b/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp
deleted file mode 100644
index ed75d6fff98..00000000000
--- a/eval/src/vespa/eval/tensor/dense/dense_replace_type_function.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "dense_replace_type_function.h"
-#include <vespa/eval/eval/value.h>
-
-namespace vespalib::tensor {
-
-using eval::DenseValueView;
-using eval::TypedCells;
-using eval::Value;
-using eval::ValueType;
-using eval::TensorFunction;
-using eval::as;
-using namespace eval::tensor_function;
-
-namespace {
-
-void my_replace_type_op(eval::InterpretedFunction::State &state, uint64_t param) {
- const ValueType &type = unwrap_param<ValueType>(param);
- TypedCells cells = state.peek(0).cells();
- state.pop_push(state.stash.create<DenseValueView>(type, cells));
-}
-
-} // namespace vespalib::tensor::<unnamed>
-
-DenseReplaceTypeFunction::DenseReplaceTypeFunction(const eval::ValueType &result_type,
- const eval::TensorFunction &child)
- : eval::tensor_function::Op1(result_type, child)
-{
-}
-
-DenseReplaceTypeFunction::~DenseReplaceTypeFunction()
-{
-}
-
-eval::InterpretedFunction::Instruction
-DenseReplaceTypeFunction::compile_self(const ValueBuilderFactory &, Stash &) const
-{
- return eval::InterpretedFunction::Instruction(my_replace_type_op, wrap_param<ValueType>(result_type()));
-}
-
-const DenseReplaceTypeFunction &
-DenseReplaceTypeFunction::create_compact(const eval::ValueType &result_type,
- const eval::TensorFunction &child,
- Stash &stash)
-{
- if (auto replace = as<DenseReplaceTypeFunction>(child)) {
- return stash.create<DenseReplaceTypeFunction>(result_type, replace->child());
- } else {
- return stash.create<DenseReplaceTypeFunction>(result_type, child);
- }
-}
-
-} // namespace vespalib::tensor
diff --git a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h b/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h
deleted file mode 100644
index 02a81ec137b..00000000000
--- a/eval/src/vespa/eval/tensor/dense/dense_simple_map_function.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#pragma once
-
-#include <vespa/eval/eval/tensor_function.h>
-
-namespace vespalib::tensor {
-
-/**
- * Tensor function for simple map operations on dense tensors.
- **/
-class DenseSimpleMapFunction : public eval::tensor_function::Map
-{
-public:
- using map_fun_t = vespalib::eval::operation::op1_t;
- DenseSimpleMapFunction(const eval::ValueType &result_type,
- const TensorFunction &child,
- map_fun_t function_in);
- ~DenseSimpleMapFunction() override;
- bool inplace() const { return child().result_is_mutable(); }
- eval::InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
-};
-
-} // namespace vespalib::tensor
diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor.cpp b/eval/src/vespa/eval/tensor/dense/dense_tensor.cpp
deleted file mode 100644
index 26f9194c8ce..00000000000
--- a/eval/src/vespa/eval/tensor/dense/dense_tensor.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "dense_tensor.h"
-#include <vespa/vespalib/util/stringfmt.h>
-#include <vespa/vespalib/util/exceptions.h>
-
-using vespalib::eval::TensorSpec;
-
-namespace vespalib::tensor {
-
-namespace {
-
-size_t
-calcCellsSize(const eval::ValueType &type)
-{
- size_t cellsSize = 1;
- for (const auto &dim : type.dimensions()) {
- cellsSize *= dim.size;
- }
- return cellsSize;
-}
-
-template<typename T>
-void
-checkCellsSize(const DenseTensor<T> &arg)
-{
- auto cellsSize = calcCellsSize(arg.fast_type());
- if (arg.cells().size != cellsSize) {
- throw IllegalStateException(make_string("Wrong cell size, "
- "expected=%zu, "
- "actual=%zu",
- cellsSize,
- arg.cells().size));
- }
- if (arg.fast_type().cell_type() != arg.cells().type) {
- throw IllegalStateException(make_string("Wrong cell type, "
- "expected=%u, "
- "actual=%u",
- (unsigned char)arg.fast_type().cell_type(),
- (unsigned char)arg.cells().type));
- }
-}
-
-}
-
-template <typename CT>
-DenseTensor<CT>::DenseTensor(eval::ValueType type_in,
- std::vector<CT> &&cells_in)
- : DenseTensorView(_type),
- _type(std::move(type_in)),
- _cells(std::move(cells_in))
-{
- initCellsRef(TypedCells(_cells));
- checkCellsSize(*this);
-}
-
-template <typename CT>
-DenseTensor<CT>::~DenseTensor() = default;
-
-template <typename CT>
-template <typename RCT>
-bool
-DenseTensor<CT>::operator==(const DenseTensor<RCT> &rhs) const
-{
- if (_type != rhs._type) return false;
- if (_cells.size != rhs._cells.size) return false;
- for (size_t i = 0; i < _cells.size; i++) {
- if (_cells[i] != rhs._cells[i]) return false;
- }
- return true;
-}
-
-template class DenseTensor<float>;
-template class DenseTensor<double>;
-
-}
diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h b/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h
deleted file mode 100644
index c0c238a2a89..00000000000
--- a/eval/src/vespa/eval/tensor/dense/dense_tensor_create_function.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#pragma once
-
-#include <vespa/eval/eval/tensor_function.h>
-
-namespace vespalib::tensor {
-
-/**
- * Tensor function for creating a dense tensor from double values.
- */
-class DenseTensorCreateFunction : public eval::TensorFunction
-{
-public:
- struct Self {
- eval::ValueType result_type;
- size_t result_size;
- Self(const eval::ValueType &r, size_t n) : result_type(r), result_size(n) {}
- };
-private:
- Self _self;
- std::vector<Child> _children;
-public:
- DenseTensorCreateFunction(const eval::ValueType &res_type, std::vector<Child> children);
- ~DenseTensorCreateFunction();
- const eval::ValueType &result_type() const override { return _self.result_type; }
- void push_children(std::vector<Child::CREF> &children) const override;
- eval::InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &factory, Stash &stash) const override;
- bool result_is_mutable() const override { return true; }
- static const eval::TensorFunction &optimize(const eval::TensorFunction &expr, Stash &stash);
-};
-
-} // namespace vespalib::tensor
diff --git a/eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.cpp b/eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.cpp
deleted file mode 100644
index 385da6d1fcd..00000000000
--- a/eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-
-#include "typed_dense_tensor_builder.h"
-
-namespace vespalib::tensor {
-
-using Address = DenseTensorView::Address;
-using eval::ValueType;
-
-namespace {
-
-size_t
-calculateCellsSize(const ValueType &type)
-{
- size_t cellsSize = 1;
- for (const auto &dim : type.dimensions()) {
- cellsSize *= dim.size;
- }
- return cellsSize;
-}
-
-} // namespace
-
-template <typename CT>
-TypedDenseTensorBuilder<CT>::~TypedDenseTensorBuilder() = default;
-
-template <typename CT>
-TypedDenseTensorBuilder<CT>::TypedDenseTensorBuilder(const ValueType &type_in)
- : _type(type_in),
- _cells(calculateCellsSize(_type))
-{
- assert(vespalib::eval::check_cell_type<CT>(_type.cell_type()));
-}
-
-template <typename CT>
-Tensor::UP
-TypedDenseTensorBuilder<CT>::build()
-{
- return std::make_unique<DenseTensor<CT>>(std::move(_type), std::move(_cells));
-}
-
-template class TypedDenseTensorBuilder<double>;
-template class TypedDenseTensorBuilder<float>;
-
-} // namespace
diff --git a/eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.h b/eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.h
deleted file mode 100644
index 770ea4ae5ea..00000000000
--- a/eval/src/vespa/eval/tensor/dense/typed_dense_tensor_builder.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#pragma once
-
-#include "dense_tensor.h"
-
-namespace vespalib::tensor {
-
-/**
- * Class for building a dense tensor by inserting cell values directly into underlying array of cells.
- */
-template <typename CT>
-class TypedDenseTensorBuilder
-{
-public:
- using Address = DenseTensorView::Address;
-private:
- eval::ValueType _type;
- std::vector<CT> _cells;
-
- static size_t calculateCellAddress(const Address &address, const eval::ValueType &type) {
- size_t result = 0;
- for (size_t i = 0; i < address.size(); ++i) {
- result *= type.dimensions()[i].size;
- result += address[i];
- }
- return result;
- }
-public:
- TypedDenseTensorBuilder(const eval::ValueType &type_in);
- ~TypedDenseTensorBuilder();
- void insertCell(const Address &address, CT cellValue) {
- insertCell(calculateCellAddress(address, _type), cellValue);
- }
- void insertCell(size_t index, CT cellValue) {
- _cells[index] = cellValue;
- }
- Tensor::UP build();
-};
-
-}
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 728029b0ed9..a53c0bd6a78 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
@@ -113,6 +113,13 @@ public class Flags {
"Takes effect at restart of distributor and content node process",
ZONE_ID, APPLICATION_ID);
+ public static final UnboundBooleanFlag USE_FAST_VALUE_TENSOR_IMPLEMENTATION = defineFeatureFlag(
+ "use-fast-value-tensor-implementation", false,
+ List.of("geirst"), "2020-12-02", "2021-02-01",
+ "Whether to use FastValueBuilderFactory as the tensor implementation on all content nodes.",
+ "Takes effect at restart of content node process",
+ ZONE_ID, APPLICATION_ID);
+
public static final UnboundBooleanFlag HOST_HARDENING = defineFeatureFlag(
"host-hardening", false,
List.of("hakonhall"), "2020-12-02", "2021-02-01",
@@ -265,6 +272,13 @@ public class Flags {
"Takes effect on next internal redeployment",
APPLICATION_ID);
+ public static final UnboundDoubleFlag REINDEXER_WINDOW_SIZE_INCREMENT = defineDoubleFlag(
+ "reindexer-window-size-increment", 0.2,
+ List.of("jonmv"), "2020-12-09", "2021-02-07",
+ "Window size increment for dynamic throttle policy used by reindexer visitor session — more means more aggressive reindexing",
+ "Takes effect on (re)deployment",
+ APPLICATION_ID);
+
public static final UnboundBooleanFlag USE_POWER_OF_TWO_CHOICES_LOAD_BALANCING = defineFeatureFlag(
"use-power-of-two-choices-load-balancing", false,
List.of("tokle"), "2020-12-02", "2021-02-01",
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java
index 5df45bbc1b1..9ac1ca2b4c1 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ApplicationMaintainer.java
@@ -95,9 +95,14 @@ public abstract class ApplicationMaintainer extends NodeRepositoryMaintainer {
}
@Override
- public void close() {
- super.close();
+ public void shutdown() {
+ super.shutdown();
this.deploymentExecutor.shutdownNow();
+ }
+
+ @Override
+ public void awaitShutdown() {
+ super.awaitShutdown();
try {
// Give deployments in progress some time to complete
this.deploymentExecutor.awaitTermination(1, TimeUnit.MINUTES);
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
index ad835901ebf..ac33cc2441c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.maintenance;
import com.google.inject.Inject;
import com.yahoo.component.AbstractComponent;
+import com.yahoo.concurrent.maintenance.Maintainer;
import com.yahoo.config.provision.Deployer;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.HostLivenessTracker;
@@ -18,7 +19,8 @@ import com.yahoo.vespa.orchestrator.Orchestrator;
import com.yahoo.vespa.service.monitor.ServiceMonitor;
import java.time.Duration;
-import java.util.Optional;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* A component which sets up all the node repo maintenance jobs.
@@ -27,28 +29,7 @@ import java.util.Optional;
*/
public class NodeRepositoryMaintenance extends AbstractComponent {
- private final NodeFailer nodeFailer;
- private final NodeHealthTracker nodeHealthTracker;
- private final PeriodicApplicationMaintainer periodicApplicationMaintainer;
- private final OperatorChangeApplicationMaintainer operatorChangeApplicationMaintainer;
- private final ReservationExpirer reservationExpirer;
- private final InactiveExpirer inactiveExpirer;
- private final RetiredExpirer retiredExpirer;
- private final FailedExpirer failedExpirer;
- private final DirtyExpirer dirtyExpirer;
- private final ProvisionedExpirer provisionedExpirer;
- private final NodeRebooter nodeRebooter;
- private final MetricsReporter metricsReporter;
- private final InfrastructureProvisioner infrastructureProvisioner;
- private final Optional<LoadBalancerExpirer> loadBalancerExpirer;
- private final Optional<DynamicProvisioningMaintainer> dynamicProvisioningMaintainer;
- private final SpareCapacityMaintainer spareCapacityMaintainer;
- private final OsUpgradeActivator osUpgradeActivator;
- private final Rebalancer rebalancer;
- private final NodeMetricsDbMaintainer nodeMetricsDbMaintainer;
- private final AutoscalingMaintainer autoscalingMaintainer;
- private final ScalingSuggestionsMaintainer scalingSuggestionsMaintainer;
- private final SwitchRebalancer switchRebalancer;
+ private final List<Maintainer> maintainers = new CopyOnWriteArrayList<>();
@SuppressWarnings("unused")
@Inject
@@ -59,60 +40,45 @@ public class NodeRepositoryMaintenance extends AbstractComponent {
MetricsFetcher metricsFetcher, MetricsDb metricsDb) {
DefaultTimes defaults = new DefaultTimes(zone, deployer);
- nodeFailer = new NodeFailer(deployer, nodeRepository, defaults.failGrace, defaults.nodeFailerInterval, orchestrator, defaults.throttlePolicy, metric);
- nodeHealthTracker = new NodeHealthTracker(hostLivenessTracker, serviceMonitor, nodeRepository, defaults.nodeFailureStatusUpdateInterval, metric);
- periodicApplicationMaintainer = new PeriodicApplicationMaintainer(deployer, metric, nodeRepository,
- defaults.redeployMaintainerInterval, defaults.periodicRedeployInterval, flagSource);
- operatorChangeApplicationMaintainer = new OperatorChangeApplicationMaintainer(deployer, metric, nodeRepository, defaults.operatorChangeRedeployInterval);
- reservationExpirer = new ReservationExpirer(nodeRepository, defaults.reservationExpiry, metric);
- retiredExpirer = new RetiredExpirer(nodeRepository, orchestrator, deployer, metric, defaults.retiredInterval, defaults.retiredExpiry);
- inactiveExpirer = new InactiveExpirer(nodeRepository, defaults.inactiveExpiry, metric);
- failedExpirer = new FailedExpirer(nodeRepository, zone, defaults.failedExpirerInterval, metric);
- dirtyExpirer = new DirtyExpirer(nodeRepository, defaults.dirtyExpiry, metric);
- provisionedExpirer = new ProvisionedExpirer(nodeRepository, defaults.provisionedExpiry, metric);
- nodeRebooter = new NodeRebooter(nodeRepository, flagSource, metric);
- metricsReporter = new MetricsReporter(nodeRepository, metric, orchestrator, serviceMonitor, periodicApplicationMaintainer::pendingDeployments, defaults.metricsInterval);
- infrastructureProvisioner = new InfrastructureProvisioner(nodeRepository, infraDeployer, defaults.infrastructureProvisionInterval, metric);
- loadBalancerExpirer = provisionServiceProvider.getLoadBalancerService(nodeRepository).map(lbService ->
- new LoadBalancerExpirer(nodeRepository, defaults.loadBalancerExpirerInterval, lbService, metric));
- dynamicProvisioningMaintainer = provisionServiceProvider.getHostProvisioner().map(hostProvisioner ->
- new DynamicProvisioningMaintainer(nodeRepository, defaults.dynamicProvisionerInterval, hostProvisioner, flagSource, metric));
- spareCapacityMaintainer = new SpareCapacityMaintainer(deployer, nodeRepository, metric, defaults.spareCapacityMaintenanceInterval);
- osUpgradeActivator = new OsUpgradeActivator(nodeRepository, defaults.osUpgradeActivatorInterval, metric);
- rebalancer = new Rebalancer(deployer, nodeRepository, metric, defaults.rebalancerInterval);
- nodeMetricsDbMaintainer = new NodeMetricsDbMaintainer(nodeRepository, metricsFetcher, metricsDb, defaults.nodeMetricsCollectionInterval, metric);
- autoscalingMaintainer = new AutoscalingMaintainer(nodeRepository, metricsDb, deployer, metric, defaults.autoscalingInterval);
- scalingSuggestionsMaintainer = new ScalingSuggestionsMaintainer(nodeRepository, metricsDb, defaults.scalingSuggestionsInterval, metric);
- switchRebalancer = new SwitchRebalancer(nodeRepository, defaults.switchRebalancerInterval, metric, deployer);
-
+ PeriodicApplicationMaintainer periodicApplicationMaintainer = new PeriodicApplicationMaintainer(deployer, metric, nodeRepository, defaults.redeployMaintainerInterval,
+ defaults.periodicRedeployInterval, flagSource);
+ InfrastructureProvisioner infrastructureProvisioner = new InfrastructureProvisioner(nodeRepository, infraDeployer, defaults.infrastructureProvisionInterval, metric);
+ maintainers.add(periodicApplicationMaintainer);
+ maintainers.add(infrastructureProvisioner);
+
+ maintainers.add(new NodeFailer(deployer, nodeRepository, defaults.failGrace, defaults.nodeFailerInterval, orchestrator, defaults.throttlePolicy, metric));
+ maintainers.add(new NodeHealthTracker(hostLivenessTracker, serviceMonitor, nodeRepository, defaults.nodeFailureStatusUpdateInterval, metric));
+ maintainers.add(new OperatorChangeApplicationMaintainer(deployer, metric, nodeRepository, defaults.operatorChangeRedeployInterval));
+ maintainers.add(new ReservationExpirer(nodeRepository, defaults.reservationExpiry, metric));
+ maintainers.add(new RetiredExpirer(nodeRepository, orchestrator, deployer, metric, defaults.retiredInterval, defaults.retiredExpiry));
+ maintainers.add(new InactiveExpirer(nodeRepository, defaults.inactiveExpiry, metric));
+ maintainers.add(new FailedExpirer(nodeRepository, zone, defaults.failedExpirerInterval, metric));
+ maintainers.add(new DirtyExpirer(nodeRepository, defaults.dirtyExpiry, metric));
+ maintainers.add(new ProvisionedExpirer(nodeRepository, defaults.provisionedExpiry, metric));
+ maintainers.add(new NodeRebooter(nodeRepository, flagSource, metric));
+ maintainers.add(new MetricsReporter(nodeRepository, metric, orchestrator, serviceMonitor, periodicApplicationMaintainer::pendingDeployments, defaults.metricsInterval));
+ maintainers.add(new SpareCapacityMaintainer(deployer, nodeRepository, metric, defaults.spareCapacityMaintenanceInterval));
+ maintainers.add(new OsUpgradeActivator(nodeRepository, defaults.osUpgradeActivatorInterval, metric));
+ maintainers.add(new Rebalancer(deployer, nodeRepository, metric, defaults.rebalancerInterval));
+ maintainers.add(new NodeMetricsDbMaintainer(nodeRepository, metricsFetcher, metricsDb, defaults.nodeMetricsCollectionInterval, metric));
+ maintainers.add(new AutoscalingMaintainer(nodeRepository, metricsDb, deployer, metric, defaults.autoscalingInterval));
+ maintainers.add(new ScalingSuggestionsMaintainer(nodeRepository, metricsDb, defaults.scalingSuggestionsInterval, metric));
+ maintainers.add(new SwitchRebalancer(nodeRepository, defaults.switchRebalancerInterval, metric, deployer));
+
+ provisionServiceProvider.getLoadBalancerService(nodeRepository)
+ .map(lbService -> new LoadBalancerExpirer(nodeRepository, defaults.loadBalancerExpirerInterval, lbService, metric))
+ .ifPresent(maintainers::add);
+ provisionServiceProvider.getHostProvisioner()
+ .map(hostProvisioner -> new DynamicProvisioningMaintainer(nodeRepository, defaults.dynamicProvisionerInterval, hostProvisioner, flagSource, metric))
+ .ifPresent(maintainers::add);
// The DuperModel is filled with infrastructure applications by the infrastructure provisioner, so explicitly run that now
infrastructureProvisioner.maintainButThrowOnException();
}
@Override
public void deconstruct() {
- nodeFailer.close();
- nodeHealthTracker.close();
- periodicApplicationMaintainer.close();
- operatorChangeApplicationMaintainer.close();
- reservationExpirer.close();
- inactiveExpirer.close();
- retiredExpirer.close();
- failedExpirer.close();
- dirtyExpirer.close();
- nodeRebooter.close();
- spareCapacityMaintainer.close();
- provisionedExpirer.close();
- metricsReporter.close();
- infrastructureProvisioner.close();
- loadBalancerExpirer.ifPresent(NodeRepositoryMaintainer::close);
- dynamicProvisioningMaintainer.ifPresent(NodeRepositoryMaintainer::close);
- osUpgradeActivator.close();
- rebalancer.close();
- nodeMetricsDbMaintainer.close();
- autoscalingMaintainer.close();
- scalingSuggestionsMaintainer.close();
- switchRebalancer.close();
+ maintainers.forEach(Maintainer::shutdown);
+ maintainers.forEach(Maintainer::awaitShutdown);
}
private static class DefaultTimes {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java
index 55a183c8ec1..cd188bc017f 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java
@@ -51,7 +51,7 @@ public class PeriodicApplicationMaintainerTest {
@After
public void after() {
- this.fixture.maintainer.close();
+ this.fixture.maintainer.awaitShutdown();
}
@Test(timeout = 60_000)
diff --git a/searchcore/src/apps/vespa-feed-bm/vespa_feed_bm.cpp b/searchcore/src/apps/vespa-feed-bm/vespa_feed_bm.cpp
index 5a5f5cb46d6..170885d1d99 100644
--- a/searchcore/src/apps/vespa-feed-bm/vespa_feed_bm.cpp
+++ b/searchcore/src/apps/vespa-feed-bm/vespa_feed_bm.cpp
@@ -269,6 +269,7 @@ class BMParams {
uint32_t _update_passes;
uint32_t _remove_passes;
uint32_t _rpc_network_threads;
+ uint32_t _rpc_events_before_wakeup;
uint32_t _rpc_targets_per_node;
uint32_t _response_threads;
uint32_t _max_pending;
@@ -292,7 +293,8 @@ public:
_put_passes(2),
_update_passes(1),
_remove_passes(2),
- _rpc_network_threads(1), // Same default as in stor-communicationmanager.def
+ _rpc_network_threads(1), // Same default as previous in stor-communicationmanager.def
+ _rpc_events_before_wakeup(1), // Same default as in stor-communicationmanager.def
_rpc_targets_per_node(1), // Same default as in stor-communicationmanager.def
_response_threads(2), // Same default as in stor-filestor.def
_max_pending(1000),
@@ -318,6 +320,7 @@ public:
uint32_t get_update_passes() const { return _update_passes; }
uint32_t get_remove_passes() const { return _remove_passes; }
uint32_t get_rpc_network_threads() const { return _rpc_network_threads; }
+ uint32_t get_rpc_events_before_wakup() const { return _rpc_events_before_wakeup; }
uint32_t get_rpc_targets_per_node() const { return _rpc_targets_per_node; }
uint32_t get_response_threads() const { return _response_threads; }
bool get_enable_distributor() const { return _enable_distributor; }
@@ -336,6 +339,7 @@ public:
void set_update_passes(uint32_t update_passes_in) { _update_passes = update_passes_in; }
void set_remove_passes(uint32_t remove_passes_in) { _remove_passes = remove_passes_in; }
void set_rpc_network_threads(uint32_t threads_in) { _rpc_network_threads = threads_in; }
+ void set_rpc_events_before_wakeup(uint32_t value) { _rpc_events_before_wakeup = value; }
void set_rpc_targets_per_node(uint32_t targets_in) { _rpc_targets_per_node = targets_in; }
void set_response_threads(uint32_t threads_in) { _response_threads = threads_in; }
void set_enable_distributor(bool value) { _enable_distributor = value; }
@@ -491,6 +495,7 @@ struct MyStorageConfig
make_slobroks_config(slobroks, slobrok_port);
stor_communicationmanager.useDirectStorageapiRpc = true;
stor_communicationmanager.rpc.numNetworkThreads = params.get_rpc_network_threads();
+ stor_communicationmanager.rpc.eventsBeforeWakeup = params.get_rpc_events_before_wakup();
stor_communicationmanager.rpc.numTargetsPerNode = params.get_rpc_targets_per_node();
stor_communicationmanager.mbusport = mbus_port;
stor_communicationmanager.rpcport = rpc_port;
@@ -878,7 +883,8 @@ PersistenceProviderFixture::start_service_layer(const BMParams& params)
_service_layer->getNode().waitUntilInitialized();
LOG(info, "start rpc client shared resources");
config::ConfigUri client_config_uri("bm-rpc-client", _config_context);
- _rpc_client_shared_rpc_resources = std::make_unique<SharedRpcResources>(client_config_uri, _rpc_client_port, 100);
+ _rpc_client_shared_rpc_resources = std::make_unique<SharedRpcResources>
+ (client_config_uri, _rpc_client_port, 100, params.get_rpc_events_before_wakup());
_rpc_client_shared_rpc_resources->start_server_and_register_slobrok("bm-rpc-client");
wait_slobrok("storage/cluster.storage/storage/0/default");
wait_slobrok("storage/cluster.storage/storage/0");
@@ -1369,6 +1375,7 @@ App::usage()
"[--put-passes put-passes]\n"
"[--update-passes update-passes]\n"
"[--remove-passes remove-passes]\n"
+ "[--rpc-events-before-wakeup events]\n"
"[--rpc-network-threads threads]\n"
"[--rpc-targets-per-node targets]\n"
"[--response-threads threads]\n"
@@ -1399,6 +1406,7 @@ App::get_options()
{ "put-passes", 1, nullptr, 0 },
{ "remove-passes", 1, nullptr, 0 },
{ "response-threads", 1, nullptr, 0 },
+ { "rpc-events-before-wakeup", 1, nullptr, 0 },
{ "rpc-network-threads", 1, nullptr, 0 },
{ "rpc-targets-per-node", 1, nullptr, 0 },
{ "skip-get-spi-bucket-info", 0, nullptr, 0 },
@@ -1420,6 +1428,7 @@ App::get_options()
LONGOPT_PUT_PASSES,
LONGOPT_REMOVE_PASSES,
LONGOPT_RESPONSE_THREADS,
+ LONGOPT_RPC_EVENTS_BEFORE_WAKEUP,
LONGOPT_RPC_NETWORK_THREADS,
LONGOPT_RPC_TARGETS_PER_NODE,
LONGOPT_SKIP_GET_SPI_BUCKET_INFO,
@@ -1471,6 +1480,9 @@ App::get_options()
case LONGOPT_RESPONSE_THREADS:
_bm_params.set_response_threads(atoi(opt_argument));
break;
+ case LONGOPT_RPC_EVENTS_BEFORE_WAKEUP:
+ _bm_params.set_rpc_events_before_wakeup(atoi(opt_argument));
+ break;
case LONGOPT_RPC_NETWORK_THREADS:
_bm_params.set_rpc_network_threads(atoi(opt_argument));
break;
diff --git a/searchlib/src/vespa/searchlib/features/onnx_feature.cpp b/searchlib/src/vespa/searchlib/features/onnx_feature.cpp
index c3655e8ed2a..87e5ef2a5c2 100644
--- a/searchlib/src/vespa/searchlib/features/onnx_feature.cpp
+++ b/searchlib/src/vespa/searchlib/features/onnx_feature.cpp
@@ -20,7 +20,7 @@ using search::fef::ParameterList;
using vespalib::Stash;
using vespalib::eval::ValueType;
using vespalib::make_string_short::fmt;
-using vespalib::tensor::Onnx;
+using vespalib::eval::Onnx;
namespace search::features {
diff --git a/searchlib/src/vespa/searchlib/features/onnx_feature.h b/searchlib/src/vespa/searchlib/features/onnx_feature.h
index f5a94cc5345..5a45b26f1f6 100644
--- a/searchlib/src/vespa/searchlib/features/onnx_feature.h
+++ b/searchlib/src/vespa/searchlib/features/onnx_feature.h
@@ -12,7 +12,7 @@ namespace search::features {
**/
class OnnxBlueprint : public fef::Blueprint {
private:
- using Onnx = vespalib::tensor::Onnx;
+ using Onnx = vespalib::eval::Onnx;
std::unique_ptr<Onnx> _model;
Onnx::WireInfo _wire_info;
public:
diff --git a/storage/src/tests/distributor/read_for_write_visitor_operation_test.cpp b/storage/src/tests/distributor/read_for_write_visitor_operation_test.cpp
index e8401914abf..320c55f9998 100644
--- a/storage/src/tests/distributor/read_for_write_visitor_operation_test.cpp
+++ b/storage/src/tests/distributor/read_for_write_visitor_operation_test.cpp
@@ -8,6 +8,8 @@
#include <vespa/storage/distributor/operations/external/visitoroperation.h>
#include <vespa/storage/distributor/distributor.h>
#include <vespa/storage/distributor/distributormetricsset.h>
+#include <vespa/storage/distributor/pendingmessagetracker.h>
+#include <vespa/storageapi/message/bucket.h>
#include <vespa/storageapi/message/persistence.h>
#include <vespa/storageapi/message/visitor.h>
#include <tests/distributor/distributortestutil.h>
@@ -25,6 +27,11 @@ Bucket default_bucket(BucketId id) {
return Bucket(document::FixedBucketSpaces::default_space(), id);
}
+api::StorageMessageAddress make_storage_address(uint16_t node) {
+ static vespalib::string _storage("storage");
+ return {&_storage, lib::NodeType::STORAGE, node};
+}
+
}
struct ReadForWriteVisitorOperationStarterTest : Test, DistributorTestUtil {
@@ -46,6 +53,7 @@ struct ReadForWriteVisitorOperationStarterTest : Test, DistributorTestUtil {
createLinks();
setupDistributor(1, 1, "version:1 distributor:1 storage:1");
_op_owner = std::make_unique<OperationOwner>(_sender, getClock());
+ _sender.setPendingMessageTracker(getDistributor().getPendingMessageTracker());
addNodesToBucketDB(_sub_bucket, "0=1/2/3/t");
}
@@ -81,6 +89,7 @@ struct ReadForWriteVisitorOperationStarterTest : Test, DistributorTestUtil {
TEST_F(ReadForWriteVisitorOperationStarterTest, visitor_that_fails_precondition_checks_is_immediately_failed) {
auto op = create_rfw_op(create_nested_visitor_op(false));
_op_owner->start(op, OperationStarter::Priority(120));
+ ASSERT_EQ("", _sender.getCommands(true));
EXPECT_EQ("CreateVisitorReply(last=BucketId(0x0000000000000000)) "
"ReturnCode(ILLEGAL_PARAMETERS, No buckets in CreateVisitorCommand for visitor 'foo')",
_sender.getLastReply());
@@ -92,6 +101,21 @@ TEST_F(ReadForWriteVisitorOperationStarterTest, visitor_immediately_started_if_n
ASSERT_EQ("Visitor Create => 0", _sender.getCommands(true));
}
+TEST_F(ReadForWriteVisitorOperationStarterTest, visitor_is_bounced_if_merge_pending_for_bucket) {
+ auto op = create_rfw_op(create_nested_visitor_op(true));
+ std::vector<api::MergeBucketCommand::Node> nodes({{0, false}, {1, false}});
+ auto merge = std::make_shared<api::MergeBucketCommand>(default_bucket(_sub_bucket),
+ std::move(nodes),
+ api::Timestamp(123456));
+ merge->setAddress(make_storage_address(0));
+ getDistributor().getPendingMessageTracker().insert(merge);
+ _op_owner->start(op, OperationStarter::Priority(120));
+ ASSERT_EQ("", _sender.getCommands(true));
+ EXPECT_EQ("CreateVisitorReply(last=BucketId(0x0000000000000000)) "
+ "ReturnCode(BUSY, A merge operation is pending for this bucket)",
+ _sender.getLastReply());
+}
+
namespace {
struct ConcurrentMutationFixture {
diff --git a/storage/src/tests/storageserver/rpc/cluster_controller_rpc_api_service_test.cpp b/storage/src/tests/storageserver/rpc/cluster_controller_rpc_api_service_test.cpp
index 8b009e02f28..a39ee819f64 100644
--- a/storage/src/tests/storageserver/rpc/cluster_controller_rpc_api_service_test.cpp
+++ b/storage/src/tests/storageserver/rpc/cluster_controller_rpc_api_service_test.cpp
@@ -57,7 +57,7 @@ struct FixtureBase {
config.getConfig("stor-server").set("node_index", "1");
addSlobrokConfig(config, slobrok);
- shared_rpc_resources = std::make_unique<SharedRpcResources>(config.getConfigId(), 0, 1);
+ shared_rpc_resources = std::make_unique<SharedRpcResources>(config.getConfigId(), 0, 1, 1);
cc_service = std::make_unique<ClusterControllerApiRpcService>(dispatcher, *shared_rpc_resources);
shared_rpc_resources->start_server_and_register_slobrok("my_cool_rpc_test");
}
diff --git a/storage/src/tests/storageserver/rpc/storage_api_rpc_service_test.cpp b/storage/src/tests/storageserver/rpc/storage_api_rpc_service_test.cpp
index d1cdd649787..0b33da39c41 100644
--- a/storage/src/tests/storageserver/rpc/storage_api_rpc_service_test.cpp
+++ b/storage/src/tests/storageserver/rpc/storage_api_rpc_service_test.cpp
@@ -119,7 +119,7 @@ public:
cfg.set("is_distributor", is_distributor ? "true" : "false");
addSlobrokConfig(_config, slobrok);
- _shared_rpc_resources = std::make_unique<SharedRpcResources>(_config.getConfigId(), 0, 1);
+ _shared_rpc_resources = std::make_unique<SharedRpcResources>(_config.getConfigId(), 0, 1, 1);
// TODO make codec provider into interface so we can test decode-failures more easily?
_codec_provider = std::make_unique<MessageCodecProvider>(_doc_type_repo);
}
diff --git a/storage/src/vespa/storage/common/CMakeLists.txt b/storage/src/vespa/storage/common/CMakeLists.txt
index efbd62a45a0..741d97f78ef 100644
--- a/storage/src/vespa/storage/common/CMakeLists.txt
+++ b/storage/src/vespa/storage/common/CMakeLists.txt
@@ -2,7 +2,6 @@
vespa_add_library(storage_common OBJECT
SOURCES
bucketmessages.cpp
- bucketoperationlogger.cpp
content_bucket_space.cpp
content_bucket_space_repo.cpp
distributorcomponent.cpp
diff --git a/storage/src/vespa/storage/common/bucketoperationlogger.cpp b/storage/src/vespa/storage/common/bucketoperationlogger.cpp
deleted file mode 100644
index 905b704409f..00000000000
--- a/storage/src/vespa/storage/common/bucketoperationlogger.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include "bucketoperationlogger.h"
-#include <vespa/storage/bucketdb/storbucketdb.h>
-#include <vespa/storage/bucketdb/bucketcopy.h>
-
-#include <vespa/storageapi/buckets/bucketinfo.h>
-#include <vespa/storageframework/defaultimplementation/clock/realclock.h>
-#include <vespa/vespalib/util/backtrace.h>
-#include <vespa/vespalib/stllike/asciistream.h>
-
-#ifdef ENABLE_BUCKET_OPERATION_LOGGING
-#include <vespa/log/log.h>
-LOG_SETUP(".debuglogger");
-
-namespace storage {
-
-namespace debug {
-
-BucketOperationLogger opLogger;
-
-void
-BucketOperationLogger::log(const document::BucketId& id,
- const vespalib::string& text,
- bool requireLock,
- State::LockUpdate lockUpdate)
-{
- LogEntry entry;
- framework::defaultimplementation::RealClock rclock;
- entry._frameCount = vespalib::getStackTraceFrames(entry._stackFrames, MAX_STACK_FRAMES);
- entry._text = text;
- entry._timestamp = rclock.getTimeInMicros();
- entry._threadId = FastOS_Thread::GetCurrentThreadId() & 0xffff;
- uint32_t lockedByThread = 0;
- bool hasError = false;
-
- {
- std::lock_guard<std:.mutex> guard(_logLock);
- BucketMapType::iterator i = _bucketMap.lower_bound(id);
- if (i != _bucketMap.end() && i->first == id) {
- if (i->second._history.size() >= MAX_ENTRIES) {
- i->second._history.pop_front();
- }
- i->second._history.push_back(entry);
- if (lockUpdate == State::BUCKET_LOCKED) {
- if (i->second._lockedByThread != 0) {
- LOG(warning, "Attempting to acquire lock, but lock "
- "is already held by thread %u", i->second._lockedByThread);
- hasError = true;
- }
- i->second._lockedByThread = entry._threadId;
- }
- lockedByThread = i->second._lockedByThread;
- if (lockUpdate == State::BUCKET_UNLOCKED) {
- if (i->second._lockedByThread == 0) {
- LOG(warning, "Attempting to release lock, but lock "
- "is not held");
- hasError = true;
- }
- i->second._lockedByThread = 0;
- }
- } else {
- State addState;
- addState._lockedByThread = 0;
- addState._history.push_back(entry);
- if (lockUpdate == State::BUCKET_LOCKED) {
- addState._lockedByThread = entry._threadId;
- } else if (lockUpdate == State::BUCKET_UNLOCKED) {
- LOG(warning, "Attempting to release lock, but lock "
- "is not held");
- hasError = true;
- }
- _bucketMap.insert(i, BucketMapType::value_type(id, addState));
- }
- }
-
- if (requireLock && !lockedByThread) {
- LOG(warning, "Operation '%s' requires lock, but lock is "
- "not registered as held", text.c_str());
- hasError = true;
- }
- if (hasError) {
- LOG(warning, "%s", getHistory(id).c_str());
- }
-}
-
-namespace {
-
-// Must hold logger lock
-template <typename LineHandler>
-void
-processHistory(const BucketOperationLogger& opLogger,
- const document::BucketId& id, LineHandler& handler)
-{
- BucketOperationLogger::BucketMapType::const_iterator i(
- opLogger._bucketMap.find(id));
- if (i == opLogger._bucketMap.end()) {
- vespalib::asciistream ss;
- ss << "No history recorded for bucket '"
- << id.toString() << "'";
- handler(ss.str());
- return;
- }
-
- {
- vespalib::asciistream ss;
- ss << "Showing last " << i->second._history.size() << " operations on "
- << "bucket " << id.toString() << " (newest first):";
- handler(ss.str());
- }
- for (BucketOperationLogger::State::LogEntryListType::const_reverse_iterator j(
- i->second._history.rbegin()), end(i->second._history.rend());
- j != end; ++j)
- {
- vespalib::asciistream ss;
- ss << storage::framework::getTimeString(
- j->_timestamp.getTime(),
- storage::framework::DATETIME_WITH_MICROS)
- << " " << j->_threadId << " "
- << j->_text << ". "
- << vespalib::getStackTrace(1, j->_stackFrames, j->_frameCount);
- handler(ss.str());
- }
-}
-
-struct LogWarnAppender
-{
- void operator()(const vespalib::string& line)
- {
- LOG(warning, "%s", line.c_str());
- }
-};
-
-struct LogStringBuilder
-{
- vespalib::asciistream ss;
- void operator()(const vespalib::string& line)
- {
- ss << line << "\n";
- }
-};
-
-}
-
-void
-BucketOperationLogger::dumpHistoryToLog(const document::BucketId& id) const
-{
- LogWarnAppender handler;
- std::lock_guard<std::mutex> guard(_logLock);
- processHistory(*this, id, handler);
-}
-
-vespalib::string
-BucketOperationLogger::getHistory(const document::BucketId& id) const
-{
- LogStringBuilder handler;
- std::lock_guard<std::mutex> lock(_logLock);
- processHistory(*this, id, handler);
- return handler.ss.str();
-}
-
-vespalib::string
-BucketOperationLogger::searchBucketHistories(
- const vespalib::string& sub,
- const vespalib::string& urlPrefix) const
-{
- vespalib::asciistream ss;
- ss << "<ul>\n";
- // This may block for a while... Assuming such searches run when system
- // is otherwise idle.
- std::lock_guard<std::mutex> guard(_logLock);
- for (BucketMapType::const_iterator
- bIt(_bucketMap.begin()), bEnd(_bucketMap.end());
- bIt != bEnd; ++bIt)
- {
- for (State::LogEntryListType::const_iterator
- sIt(bIt->second._history.begin()),
- sEnd(bIt->second._history.end());
- sIt != sEnd; ++sIt)
- {
- if (sIt->_text.find(sub.c_str()) != vespalib::string::npos) {
- ss << "<li><a href=\"" << urlPrefix
- << "0x" << vespalib::hex << bIt->first.getId()
- << vespalib::dec << "\">" << bIt->first.toString()
- << "</a>:\n";
- ss << sIt->_text << "</li>\n";
- }
- }
- }
- ss << "</ul>\n";
- return ss.str();
-}
-
-BucketOperationLogger&
-BucketOperationLogger::getInstance()
-{
- return opLogger;
-}
-
-// Storage node
-void logBucketDbInsert(uint64_t key, const bucketdb::StorageBucketInfo& entry)
-{
- LOG_BUCKET_OPERATION_NO_LOCK(
- document::BucketId(document::BucketId::keyToBucketId(key)),
- vespalib::make_string(
- "bucketdb insert Bucket(crc=%x, docs=%u, size=%u, "
- "metacount=%u, usedfilesize=%u, ready=%s, "
- "active=%s, lastModified=%zu) disk=%u",
- entry.info.getChecksum(),
- entry.info.getDocumentCount(),
- entry.info.getTotalDocumentSize(),
- entry.info.getMetaCount(),
- entry.info.getUsedFileSize(),
- (entry.info.isReady() ? "true" : "false"),
- (entry.info.isActive() ? "true" : "false"),
- entry.info.getLastModified(),
- entry.disk));
-}
-
-void logBucketDbErase(uint64_t key, const TypeTag<bucketdb::StorageBucketInfo>&)
-{
- LOG_BUCKET_OPERATION_NO_LOCK(
- document::BucketId(document::BucketId::keyToBucketId(key)),
- "bucketdb erase");
-}
-
-// Distributor
-void
-checkAllConsistentNodesImpliesTrusted(
- const document::BucketId& bucket,
- const BucketInfo& entry)
-{
- // If all copies are consistent, they should also be trusted
- if (entry.validAndConsistent() && entry.getNodeCount() > 1) {
- for (std::size_t i = 0; i < entry.getNodeCount(); ++i) {
- const BucketCopy& copy = entry.getNodeRef(i);
- if (copy.trusted() == false) {
- LOG(warning, "Bucket DB entry %s for %s is consistent, but "
- "contains non-trusted copy %s", entry.toString().c_str(),
- bucket.toString().c_str(), copy.toString().c_str());
- DUMP_LOGGED_BUCKET_OPERATIONS(bucket);
- }
- }
- }
-}
-
-std::size_t
-firstTrustedNode(const BucketInfo& entry)
-{
- for (std::size_t i = 0; i < entry.getNodeCount(); ++i) {
- const distributor::BucketCopy& copy = entry.getNodeRef(i);
- if (copy.trusted()) {
- return i;
- }
- }
- return std::numeric_limits<std::size_t>::max();
-}
-
-void
-checkNotInSyncImpliesNotTrusted(
- const document::BucketId& bucket,
- const BucketInfo& entry)
-{
- // If there are copies out of sync, different copies should not
- // be set to trusted
- std::size_t trustedNode = firstTrustedNode(entry);
- if (trustedNode != std::numeric_limits<std::size_t>::max()) {
- // Ensure all other trusted copies match the metadata of the
- // first trusted bucket
- const BucketCopy& trustedCopy = entry.getNodeRef(trustedNode);
- for (std::size_t i = 0; i < entry.getNodeCount(); ++i) {
- if (i == trustedNode) {
- continue;
- }
- const BucketCopy& copy = entry.getNodeRef(i);
- const api::BucketInfo& copyInfo = copy.getBucketInfo();
- const api::BucketInfo& trustedInfo = trustedCopy.getBucketInfo();
- if (copy.trusted()
- && ((copyInfo.getChecksum() != trustedInfo.getChecksum())))
- //|| (copyInfo.getTotalDocumentSize() != trustedInfo.getTotalDocumentSize())))
- {
- LOG(warning, "Bucket DB entry %s for %s has trusted node copy "
- "with differing metadata %s", entry.toString().c_str(),
- bucket.toString().c_str(), copy.toString().c_str());
- DUMP_LOGGED_BUCKET_OPERATIONS(bucket);
- }
- }
- }
-}
-
-void
-checkInvalidImpliesNotTrusted(
- const document::BucketId& bucket,
- const BucketInfo& entry)
-{
- for (std::size_t i = 0; i < entry.getNodeCount(); ++i) {
- const BucketCopy& copy = entry.getNodeRef(i);
- if (!copy.valid() && copy.trusted()) {
- LOG(warning, "Bucket DB entry %s for %s has invalid copy %s "
- "marked as trusted", entry.toString().c_str(),
- bucket.toString().c_str(), copy.toString().c_str());
- DUMP_LOGGED_BUCKET_OPERATIONS(bucket);
- }
- }
-}
-
-void
-logBucketDbInsert(uint64_t key, const BucketInfo& entry)
-{
- document::BucketId bucket(document::BucketId::keyToBucketId(key));
- LOG_BUCKET_OPERATION_NO_LOCK(
- bucket, vespalib::make_string(
- "bucketdb insert of %s", entry.toString().c_str()));
- // Do some sanity checking of the inserted entry
- checkAllConsistentNodesImpliesTrusted(bucket, entry);
- checkNotInSyncImpliesNotTrusted(bucket, entry);
- checkInvalidImpliesNotTrusted(bucket, entry);
-}
-
-void
-logBucketDbErase(uint64_t key, const TypeTag<BucketInfo>&)
-{
- document::BucketId bucket(document::BucketId::keyToBucketId(key));
- LOG_BUCKET_OPERATION_NO_LOCK(bucket, "bucketdb erase");
-}
-
-} // namespace debug
-
-} // namespace storage
-
-#endif // ENABLE_BUCKET_OPERATION_LOGGING
diff --git a/storage/src/vespa/storage/common/bucketoperationlogger.h b/storage/src/vespa/storage/common/bucketoperationlogger.h
deleted file mode 100644
index af4b539a4c8..00000000000
--- a/storage/src/vespa/storage/common/bucketoperationlogger.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#pragma once
-
-#include <vespa/vespalib/stllike/string.h>
-#include <vespa/document/bucket/bucketid.h>
-#include <map>
-#include <list>
-#include <mutex>
-
-/**
- * Enable this to log most slotfile operations (such as all mutations) as
- * well as common bucket operations such as splitting, joining and bucket db
- * updates. Each log entry contains the stack frames for the logging callsite,
- * a timestamp, the ID of the thread performing the operation as well as a
- * message. The stack trace is cheaply acquired and does thus not affect runtime
- * performance to a great degree. Expect some overhead from the logging itself
- * since it requires a global mutex around the log state.
- *
- * All relevant bucket/slotfile operations are checked to ensure that the
- * filestor lock is held during the operation and that the thread performing
- * it is the same as the one that acquired the lock.
- *
- * Similarly, code has been added to distributor bucket database and ideal
- * state handling to log these.
- *
- * In the case of an invariant violation (such as a locking bug), the last
- * BUCKET_OPERATION_LOG_ENTRIES log entries will be dumped to the vespalog.
- * Code may also dump the logged history for a bucket by calling
- * DUMP_LOGGED_BUCKET_OPERATIONS(bucketid)
- */
-//#define ENABLE_BUCKET_OPERATION_LOGGING
-#define BUCKET_OPERATION_LOG_ENTRIES 40
-
-#ifdef ENABLE_BUCKET_OPERATION_LOGGING
-#define LOG_BUCKET_OPERATION_NO_LOCK(bucket, string) \
-debug::BucketOperationLogger::getInstance().log( \
- (bucket), (string), false)
-
-#define LOG_BUCKET_OPERATION(bucket, string) \
-debug::BucketOperationLogger::getInstance().log( \
- (bucket), (string), true)
-
-#define LOG_BUCKET_OPERATION_SPECIFY_LOCKED(bucket, string, require_locked) \
-debug::BucketOperationLogger::getInstance().log( \
- (bucket), (string), (require_locked))
-
-#define LOG_BUCKET_OPERATION_SET_LOCK_STATE(bucket, string, require_locked, new_state) \
-debug::BucketOperationLogger::getInstance().log( \
- (bucket), (string), (require_locked), (new_state))
-
-#define DUMP_LOGGED_BUCKET_OPERATIONS(bucket) \
- debug::BucketOperationLogger::getInstance().dumpHistoryToLog(bucket)
-
-namespace storage {
-
-// Debug stuff for tracking the last n operations to buckets
-namespace debug {
-
-struct BucketOperationLogger
-{
- static const std::size_t MAX_ENTRIES = BUCKET_OPERATION_LOG_ENTRIES;
- static const std::size_t MAX_STACK_FRAMES = 25;
-
- struct LogEntry
- {
- void* _stackFrames[MAX_STACK_FRAMES];
- vespalib::string _text;
- framework::MicroSecTime _timestamp;
- int _frameCount;
- int32_t _threadId;
- };
-
- struct State
- {
- typedef std::list<LogEntry> LogEntryListType;
- enum LockUpdate
- {
- NO_UPDATE = 0,
- BUCKET_LOCKED = 1,
- BUCKET_UNLOCKED = 2
- };
- LogEntryListType _history;
- uint32_t _lockedByThread;
- };
-
- typedef std::map<document::BucketId, State> BucketMapType;
-
- std::mutex _logLock;
- BucketMapType _bucketMap;
-
- void log(const document::BucketId& id,
- const vespalib::string& text,
- bool requireLock = true,
- State::LockUpdate update = State::NO_UPDATE);
-
- vespalib::string getHistory(const document::BucketId& id) const;
- void dumpHistoryToLog(const document::BucketId& id) const;
- //void dumpAllBucketHistoriesToFile(const vespalib::string& filename) const;
- /**
- * Search through all bucket history entry descriptions to find substring,
- * creating a itemized list of buckets containing it as well as a preview.
- * @param sub the exact substring to search for.
- * @param urlPrefix the URL used for creating bucket links.
- */
- vespalib::string searchBucketHistories(const vespalib::string& sub,
- const vespalib::string& urlPrefix) const;
- static BucketOperationLogger& getInstance();
-};
-
-}
-
-}
-
-#else
-
-#define LOG_BUCKET_OPERATION_NO_LOCK(bucket, string)
-#define LOG_BUCKET_OPERATION(bucket, string)
-#define LOG_BUCKET_OPERATION_SPECIFY_LOCKED(bucket, string, require_locked)
-#define DUMP_LOGGED_BUCKET_OPERATIONS(bucket)
-#define LOG_BUCKET_OPERATION_SET_LOCK_STATE(bucket, string, require_locked, new_state)
-
-#endif
-
diff --git a/storage/src/vespa/storage/config/stor-communicationmanager.def b/storage/src/vespa/storage/config/stor-communicationmanager.def
index 8f24646367f..d674ee96aa3 100644
--- a/storage/src/vespa/storage/config/stor-communicationmanager.def
+++ b/storage/src/vespa/storage/config/stor-communicationmanager.def
@@ -63,6 +63,9 @@ use_direct_storageapi_rpc bool default=false
## The number of network (FNET) threads used by the shared rpc resource.
rpc.num_network_threads int default=2 restart
+## The number of events in the queue of a network (FNET) thread before it is woken up.
+rpc.events_before_wakeup int default=1 restart
+
## The number of (FNET) RPC targets to use per node in the cluster.
##
## The bucket id associated with a message is used to select the RPC target.
diff --git a/storage/src/vespa/storage/distributor/bucketdbupdater.cpp b/storage/src/vespa/storage/distributor/bucketdbupdater.cpp
index d7fa770ef12..a8c4e7c3544 100644
--- a/storage/src/vespa/storage/distributor/bucketdbupdater.cpp
+++ b/storage/src/vespa/storage/distributor/bucketdbupdater.cpp
@@ -8,7 +8,6 @@
#include "distributormetricsset.h"
#include "simpleclusterinformation.h"
#include <vespa/document/bucket/fixed_bucket_spaces.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/storageapi/message/persistence.h>
#include <vespa/storageapi/message/removelocation.h>
#include <vespa/vespalib/util/xmlstream.h>
diff --git a/storage/src/vespa/storage/distributor/distributorcomponent.cpp b/storage/src/vespa/storage/distributor/distributorcomponent.cpp
index dde5281a15f..86c98cc7b78 100644
--- a/storage/src/vespa/storage/distributor/distributorcomponent.cpp
+++ b/storage/src/vespa/storage/distributor/distributorcomponent.cpp
@@ -4,7 +4,6 @@
#include "distributor_bucket_space.h"
#include "pendingmessagetracker.h"
#include <vespa/document/select/parser.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/vdslib/state/cluster_state_bundle.h>
diff --git a/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.cpp b/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.cpp
index 1e87172e870..5ebf20138a4 100644
--- a/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.cpp
+++ b/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.cpp
@@ -2,6 +2,7 @@
#include "read_for_write_visitor_operation.h"
#include "visitoroperation.h"
+#include <vespa/storage/distributor/distributormessagesender.h>
#include <vespa/storage/distributor/pendingmessagetracker.h>
#include <vespa/storage/distributor/operationowner.h>
#include <cassert>
@@ -40,6 +41,11 @@ void ReadForWriteVisitorOperationStarter::onStart(DistributorMessageSender& send
assert(_visitor_op->has_sent_reply());
return;
}
+ if (bucket_has_pending_merge(*maybe_bucket, sender.getPendingMessageTracker())) {
+ LOG(debug, "A merge is pending for bucket %s, failing visitor", maybe_bucket->toString().c_str());
+ _visitor_op->fail_with_merge_pending(sender);
+ return;
+ }
auto bucket_handle = _operation_sequencer.try_acquire(*maybe_bucket);
if (!bucket_handle.valid()) {
LOG(debug, "An operation is already pending for bucket %s, failing visitor",
@@ -71,4 +77,26 @@ void ReadForWriteVisitorOperationStarter::onReceive(DistributorMessageSender& se
_visitor_op->onReceive(sender, msg);
}
+namespace {
+
+struct MergePendingChecker : PendingMessageTracker::Checker {
+ bool has_pending_merge = false;
+ bool check(uint32_t message_type, [[maybe_unused]] uint16_t node, [[maybe_unused]] uint8_t priority) override {
+ if (message_type == api::MessageType::MERGEBUCKET_ID) {
+ has_pending_merge = true;
+ }
+ return true;
+ }
+};
+
+}
+
+bool ReadForWriteVisitorOperationStarter::bucket_has_pending_merge(const document::Bucket& bucket,
+ const PendingMessageTracker& tracker) const {
+ MergePendingChecker merge_checker;
+ tracker.checkPendingMessages(bucket, merge_checker);
+ return merge_checker.has_pending_merge;
+}
+
+
}
diff --git a/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.h b/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.h
index 06b4f60307e..a6b414e6fb5 100644
--- a/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.h
+++ b/storage/src/vespa/storage/distributor/operations/external/read_for_write_visitor_operation.h
@@ -43,6 +43,8 @@ public:
void onStart(DistributorMessageSender& sender) override;
void onReceive(DistributorMessageSender& sender,
const std::shared_ptr<api::StorageReply> & msg) override;
+private:
+ bool bucket_has_pending_merge(const document::Bucket&, const PendingMessageTracker& tracker) const;
};
}
diff --git a/storage/src/vespa/storage/distributor/operations/external/visitoroperation.cpp b/storage/src/vespa/storage/distributor/operations/external/visitoroperation.cpp
index 3d79aa176d7..5a8adb26cd8 100644
--- a/storage/src/vespa/storage/distributor/operations/external/visitoroperation.cpp
+++ b/storage/src/vespa/storage/distributor/operations/external/visitoroperation.cpp
@@ -887,6 +887,13 @@ VisitorOperation::fail_with_bucket_already_locked(DistributorMessageSender& send
sendReply(api::ReturnCode(api::ReturnCode::BUSY, "This bucket is already locked by another operation"), sender);
}
+void
+VisitorOperation::fail_with_merge_pending(DistributorMessageSender& sender)
+{
+ assert(is_read_for_write());
+ sendReply(api::ReturnCode(api::ReturnCode::BUSY, "A merge operation is pending for this bucket"), sender);
+}
+
std::optional<document::Bucket>
VisitorOperation::first_bucket_to_visit() const
{
diff --git a/storage/src/vespa/storage/distributor/operations/external/visitoroperation.h b/storage/src/vespa/storage/distributor/operations/external/visitoroperation.h
index 4043b0b2c50..e6ad7a042dd 100644
--- a/storage/src/vespa/storage/distributor/operations/external/visitoroperation.h
+++ b/storage/src/vespa/storage/distributor/operations/external/visitoroperation.h
@@ -51,6 +51,7 @@ public:
// Only valid to call if is_read_for_write() == true
void fail_with_bucket_already_locked(DistributorMessageSender& sender);
+ void fail_with_merge_pending(DistributorMessageSender& sender);
[[nodiscard]] bool verify_command_and_expand_buckets(DistributorMessageSender& sender);
diff --git a/storage/src/vespa/storage/distributor/operations/idealstate/splitoperation.cpp b/storage/src/vespa/storage/distributor/operations/idealstate/splitoperation.cpp
index a74dc1c0d65..ea9cb56fae8 100644
--- a/storage/src/vespa/storage/distributor/operations/idealstate/splitoperation.cpp
+++ b/storage/src/vespa/storage/distributor/operations/idealstate/splitoperation.cpp
@@ -2,7 +2,6 @@
#include "splitoperation.h"
#include <vespa/storage/distributor/idealstatemanager.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/storageapi/message/bucketsplitting.h>
#include <vespa/storage/distributor/distributor_bucket_space.h>
#include <climits>
@@ -107,11 +106,6 @@ SplitOperation::onReceive(DistributorMessageSender&, const api::StorageReply::SP
(DatabaseUpdate::CREATE_IF_NONEXISTING
| DatabaseUpdate::RESET_TRUSTED));
- LOG_BUCKET_OPERATION_NO_LOCK(
- sinfo.first, vespalib::make_string(
- "Split from bucket %s: %s",
- getBucketId().toString().c_str(),
- copy.toString().c_str()));
}
} else if (
rep.getResult().getResult() == api::ReturnCode::BUCKET_NOT_FOUND
@@ -137,21 +131,6 @@ SplitOperation::onReceive(DistributorMessageSender&, const api::StorageReply::SP
getBucketId().toString().c_str(),
rep.getResult().toString().c_str());
}
-#ifdef ENABLE_BUCKET_OPERATION_LOGGING
- if (_ok) {
- LOG_BUCKET_OPERATION_NO_LOCK(
- getBucketId(), vespalib::make_string(
- "Split OK on node %d: %s. Finished: %s",
- node, ost.str().c_str(),
- _tracker.finished() ? "yes" : "no"));
- } else {
- LOG_BUCKET_OPERATION_NO_LOCK(
- getBucketId(), vespalib::make_string(
- "Split FAILED on node %d: %s. Finished: %s",
- node, rep.getResult().toString().c_str(),
- _tracker.finished() ? "yes" : "no"));
- }
-#endif
if (_tracker.finished()) {
LOG(debug, "Split done on node %d: %s completed operation",
diff --git a/storage/src/vespa/storage/distributor/pending_bucket_space_db_transition.cpp b/storage/src/vespa/storage/distributor/pending_bucket_space_db_transition.cpp
index 6983e3594af..7eb2e2bf236 100644
--- a/storage/src/vespa/storage/distributor/pending_bucket_space_db_transition.cpp
+++ b/storage/src/vespa/storage/distributor/pending_bucket_space_db_transition.cpp
@@ -4,7 +4,6 @@
#include "clusterinformation.h"
#include "pendingclusterstate.h"
#include "distributor_bucket_space.h"
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <algorithm>
#include <vespa/log/log.h>
diff --git a/storage/src/vespa/storage/distributor/pendingclusterstate.cpp b/storage/src/vespa/storage/distributor/pendingclusterstate.cpp
index 3dda989ff74..d009375a641 100644
--- a/storage/src/vespa/storage/distributor/pendingclusterstate.cpp
+++ b/storage/src/vespa/storage/distributor/pendingclusterstate.cpp
@@ -6,7 +6,6 @@
#include "distributor_bucket_space_repo.h"
#include "distributor_bucket_space.h"
#include <vespa/storageframework/defaultimplementation/clock/realclock.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/storage/common/global_bucket_space_distribution_converter.h>
#include <vespa/document/bucket/fixed_bucket_spaces.h>
#include <vespa/vespalib/util/xmlstream.hpp>
diff --git a/storage/src/vespa/storage/distributor/statecheckers.cpp b/storage/src/vespa/storage/distributor/statecheckers.cpp
index e861adda428..9616ca018b5 100644
--- a/storage/src/vespa/storage/distributor/statecheckers.cpp
+++ b/storage/src/vespa/storage/distributor/statecheckers.cpp
@@ -9,7 +9,6 @@
#include <vespa/storage/distributor/operations/idealstate/setbucketstateoperation.h>
#include <vespa/storage/distributor/operations/idealstate/mergeoperation.h>
#include <vespa/storage/distributor/operations/idealstate/garbagecollectionoperation.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/log/log.h>
diff --git a/storage/src/vespa/storage/persistence/bucketownershipnotifier.cpp b/storage/src/vespa/storage/persistence/bucketownershipnotifier.cpp
index 9a2fe2cd6ce..0ff12ac71bc 100644
--- a/storage/src/vespa/storage/persistence/bucketownershipnotifier.cpp
+++ b/storage/src/vespa/storage/persistence/bucketownershipnotifier.cpp
@@ -2,7 +2,6 @@
#include "bucketownershipnotifier.h"
#include <vespa/storage/common/nodestateupdater.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/storage/common/content_bucket_space_repo.h>
#include <vespa/vdslib/state/cluster_state_bundle.h>
#include <vespa/storageapi/message/bucket.h>
@@ -83,12 +82,6 @@ BucketOwnershipNotifier::logNotification(const document::Bucket &bucket,
currentOwnerIndex,
sourceIndex,
newInfo.toString().c_str());
- LOG_BUCKET_OPERATION_NO_LOCK(
- bucket,
- vespalib::make_string(
- "Sending notify to distributor %u "
- "(ownership changed away from %u)",
- currentOwnerIndex, sourceIndex));
}
void
diff --git a/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp b/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp
index 226df025465..c97965969bc 100644
--- a/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp
+++ b/storage/src/vespa/storage/persistence/filestorage/filestorhandlerimpl.cpp
@@ -9,7 +9,6 @@
#include <vespa/storage/bucketdb/storbucketdb.h>
#include <vespa/storage/common/bucketmessages.h>
#include <vespa/storage/common/statusmessages.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/storage/common/messagebucket.h>
#include <vespa/storage/persistence/asynchandler.h>
#include <vespa/storage/persistence/messages.h>
@@ -480,16 +479,6 @@ FileStorHandlerImpl::remapMessage(api::StorageMessage& msg, const document::Buck
if (idx > -1) {
cmd.remapBucketId(targets[idx]->bucket.getBucketId());
targets[idx]->foundInQueue = true;
-#if defined(ENABLE_BUCKET_OPERATION_LOGGING)
- {
- vespalib::string desc = vespalib::make_string(
- "Remapping %s from %s to %s, targetDisk = %u",
- cmd.toString().c_str(), source.toString().c_str(),
- targets[idx]->bid.toString().c_str(), targetDisk);
- LOG_BUCKET_OPERATION_NO_LOCK(source, desc);
- LOG_BUCKET_OPERATION_NO_LOCK(targets[idx]->bid, desc);
- }
-#endif
newBucket = targets[idx]->bucket;
} else {
document::DocumentId did(getDocId(msg));
@@ -522,16 +511,6 @@ FileStorHandlerImpl::remapMessage(api::StorageMessage& msg, const document::Buck
cmd.toString().c_str(), targets[0]->bucket.getBucketId().toString().c_str());
cmd.remapBucketId(targets[0]->bucket.getBucketId());
newBucket = targets[0]->bucket;
-#ifdef ENABLE_BUCKET_OPERATION_LOGGING
- {
- vespalib::string desc = vespalib::make_string(
- "Remapping %s from %s to %s, targetDisk = %u",
- cmd.toString().c_str(), source.toString().c_str(),
- targets[0]->bid.toString().c_str(), targetDisk);
- LOG_BUCKET_OPERATION_NO_LOCK(source, desc);
- LOG_BUCKET_OPERATION_NO_LOCK(targets[0]->bid, desc);
- }
-#endif
}
} else {
LOG(debug, "Did not remap %s with bucket %s from bucket %s",
diff --git a/storage/src/vespa/storage/persistence/simplemessagehandler.cpp b/storage/src/vespa/storage/persistence/simplemessagehandler.cpp
index 5a5d3dcabca..9c31a1c81bc 100644
--- a/storage/src/vespa/storage/persistence/simplemessagehandler.cpp
+++ b/storage/src/vespa/storage/persistence/simplemessagehandler.cpp
@@ -3,7 +3,6 @@
#include "simplemessagehandler.h"
#include "persistenceutil.h"
#include <vespa/persistence/spi/persistenceprovider.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/storageapi/message/bucket.h>
#include <vespa/document/base/exceptions.h>
#include <vespa/document/fieldset/fieldsetrepo.h>
@@ -105,7 +104,6 @@ SimpleMessageHandler::handleCreateBucket(api::CreateBucketCommand& cmd, MessageT
LOG(debug, "CreateBucket(%s)", cmd.getBucketId().toString().c_str());
if (_env._fileStorHandler.isMerging(cmd.getBucket())) {
LOG(warning, "Bucket %s was merging at create time. Unexpected.", cmd.getBucketId().toString().c_str());
- DUMP_LOGGED_BUCKET_OPERATIONS(cmd.getBucketId());
}
spi::Bucket spiBucket(cmd.getBucket());
_spi.createBucket(spiBucket, tracker->context());
@@ -147,7 +145,6 @@ SimpleMessageHandler::handleDeleteBucket(api::DeleteBucketCommand& cmd, MessageT
{
tracker->setMetric(_env._metrics.deleteBuckets);
LOG(debug, "DeletingBucket(%s)", cmd.getBucketId().toString().c_str());
- LOG_BUCKET_OPERATION(cmd.getBucketId(), "deleteBucket()");
if (_env._fileStorHandler.isMerging(cmd.getBucket())) {
_env._fileStorHandler.clearMergeStatus(cmd.getBucket(),
api::ReturnCode(api::ReturnCode::ABORTED, "Bucket was deleted during the merge"));
diff --git a/storage/src/vespa/storage/storageserver/communicationmanager.cpp b/storage/src/vespa/storage/storageserver/communicationmanager.cpp
index 9d4b7b58a6f..7a3dd16bbd1 100644
--- a/storage/src/vespa/storage/storageserver/communicationmanager.cpp
+++ b/storage/src/vespa/storage/storageserver/communicationmanager.cpp
@@ -429,7 +429,8 @@ void CommunicationManager::configure(std::unique_ptr<CommunicationManagerConfig>
}
_message_codec_provider = std::make_unique<rpc::MessageCodecProvider>(_component.getTypeRepo()->documentTypeRepo);
- _shared_rpc_resources = std::make_unique<rpc::SharedRpcResources>(_configUri, config->rpcport, config->rpc.numNetworkThreads);
+ _shared_rpc_resources = std::make_unique<rpc::SharedRpcResources>(_configUri, config->rpcport,
+ config->rpc.numNetworkThreads, config->rpc.eventsBeforeWakeup);
_cc_rpc_service = std::make_unique<rpc::ClusterControllerApiRpcService>(*this, *_shared_rpc_resources);
rpc::StorageApiRpcService::Params rpc_params;
rpc_params.compression_config = convert_to_rpc_compression_config(*config);
diff --git a/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.cpp b/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.cpp
index 3aa3d21aa7b..4c075f44d35 100644
--- a/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.cpp
+++ b/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.cpp
@@ -62,9 +62,11 @@ public:
SharedRpcResources::SharedRpcResources(const config::ConfigUri& config_uri,
int rpc_server_port,
- size_t rpc_thread_pool_size)
+ size_t rpc_thread_pool_size,
+ size_t rpc_events_before_wakeup)
: _thread_pool(std::make_unique<FastOS_ThreadPool>(1024*60)),
- _transport(std::make_unique<FNET_Transport>(TransportConfig(rpc_thread_pool_size).events_before_wakeup(1))),
+ _transport(std::make_unique<FNET_Transport>(TransportConfig(rpc_thread_pool_size).
+ events_before_wakeup(rpc_events_before_wakeup))),
_orb(std::make_unique<FRT_Supervisor>(_transport.get())),
_slobrok_register(std::make_unique<slobrok::api::RegisterAPI>(*_orb, slobrok::ConfiguratorFactory(config_uri))),
_slobrok_mirror(std::make_unique<slobrok::api::MirrorAPI>(*_orb, slobrok::ConfiguratorFactory(config_uri))),
diff --git a/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.h b/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.h
index 740277218c3..1fdd0f2648b 100644
--- a/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.h
+++ b/storage/src/vespa/storage/storageserver/rpc/shared_rpc_resources.h
@@ -30,7 +30,8 @@ class SharedRpcResources {
int _rpc_server_port;
bool _shutdown;
public:
- SharedRpcResources(const config::ConfigUri& config_uri, int rpc_server_port, size_t rpc_thread_pool_size);
+ SharedRpcResources(const config::ConfigUri& config_uri, int rpc_server_port,
+ size_t rpc_thread_pool_size, size_t rpc_events_before_wakeup);
~SharedRpcResources();
FRT_Supervisor& supervisor() noexcept { return *_orb; }
diff --git a/storage/src/vespa/storage/storageserver/statemanager.cpp b/storage/src/vespa/storage/storageserver/statemanager.cpp
index 653822626ed..395e33a0393 100644
--- a/storage/src/vespa/storage/storageserver/statemanager.cpp
+++ b/storage/src/vespa/storage/storageserver/statemanager.cpp
@@ -6,7 +6,6 @@
#include <vespa/document/bucket/fixed_bucket_spaces.h>
#include <vespa/metrics/jsonwriter.h>
#include <vespa/metrics/metricmanager.h>
-#include <vespa/storage/common/bucketoperationlogger.h>
#include <vespa/storageapi/messageapi/storagemessage.h>
#include <vespa/vdslib/state/cluster_state_bundle.h>
#include <vespa/vespalib/io/fileutil.h>
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 2c123779a1e..2690edc9407 100644
--- a/vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java
+++ b/vespajlib/src/main/java/com/yahoo/concurrent/maintenance/Maintainer.java
@@ -11,6 +11,7 @@ import java.util.Objects;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -21,7 +22,7 @@ import java.util.logging.Logger;
* @author mpolden
* @author jonmv
*/
-public abstract class Maintainer implements Runnable, AutoCloseable {
+public abstract class Maintainer implements Runnable {
protected final Logger log = Logger.getLogger(this.getClass().getName());
@@ -30,6 +31,7 @@ public abstract class Maintainer implements Runnable, AutoCloseable {
private final JobMetrics jobMetrics;
private final Duration interval;
private final ScheduledExecutorService service;
+ private AtomicBoolean shutDown = new AtomicBoolean();
public Maintainer(String name, Duration interval, Instant startedAt, JobControl jobControl, JobMetrics jobMetrics, List<String> clusterHostnames) {
this(name, interval, staggeredDelay(interval, startedAt, HostName.getLocalhost(), clusterHostnames), jobControl, jobMetrics);
@@ -60,10 +62,16 @@ public abstract class Maintainer implements Runnable, AutoCloseable {
log.log(Level.FINE, () -> "Finished " + this.getClass().getSimpleName());
}
- @Override
- public void close() {
+ /** Starts shutdown of this, typically by shutting down executors. {@link #awaitShutdown()} waits for shutdown to complete. */
+ public void shutdown() {
+ if ( ! shutDown.getAndSet(true))
+ service.shutdown();
+ }
+
+ /** Waits for shutdown to complete, calling {@link #shutdown} if this hasn't been done already. */
+ public void awaitShutdown() {
+ shutdown();
var timeout = Duration.ofSeconds(30);
- service.shutdown();
try {
if (!service.awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
log.log(Level.WARNING, "Maintainer " + name() + " failed to shutdown " +
diff --git a/zookeeper-server/zookeeper-server-3.6.2/pom.xml b/zookeeper-server/zookeeper-server-3.6.2/pom.xml
index c479c84ac86..522bc71df97 100644
--- a/zookeeper-server/zookeeper-server-3.6.2/pom.xml
+++ b/zookeeper-server/zookeeper-server-3.6.2/pom.xml
@@ -31,6 +31,21 @@
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
+ <!-- snappy-java and metrics-core are included here
+ to be able to work with ZooKeeper 3.6.2 due to
+ class loading issues -->
+ <dependency>
+ <groupId>io.dropwizard.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ <scope>compile</scope>
+ <version>3.2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.xerial.snappy</groupId>
+ <artifactId>snappy-java</artifactId>
+ <scope>compile</scope>
+ <version>1.1.7</version>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
diff --git a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java
index 0e3f3743c18..e535f627f00 100644
--- a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java
+++ b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/Configurator.java
@@ -90,8 +90,9 @@ public class Configurator {
sb.append("serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory").append("\n");
sb.append("quorumListenOnAllIPs=true").append("\n");
sb.append("standaloneEnabled=false").append("\n");
- sb.append("reconfigEnabled=" + config.dynamicReconfiguration()).append("\n");
+ sb.append("reconfigEnabled=true").append("\n");
sb.append("skipACL=yes").append("\n");
+ sb.append("metricsProvider.className=org.apache.zookeeper.metrics.impl.NullMetricsProvider\n");
ensureThisServerIsRepresented(config.myid(), config.server());
config.server().forEach(server -> addServerToCfg(sb, server, config.clientPort()));
SSLContext sslContext = new SslContextBuilder().build();
diff --git a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java
index 492cfffa1ad..9e9b6a0bbc9 100644
--- a/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java
+++ b/zookeeper-server/zookeeper-server-common/src/main/java/com/yahoo/vespa/zookeeper/ZooKeeperRunner.java
@@ -56,7 +56,19 @@ public class ZooKeeperRunner implements Runnable {
Path path = Paths.get(getDefaults().underVespaHome(zookeeperServerConfig.zooKeeperConfigFile()));
log.log(Level.INFO, "Starting ZooKeeper server with config file " + path.toFile().getAbsolutePath() +
". Trying to establish ZooKeeper quorum (members: " + zookeeperServerHostnames(zookeeperServerConfig) + ")");
- server.start(path);
+ // Note: Hack to make this work in ZooKeeper 3.6, where metrics provider class is
+ // loaded by using Thread.currentThread().getContextClassLoader() which does not work
+ // well in the container
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ try {
+ server.start(path);
+ } catch (Throwable e) {
+ log.log(Level.SEVERE, "Starting ZooKeeper server failed", e);
+ throw new RuntimeException("Starting ZooKeeper server failed", e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(tccl);
+ }
}
}
diff --git a/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java b/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java
index 04a4010edf8..0cdbd68421c 100644
--- a/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java
+++ b/zookeeper-server/zookeeper-server-common/src/test/java/com/yahoo/vespa/zookeeper/ConfiguratorTest.java
@@ -69,7 +69,6 @@ public class ConfiguratorTest {
builder.server(newServer(2, "baz", 345, 543));
builder.myidFile(idFile.getAbsolutePath());
builder.myid(1);
- builder.dynamicReconfiguration(true);
new Configurator(builder.build()).writeConfigToDisk(Optional.empty());
validateConfigFileMultipleHosts(cfgFile);
validateIdFile(idFile, "1\n");
@@ -115,7 +114,6 @@ public class ConfiguratorTest {
builder.server(newServer(0, "foo", 123, 321));
builder.myid(0);
builder.jksKeyStoreFile(jksKeyStoreFile.getAbsolutePath());
- builder.dynamicReconfiguration(true);
return builder;
}
@@ -179,7 +177,8 @@ public class ConfiguratorTest {
"quorumListenOnAllIPs=true\n" +
"standaloneEnabled=false\n" +
"reconfigEnabled=true\n" +
- "skipACL=yes\n";
+ "skipACL=yes\n" +
+ "metricsProvider.className=org.apache.zookeeper.metrics.impl.NullMetricsProvider\n";
}
private String quorumKeyStoreAndTrustStoreConfig(File jksKeyStoreFilePath, File caCertificatesFilePath) {