github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/storage/database_test.go (about)

     1  // Copyright (c) 2016 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package storage
    22  
    23  import (
    24  	stdlibctx "context"
    25  	"errors"
    26  	"fmt"
    27  	"sort"
    28  	"sync"
    29  	"testing"
    30  	"time"
    31  
    32  	"github.com/m3db/m3/src/cluster/shard"
    33  	"github.com/m3db/m3/src/dbnode/client"
    34  	"github.com/m3db/m3/src/dbnode/generated/proto/annotation"
    35  	"github.com/m3db/m3/src/dbnode/namespace"
    36  	"github.com/m3db/m3/src/dbnode/persist/fs/commitlog"
    37  	"github.com/m3db/m3/src/dbnode/retention"
    38  	"github.com/m3db/m3/src/dbnode/sharding"
    39  	"github.com/m3db/m3/src/dbnode/storage/block"
    40  	dberrors "github.com/m3db/m3/src/dbnode/storage/errors"
    41  	"github.com/m3db/m3/src/dbnode/storage/index"
    42  	"github.com/m3db/m3/src/dbnode/storage/index/convert"
    43  	"github.com/m3db/m3/src/dbnode/storage/repair"
    44  	"github.com/m3db/m3/src/dbnode/testdata/prototest"
    45  	"github.com/m3db/m3/src/dbnode/topology"
    46  	"github.com/m3db/m3/src/dbnode/tracepoint"
    47  	"github.com/m3db/m3/src/dbnode/ts"
    48  	"github.com/m3db/m3/src/dbnode/ts/writes"
    49  	xmetrics "github.com/m3db/m3/src/dbnode/x/metrics"
    50  	"github.com/m3db/m3/src/m3ninx/idx"
    51  	xclock "github.com/m3db/m3/src/x/clock"
    52  	"github.com/m3db/m3/src/x/context"
    53  	xerrors "github.com/m3db/m3/src/x/errors"
    54  	"github.com/m3db/m3/src/x/ident"
    55  	"github.com/m3db/m3/src/x/instrument"
    56  	"github.com/m3db/m3/src/x/pool"
    57  	"github.com/m3db/m3/src/x/serialize"
    58  	xtest "github.com/m3db/m3/src/x/test"
    59  	xtime "github.com/m3db/m3/src/x/time"
    60  	xwatch "github.com/m3db/m3/src/x/watch"
    61  
    62  	"github.com/fortytw2/leaktest"
    63  	"github.com/golang/mock/gomock"
    64  	"github.com/opentracing/opentracing-go"
    65  	"github.com/opentracing/opentracing-go/mocktracer"
    66  	"github.com/stretchr/testify/assert"
    67  	"github.com/stretchr/testify/require"
    68  	"github.com/uber-go/tally"
    69  )
    70  
    71  var (
    72  	defaultTestNs1ID         = ident.StringID("testns1")
    73  	defaultTestNs2ID         = ident.StringID("testns2")
    74  	defaultTestRetentionOpts = retention.NewOptions().SetBufferFuture(10 * time.Minute).SetBufferPast(10 * time.Minute).
    75  					SetBlockSize(2 * time.Hour).SetRetentionPeriod(2 * 24 * time.Hour)
    76  	defaultTestNs2RetentionOpts = retention.NewOptions().SetBufferFuture(10 * time.Minute).SetBufferPast(10 * time.Minute).
    77  					SetBlockSize(4 * time.Hour).SetRetentionPeriod(2 * 24 * time.Hour)
    78  	defaultTestNs1Opts = namespace.NewOptions().SetRetentionOptions(defaultTestRetentionOpts)
    79  	defaultTestNs2Opts = namespace.NewOptions().SetRetentionOptions(defaultTestNs2RetentionOpts)
    80  	testSchemaHistory  = prototest.NewSchemaHistory()
    81  	testClientOptions  = client.NewOptions()
    82  )
    83  
    84  type nsMapCh chan namespace.Map
    85  
    86  type mockNsInitializer struct {
    87  	registry *namespace.MockRegistry
    88  	updateCh chan struct{}
    89  }
    90  
    91  func (mi *mockNsInitializer) Init() (namespace.Registry, error) {
    92  	return mi.registry, nil
    93  }
    94  
    95  func newMockNsInitializer(
    96  	t *testing.T,
    97  	ctrl *gomock.Controller,
    98  	nsMapCh nsMapCh,
    99  ) namespace.Initializer {
   100  	updateCh := make(chan struct{}, 10)
   101  	watch := xwatch.NewWatchable()
   102  	go func() {
   103  		for {
   104  			v, ok := <-nsMapCh
   105  			if !ok { // closed channel
   106  				return
   107  			}
   108  
   109  			watch.Update(v)
   110  			updateCh <- struct{}{}
   111  		}
   112  	}()
   113  
   114  	_, w, err := watch.Watch()
   115  	require.NoError(t, err)
   116  
   117  	nsWatch := namespace.NewWatch(w)
   118  	reg := namespace.NewMockRegistry(ctrl)
   119  	reg.EXPECT().Watch().Return(nsWatch, nil).AnyTimes()
   120  
   121  	return &mockNsInitializer{
   122  		registry: reg,
   123  		updateCh: updateCh,
   124  	}
   125  }
   126  
   127  func testNamespaceMap(t *testing.T) namespace.Map {
   128  	md1, err := namespace.NewMetadata(defaultTestNs1ID, defaultTestNs1Opts)
   129  	require.NoError(t, err)
   130  	md2, err := namespace.NewMetadata(defaultTestNs2ID, defaultTestNs2Opts)
   131  	require.NoError(t, err)
   132  	nsMap, err := namespace.NewMap([]namespace.Metadata{md1, md2})
   133  	require.NoError(t, err)
   134  	return nsMap
   135  }
   136  
   137  func testRepairOptions(ctrl *gomock.Controller) repair.Options {
   138  	var (
   139  		origin     = topology.NewHost("some-id", "some-address")
   140  		clientOpts = testClientOptions.(client.AdminOptions).SetOrigin(origin)
   141  		mockClient = client.NewMockAdminClient(ctrl)
   142  	)
   143  	mockClient.EXPECT().Options().Return(clientOpts).AnyTimes()
   144  	return repair.NewOptions().
   145  		SetAdminClients([]client.AdminClient{mockClient}).
   146  		SetRepairCheckInterval(100 * time.Millisecond)
   147  }
   148  
   149  func newMockdatabase(ctrl *gomock.Controller, ns ...databaseNamespace) *Mockdatabase {
   150  	db := NewMockdatabase(ctrl)
   151  	db.EXPECT().Options().Return(DefaultTestOptions()).AnyTimes()
   152  	if len(ns) != 0 {
   153  		db.EXPECT().OwnedNamespaces().Return(ns, nil).AnyTimes()
   154  	}
   155  	return db
   156  }
   157  
   158  type newTestDatabaseOpt struct {
   159  	bs    BootstrapState
   160  	nsMap namespace.Map
   161  	dbOpt Options
   162  }
   163  
   164  func defaultTestDatabase(t *testing.T, ctrl *gomock.Controller, bs BootstrapState) (*db, nsMapCh, xmetrics.TestStatsReporter) {
   165  	return newTestDatabase(t, ctrl, newTestDatabaseOpt{bs: bs, nsMap: testNamespaceMap(t), dbOpt: DefaultTestOptions()})
   166  }
   167  
   168  func newTestDatabase(
   169  	t *testing.T,
   170  	ctrl *gomock.Controller,
   171  	opt newTestDatabaseOpt,
   172  ) (*db, nsMapCh, xmetrics.TestStatsReporter) {
   173  	testReporter := xmetrics.NewTestStatsReporter(xmetrics.NewTestStatsReporterOptions())
   174  	scope, _ := tally.NewRootScope(tally.ScopeOptions{
   175  		Reporter: testReporter,
   176  	}, 100*time.Millisecond)
   177  
   178  	mapCh := make(nsMapCh, 10)
   179  	mapCh <- opt.nsMap
   180  
   181  	opts := opt.dbOpt
   182  	opts = opts.SetInstrumentOptions(
   183  		opts.InstrumentOptions().SetMetricsScope(scope)).
   184  		SetRepairEnabled(false).
   185  		SetRepairOptions(testRepairOptions(ctrl)).
   186  		SetNamespaceInitializer(newMockNsInitializer(t, ctrl, mapCh))
   187  
   188  	shards := sharding.NewShards([]uint32{0, 1}, shard.Available)
   189  	shardSet, err := sharding.NewShardSet(shards, nil)
   190  	require.NoError(t, err)
   191  
   192  	database, err := NewDatabase(shardSet, opts)
   193  	require.NoError(t, err)
   194  	d := database.(*db)
   195  	m := d.mediator.(*mediator)
   196  	bsm := newBootstrapManager(d, m, opts).(*bootstrapManager)
   197  	bsm.state = opt.bs
   198  	m.databaseBootstrapManager = bsm
   199  
   200  	return d, mapCh, testReporter
   201  }
   202  
   203  func dbAddNewMockNamespace(
   204  	ctrl *gomock.Controller,
   205  	d *db,
   206  	id string,
   207  ) *MockdatabaseNamespace {
   208  	ns := ident.StringID(id)
   209  	mockNamespace := NewMockdatabaseNamespace(ctrl)
   210  	mockNamespace.EXPECT().ID().Return(ns).AnyTimes()
   211  	d.namespaces.Set(ns, mockNamespace)
   212  	return mockNamespace
   213  }
   214  
   215  func TestDatabaseOpen(t *testing.T) {
   216  	ctrl := xtest.NewController(t)
   217  	defer ctrl.Finish()
   218  
   219  	d, mapCh, _ := defaultTestDatabase(t, ctrl, BootstrapNotStarted)
   220  	defer func() {
   221  		close(mapCh)
   222  		leaktest.CheckTimeout(t, time.Second)()
   223  	}()
   224  	require.NoError(t, d.Open())
   225  	require.Equal(t, errDatabaseAlreadyOpen, d.Open())
   226  	require.NoError(t, d.Close())
   227  }
   228  
   229  func TestDatabaseClose(t *testing.T) {
   230  	ctrl := xtest.NewController(t)
   231  	defer ctrl.Finish()
   232  
   233  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   234  	defer func() {
   235  		close(mapCh)
   236  		leaktest.CheckTimeout(t, time.Second)()
   237  	}()
   238  	require.NoError(t, d.Open())
   239  	require.NoError(t, d.Close())
   240  	require.Equal(t, errDatabaseAlreadyClosed, d.Close())
   241  }
   242  
   243  func TestDatabaseTerminate(t *testing.T) {
   244  	ctrl := xtest.NewController(t)
   245  	defer ctrl.Finish()
   246  
   247  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   248  	defer func() {
   249  		close(mapCh)
   250  		leaktest.CheckTimeout(t, time.Second)()
   251  	}()
   252  	require.NoError(t, d.Open())
   253  	require.NoError(t, d.Terminate())
   254  	require.Equal(t, errDatabaseAlreadyClosed, d.Close())
   255  }
   256  
   257  func TestDatabaseReadEncodedNamespaceNonExistent(t *testing.T) {
   258  	ctrl := xtest.NewController(t)
   259  	defer ctrl.Finish()
   260  
   261  	ctx := context.NewBackground()
   262  	defer ctx.Close()
   263  
   264  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   265  	defer func() {
   266  		close(mapCh)
   267  	}()
   268  	now := xtime.Now()
   269  	_, err := d.ReadEncoded(ctx, ident.StringID("nonexistent"),
   270  		ident.StringID("foo"), now, now)
   271  	require.True(t, dberrors.IsUnknownNamespaceError(err))
   272  }
   273  
   274  func TestDatabaseReadEncoded(t *testing.T) {
   275  	ctrl := xtest.NewController(t)
   276  	defer ctrl.Finish()
   277  
   278  	ctx := context.NewBackground()
   279  	defer ctx.Close()
   280  
   281  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   282  	defer func() {
   283  		close(mapCh)
   284  	}()
   285  
   286  	ns := ident.StringID("testns1")
   287  	id := ident.StringID("bar")
   288  	end := xtime.Now()
   289  	start := end.Add(-time.Hour)
   290  	mockNamespace := NewMockdatabaseNamespace(ctrl)
   291  	mockNamespace.EXPECT().ReadEncoded(ctx, id, start, end).Return(nil, nil)
   292  	d.namespaces.Set(ns, mockNamespace)
   293  
   294  	res, err := d.ReadEncoded(ctx, ns, id, start, end)
   295  	require.Nil(t, res)
   296  	require.Nil(t, err)
   297  }
   298  
   299  func TestDatabaseFetchBlocksNamespaceNonExistent(t *testing.T) {
   300  	ctrl := xtest.NewController(t)
   301  	defer ctrl.Finish()
   302  
   303  	ctx := context.NewBackground()
   304  	defer ctx.Close()
   305  
   306  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   307  	defer func() {
   308  		close(mapCh)
   309  	}()
   310  
   311  	now := xtime.Now()
   312  	starts := []xtime.UnixNano{now, now.Add(time.Second), now.Add(-time.Second)}
   313  	res, err := d.FetchBlocks(ctx, ident.StringID("non-existent-ns"), 0, ident.StringID("foo"), starts)
   314  	require.Nil(t, res)
   315  	require.True(t, xerrors.IsInvalidParams(err))
   316  }
   317  
   318  func TestDatabaseFetchBlocks(t *testing.T) {
   319  	ctrl := xtest.NewController(t)
   320  	defer ctrl.Finish()
   321  
   322  	ctx := context.NewBackground()
   323  	defer ctx.Close()
   324  
   325  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   326  	defer func() {
   327  		close(mapCh)
   328  	}()
   329  
   330  	ns := ident.StringID("testns1")
   331  	id := ident.StringID("bar")
   332  	shardID := uint32(0)
   333  	now := xtime.Now()
   334  	starts := []xtime.UnixNano{now, now.Add(time.Second), now.Add(-time.Second)}
   335  	expected := []block.FetchBlockResult{block.NewFetchBlockResult(starts[0], nil, nil)}
   336  	mockNamespace := NewMockdatabaseNamespace(ctrl)
   337  	mockNamespace.EXPECT().FetchBlocks(ctx, shardID, id, starts).Return(expected, nil)
   338  	d.namespaces.Set(ns, mockNamespace)
   339  
   340  	res, err := d.FetchBlocks(ctx, ns, shardID, id, starts)
   341  	require.Equal(t, expected, res)
   342  	require.NoError(t, err)
   343  }
   344  
   345  func TestDatabaseNamespaces(t *testing.T) {
   346  	ctrl := xtest.NewController(t)
   347  	defer ctrl.Finish()
   348  
   349  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   350  	defer func() {
   351  		close(mapCh)
   352  	}()
   353  
   354  	dbAddNewMockNamespace(ctrl, d, "testns1")
   355  	dbAddNewMockNamespace(ctrl, d, "testns2")
   356  
   357  	result := d.Namespaces()
   358  	require.Equal(t, 2, len(result))
   359  
   360  	sort.Sort(NamespacesByID(result))
   361  	assert.Equal(t, "testns1", result[0].ID().String())
   362  	assert.Equal(t, "testns2", result[1].ID().String())
   363  }
   364  
   365  func TestOwnedNamespacesErrorIfClosed(t *testing.T) {
   366  	ctrl := xtest.NewController(t)
   367  	defer ctrl.Finish()
   368  
   369  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   370  	defer func() {
   371  		close(mapCh)
   372  	}()
   373  
   374  	require.NoError(t, d.Open())
   375  	require.NoError(t, d.Terminate())
   376  
   377  	_, err := d.OwnedNamespaces()
   378  	require.Equal(t, errDatabaseIsClosed, err)
   379  }
   380  
   381  func TestDatabaseAssignShardSet(t *testing.T) {
   382  	ctrl := xtest.NewController(t)
   383  	defer ctrl.Finish()
   384  
   385  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   386  	defer func() {
   387  		close(mapCh)
   388  	}()
   389  
   390  	var ns []*MockdatabaseNamespace
   391  	ns = append(ns, dbAddNewMockNamespace(ctrl, d, "testns1"))
   392  	ns = append(ns, dbAddNewMockNamespace(ctrl, d, "testns2"))
   393  
   394  	shards := append(sharding.NewShards([]uint32{0, 1}, shard.Available),
   395  		sharding.NewShards([]uint32{2}, shard.Initializing)...)
   396  	shardSet, err := sharding.NewShardSet(shards, nil)
   397  	require.NoError(t, err)
   398  
   399  	var wg sync.WaitGroup
   400  	wg.Add(len(ns))
   401  	for _, n := range ns {
   402  		n.EXPECT().AssignShardSet(shardSet).Do(func(_ sharding.ShardSet) {
   403  			wg.Done()
   404  		})
   405  	}
   406  
   407  	t1 := d.lastReceivedNewShards
   408  	d.AssignShardSet(shardSet)
   409  	require.True(t, d.lastReceivedNewShards.After(t1))
   410  
   411  	wg.Wait()
   412  	assertFileOpsEnabled(t, d)
   413  }
   414  
   415  func TestDatabaseAssignShardSetEnqueueBootstrapWhenMediatorClosed(t *testing.T) {
   416  	ctrl := xtest.NewController(t)
   417  	defer ctrl.Finish()
   418  
   419  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   420  	defer func() {
   421  		close(mapCh)
   422  	}()
   423  
   424  	mockMediator := NewMockdatabaseMediator(ctrl)
   425  	mockMediator.EXPECT().IsOpen().Return(false)
   426  	mockMediator.EXPECT().BootstrapEnqueue(gomock.Any())
   427  	d.mediator = mockMediator
   428  	d.bootstraps = 1
   429  
   430  	var ns []*MockdatabaseNamespace
   431  	ns = append(ns,
   432  		dbAddNewMockNamespace(ctrl, d, "testns1"),
   433  		dbAddNewMockNamespace(ctrl, d, "testns2"))
   434  
   435  	shards := append(sharding.NewShards([]uint32{0, 1}, shard.Available),
   436  		sharding.NewShards([]uint32{2}, shard.Initializing)...)
   437  	shardSet, err := sharding.NewShardSet(shards, nil)
   438  	require.NoError(t, err)
   439  
   440  	var wg sync.WaitGroup
   441  	wg.Add(len(ns))
   442  	for _, n := range ns {
   443  		n.EXPECT().AssignShardSet(shardSet).Do(func(_ sharding.ShardSet) {
   444  			wg.Done()
   445  		})
   446  	}
   447  
   448  	t1 := d.lastReceivedNewShards
   449  	d.AssignShardSet(shardSet)
   450  	require.True(t, d.lastReceivedNewShards.After(t1))
   451  
   452  	wg.Wait()
   453  }
   454  
   455  func TestDatabaseAssignShardSetBehaviorNoNewShards(t *testing.T) {
   456  	ctrl := xtest.NewController(t)
   457  	defer ctrl.Finish()
   458  
   459  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   460  	defer func() {
   461  		close(mapCh)
   462  	}()
   463  
   464  	t1 := d.lastReceivedNewShards
   465  	d.AssignShardSet(d.shardSet)
   466  	// Ensure that lastReceivedNewShards is not updated if no new shards are assigned.
   467  	require.True(t, d.lastReceivedNewShards.Equal(t1))
   468  }
   469  
   470  func TestDatabaseBootstrappedAssignShardSet(t *testing.T) {
   471  	ctrl := xtest.NewController(t)
   472  	defer ctrl.Finish()
   473  
   474  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   475  	defer func() {
   476  		close(mapCh)
   477  	}()
   478  
   479  	ns := dbAddNewMockNamespace(ctrl, d, "testns")
   480  
   481  	mediator := NewMockdatabaseMediator(ctrl)
   482  	mediator.EXPECT().IsOpen().Return(true).AnyTimes()
   483  	mediator.EXPECT().DisableFileOpsAndWait().AnyTimes()
   484  	mediator.EXPECT().EnableFileOps().AnyTimes()
   485  	mediator.EXPECT().Bootstrap().DoAndReturn(func() (BootstrapResult, error) {
   486  		return BootstrapResult{}, nil
   487  	})
   488  	d.mediator = mediator
   489  
   490  	assert.NoError(t, d.Bootstrap())
   491  
   492  	shards := append(sharding.NewShards([]uint32{0, 1}, shard.Available),
   493  		sharding.NewShards([]uint32{2}, shard.Initializing)...)
   494  	shardSet, err := sharding.NewShardSet(shards, nil)
   495  	require.NoError(t, err)
   496  
   497  	ns.EXPECT().AssignShardSet(shardSet)
   498  
   499  	var wg sync.WaitGroup
   500  	wg.Add(1)
   501  	mediator.EXPECT().
   502  		BootstrapEnqueue(gomock.Any()).
   503  		Do(func(_ BootstrapEnqueueOptions) {
   504  			wg.Done()
   505  		})
   506  
   507  	d.AssignShardSet(shardSet)
   508  
   509  	wg.Wait()
   510  }
   511  
   512  func TestDatabaseAssignShardSetDuringBootstrap(t *testing.T) {
   513  	ctrl := xtest.NewController(t)
   514  	defer ctrl.Finish()
   515  
   516  	var wgBootstrap, wgAssignShards sync.WaitGroup
   517  	wgBootstrap.Add(3)
   518  	wgAssignShards.Add(1)
   519  
   520  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   521  	defer func() {
   522  		close(mapCh)
   523  	}()
   524  
   525  	ns := dbAddNewMockNamespace(ctrl, d, "testns")
   526  
   527  	newShards := append(sharding.NewShards([]uint32{0}, shard.Available),
   528  		shard.NewShard(1).SetState(shard.Leaving),
   529  		shard.NewShard(2).SetState(shard.Initializing))
   530  
   531  	newShardSet, err := sharding.NewShardSet(newShards, nil)
   532  	require.NoError(t, err)
   533  
   534  	ns.EXPECT().AssignShardSet(newShardSet)
   535  
   536  	mediator := NewMockdatabaseMediator(ctrl)
   537  	mediator.EXPECT().IsOpen().Return(true).AnyTimes()
   538  	mediator.EXPECT().DisableFileOpsAndWait().AnyTimes()
   539  	mediator.EXPECT().EnableFileOps().AnyTimes()
   540  	mediator.EXPECT().
   541  		BootstrapEnqueue(gomock.Any()).
   542  		Do(func(_ BootstrapEnqueueOptions) {
   543  			wgBootstrap.Done()
   544  		})
   545  	mediator.EXPECT().Bootstrap().DoAndReturn(func() (BootstrapResult, error) {
   546  		go func() {
   547  			// make sure bootstrap not finished before assigning new shards.
   548  			wgAssignShards.Done()
   549  			d.AssignShardSet(newShardSet)
   550  			wgBootstrap.Done()
   551  		}()
   552  		wgAssignShards.Wait()
   553  		time.Sleep(time.Second)
   554  		// AssignShardSet should wait on lock and not update new shardset yet.
   555  		require.NotEqual(t, newShardSet, d.shardSet)
   556  		return BootstrapResult{}, nil
   557  	})
   558  	d.mediator = mediator
   559  
   560  	go func() {
   561  		require.NoError(t, d.Bootstrap())
   562  		wgBootstrap.Done()
   563  	}()
   564  	wgBootstrap.Wait()
   565  	require.Equal(t, newShardSet, d.shardSet)
   566  }
   567  
   568  func TestDatabaseUpdateOwnedNamespacesDuringBootstrap(t *testing.T) {
   569  	ctrl := xtest.NewController(t)
   570  	defer ctrl.Finish()
   571  
   572  	var wgBootstrap, wgUpdateNs sync.WaitGroup
   573  	wgBootstrap.Add(3)
   574  	wgUpdateNs.Add(1)
   575  
   576  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   577  	defer func() {
   578  		close(mapCh)
   579  	}()
   580  
   581  	// check initial namespaces
   582  	require.Len(t, d.Namespaces(), 2)
   583  
   584  	md1, err := namespace.NewMetadata(defaultTestNs1ID, defaultTestNs1Opts)
   585  	require.NoError(t, err)
   586  	md2, err := namespace.NewMetadata(defaultTestNs2ID, defaultTestNs2Opts)
   587  	require.NoError(t, err)
   588  	md3, err := namespace.NewMetadata(ident.StringID("ns3"), defaultTestNs2Opts)
   589  	require.NoError(t, err)
   590  	nsMap, err := namespace.NewMap([]namespace.Metadata{md1, md2, md3})
   591  	require.NoError(t, err)
   592  
   593  	mediator := NewMockdatabaseMediator(ctrl)
   594  	mediator.EXPECT().IsOpen().Return(true).AnyTimes()
   595  	mediator.EXPECT().DisableFileOpsAndWait().AnyTimes()
   596  	mediator.EXPECT().EnableFileOps().AnyTimes()
   597  	mediator.EXPECT().
   598  		BootstrapEnqueue(gomock.Any()).
   599  		Do(func(_ BootstrapEnqueueOptions) {
   600  			wgBootstrap.Done()
   601  		})
   602  	mediator.EXPECT().Bootstrap().DoAndReturn(func() (BootstrapResult, error) {
   603  		go func() {
   604  			// make sure bootstrap not finished before updating namespaces.
   605  			wgUpdateNs.Done()
   606  			require.NoError(t, d.UpdateOwnedNamespaces(nsMap))
   607  			wgBootstrap.Done()
   608  		}()
   609  		wgUpdateNs.Wait()
   610  		time.Sleep(time.Second)
   611  		// UpdateOwnedNamespaces should wait on lock and not update namespaces yet.
   612  		require.Len(t, d.Namespaces(), 2)
   613  		return BootstrapResult{}, nil
   614  	})
   615  	d.mediator = mediator
   616  
   617  	go func() {
   618  		require.NoError(t, d.Bootstrap())
   619  		wgBootstrap.Done()
   620  	}()
   621  	wgBootstrap.Wait()
   622  	require.Len(t, d.Namespaces(), 3)
   623  }
   624  
   625  func TestDatabaseRemoveNamespace(t *testing.T) {
   626  	ctrl := xtest.NewController(t)
   627  	defer ctrl.Finish()
   628  
   629  	d, mapCh, testReporter := defaultTestDatabase(t, ctrl, Bootstrapped)
   630  	require.NoError(t, d.Open())
   631  	defer func() {
   632  		close(mapCh)
   633  		require.NoError(t, d.Close())
   634  		leaktest.CheckTimeout(t, time.Second)()
   635  	}()
   636  
   637  	// retrieve the update channel to track propatation
   638  	updateCh := d.opts.NamespaceInitializer().(*mockNsInitializer).updateCh
   639  
   640  	// check initial namespaces
   641  	nses := d.Namespaces()
   642  	require.Len(t, nses, 2)
   643  
   644  	// construct new namespace Map
   645  	md1, err := namespace.NewMetadata(defaultTestNs1ID, defaultTestNs1Opts)
   646  	require.NoError(t, err)
   647  	nsMap, err := namespace.NewMap([]namespace.Metadata{md1})
   648  	require.NoError(t, err)
   649  
   650  	// update the database watch with new Map
   651  	mapCh <- nsMap
   652  
   653  	// wait till the update has propagated
   654  	<-updateCh
   655  	<-updateCh
   656  
   657  	// the updateCh gets are in-sufficient to determine the update has been applied
   658  	// to the database, they only measure if the watch itself has been updated. It
   659  	// can take a few ms until the DB finds those values.
   660  	require.True(t, xclock.WaitUntil(func() bool {
   661  		counter, ok := testReporter.Counters()["database.namespace-watch.updates"]
   662  		return ok && counter == 1
   663  	}, 2*time.Second))
   664  	require.True(t, xclock.WaitUntil(func() bool {
   665  		return len(d.Namespaces()) == 2
   666  	}, 2*time.Second))
   667  }
   668  
   669  func TestDatabaseAddNamespace(t *testing.T) {
   670  	ctrl := xtest.NewController(t)
   671  	defer ctrl.Finish()
   672  
   673  	d, mapCh, testReporter := defaultTestDatabase(t, ctrl, Bootstrapped)
   674  	require.NoError(t, d.Open())
   675  	defer func() {
   676  		close(mapCh)
   677  		require.NoError(t, d.Close())
   678  		leaktest.CheckTimeout(t, time.Second)()
   679  	}()
   680  
   681  	// retrieve the update channel to track propatation
   682  	updateCh := d.opts.NamespaceInitializer().(*mockNsInitializer).updateCh
   683  
   684  	// check initial namespaces
   685  	nses := d.Namespaces()
   686  	require.Len(t, nses, 2)
   687  
   688  	md1, md2, _, nsMap := addNamespace(t, "and1")
   689  
   690  	// update the database watch with new Map
   691  	mapCh <- nsMap
   692  
   693  	// wait till the update has propagated
   694  	<-updateCh
   695  	<-updateCh
   696  
   697  	// the updateCh gets are in-sufficient to determine the update has been applied
   698  	// to the database, they only measure if the watch itself has been updated. It
   699  	// can take a few ms until the DB finds those values.
   700  	require.True(t, xclock.WaitUntil(func() bool {
   701  		counter, ok := testReporter.Counters()["database.namespace-watch.updates"]
   702  		return ok && counter == 1
   703  	}, 2*time.Second))
   704  	require.True(t, xclock.WaitUntil(func() bool {
   705  		return len(d.Namespaces()) == 3
   706  	}, 2*time.Second))
   707  
   708  	// ensure the expected namespaces exist
   709  	nses = d.Namespaces()
   710  	require.Len(t, nses, 3)
   711  	ns1, ok := d.Namespace(defaultTestNs1ID)
   712  	require.True(t, ok)
   713  	require.Equal(t, md1.Options(), ns1.Options())
   714  	ns2, ok := d.Namespace(defaultTestNs2ID)
   715  	require.True(t, ok)
   716  	require.Equal(t, md2.Options(), ns2.Options())
   717  	ns3, ok := d.Namespace(ident.StringID("and1"))
   718  	require.True(t, ok)
   719  	require.Equal(t, md1.Options(), ns3.Options())
   720  	assertFileOpsEnabled(t, d)
   721  }
   722  
   723  type testNamespaceHooks struct {
   724  	sync.Mutex
   725  	adds int
   726  }
   727  
   728  func (th *testNamespaceHooks) addCount() int {
   729  	th.Lock()
   730  	defer th.Unlock()
   731  	return th.adds
   732  }
   733  
   734  func (th *testNamespaceHooks) OnCreatedNamespace(Namespace, GetNamespaceFn) error {
   735  	th.Lock()
   736  	defer th.Unlock()
   737  	th.adds++
   738  	return nil
   739  }
   740  
   741  func TestDatabaseAddNamespaceBootstrapEnqueue(t *testing.T) {
   742  	ctrl := xtest.NewController(t)
   743  	defer ctrl.Finish()
   744  
   745  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   746  	require.NoError(t, d.Open())
   747  	defer func() {
   748  		close(mapCh)
   749  		require.NoError(t, d.Close())
   750  		leaktest.CheckTimeout(t, time.Second)()
   751  	}()
   752  
   753  	// retrieve the update channel to track propatation
   754  	updateCh := d.opts.NamespaceInitializer().(*mockNsInitializer).updateCh
   755  
   756  	nsHooks := &testNamespaceHooks{}
   757  	d.opts = d.opts.SetNamespaceHooks(nsHooks)
   758  	d.bootstraps++
   759  
   760  	// check initial namespaces
   761  	nses := d.Namespaces()
   762  	require.Len(t, nses, 2)
   763  
   764  	_, _, md3, nsMap := addNamespace(t, "nsNew")
   765  
   766  	// update the database watch with new Map
   767  	mapCh <- nsMap
   768  
   769  	// wait till the update has propagated
   770  	<-updateCh
   771  	<-updateCh
   772  
   773  	// Because ns update will be enqueued and performed later, we need to wait for more time in theory.
   774  	// Usually this update should complete in a few seconds.
   775  	require.True(t, xclock.WaitUntil(func() bool {
   776  		return nsHooks.addCount() == 1
   777  	}, 1*time.Minute))
   778  	require.True(t, xclock.WaitUntil(func() bool {
   779  		return len(d.Namespaces()) == 3
   780  	}, 2*time.Second))
   781  
   782  	// ensure the expected namespaces exist
   783  	nses = d.Namespaces()
   784  	require.Len(t, nses, 3)
   785  	ns3, ok := d.Namespace(ident.StringID("nsNew"))
   786  	require.True(t, ok)
   787  	require.Equal(t, md3.Options(), ns3.Options())
   788  	assertFileOpsEnabled(t, d)
   789  }
   790  
   791  type errorNamespaceHooks struct{}
   792  
   793  func (th *errorNamespaceHooks) OnCreatedNamespace(Namespace, GetNamespaceFn) error {
   794  	return errors.New("failed to create namespace")
   795  }
   796  
   797  func TestDatabaseAddNamespaceErrorAfterWaitForFileOps(t *testing.T) {
   798  	ctrl := xtest.NewController(t)
   799  	defer ctrl.Finish()
   800  
   801  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   802  	require.NoError(t, d.Open())
   803  	defer func() {
   804  		close(mapCh)
   805  		require.NoError(t, d.Close())
   806  		leaktest.CheckTimeout(t, time.Second)()
   807  	}()
   808  
   809  	nsHooks := &errorNamespaceHooks{}
   810  	d.opts = d.opts.SetNamespaceHooks(nsHooks)
   811  
   812  	_, _, _, nsMap := addNamespace(t, "testns3")
   813  	d.bootstraps = 1
   814  
   815  	require.Error(t, d.UpdateOwnedNamespaces(nsMap))
   816  	assertFileOpsEnabled(t, d)
   817  }
   818  
   819  func TestDatabaseAddNamespaceBootstrapEnqueueMediatorClosed(t *testing.T) {
   820  	ctrl := xtest.NewController(t)
   821  	defer ctrl.Finish()
   822  
   823  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   824  	require.NoError(t, d.Open())
   825  	mediator := d.mediator
   826  	defer func() {
   827  		close(mapCh)
   828  		d.mediator = mediator
   829  		require.NoError(t, d.Close())
   830  		leaktest.CheckTimeout(t, time.Second)()
   831  	}()
   832  
   833  	// retrieve the update channel to track propatation
   834  	updateCh := d.opts.NamespaceInitializer().(*mockNsInitializer).updateCh
   835  
   836  	nsHooks := &testNamespaceHooks{}
   837  	d.opts = d.opts.SetNamespaceHooks(nsHooks)
   838  	mockMediator := NewMockdatabaseMediator(ctrl)
   839  	mockMediator.EXPECT().IsOpen().Return(false).AnyTimes()
   840  	mockMediator.EXPECT().BootstrapEnqueue(gomock.Any())
   841  	d.mediator = mockMediator
   842  
   843  	// check initial namespaces
   844  	nses := d.Namespaces()
   845  	require.Len(t, nses, 2)
   846  
   847  	_, _, md3, nsMap := addNamespace(t, "testns3")
   848  	d.bootstraps = 1
   849  	// update the database watch with new Map
   850  	mapCh <- nsMap
   851  
   852  	// wait till the update has propagated
   853  	<-updateCh
   854  	<-updateCh
   855  
   856  	// Because ns update will be enqueued and performed later, we need to wait for more time in theory.
   857  	// Usually this update should complete in a few seconds.
   858  	require.True(t, xclock.WaitUntil(func() bool {
   859  		return nsHooks.addCount() == 1
   860  	}, time.Minute))
   861  	require.True(t, xclock.WaitUntil(func() bool {
   862  		return len(d.Namespaces()) == 3
   863  	}, 2*time.Second))
   864  
   865  	// ensure the expected namespaces exist
   866  	nses = d.Namespaces()
   867  	require.Len(t, nses, 3)
   868  	ns3, ok := d.Namespace(ident.StringID("testns3"))
   869  	require.True(t, ok)
   870  	require.Equal(t, md3.Options(), ns3.Options())
   871  }
   872  
   873  func addNamespace(
   874  	t *testing.T,
   875  	ns string,
   876  ) (namespace.Metadata, namespace.Metadata, namespace.Metadata, namespace.Map) {
   877  	// construct new namespace Map
   878  	md1, err := namespace.NewMetadata(defaultTestNs1ID, defaultTestNs1Opts)
   879  	require.NoError(t, err)
   880  	md2, err := namespace.NewMetadata(defaultTestNs2ID, defaultTestNs2Opts)
   881  	require.NoError(t, err)
   882  	md3, err := namespace.NewMetadata(ident.StringID(ns), defaultTestNs1Opts)
   883  	require.NoError(t, err)
   884  	nsMap, err := namespace.NewMap([]namespace.Metadata{md1, md2, md3})
   885  	require.NoError(t, err)
   886  	return md1, md2, md3, nsMap
   887  }
   888  
   889  func TestDatabaseUpdateNamespace(t *testing.T) {
   890  	ctrl := xtest.NewController(t)
   891  	defer ctrl.Finish()
   892  
   893  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
   894  	require.NoError(t, d.Open())
   895  	defer func() {
   896  		close(mapCh)
   897  		require.NoError(t, d.Close())
   898  		leaktest.CheckTimeout(t, time.Second)()
   899  	}()
   900  
   901  	// retrieve the update channel to track propatation
   902  	updateCh := d.opts.NamespaceInitializer().(*mockNsInitializer).updateCh
   903  
   904  	// check initial namespaces
   905  	nses := d.Namespaces()
   906  	require.Len(t, nses, 2)
   907  
   908  	// construct new namespace Map
   909  	ropts := defaultTestNs1Opts.RetentionOptions().SetRetentionPeriod(2000 * time.Hour)
   910  	md1, err := namespace.NewMetadata(defaultTestNs1ID, defaultTestNs1Opts.SetRetentionOptions(ropts))
   911  	require.NoError(t, err)
   912  	md2, err := namespace.NewMetadata(defaultTestNs2ID, defaultTestNs2Opts)
   913  	require.NoError(t, err)
   914  	nsMap, err := namespace.NewMap([]namespace.Metadata{md1, md2})
   915  	require.NoError(t, err)
   916  
   917  	// update the database watch with new Map
   918  	mapCh <- nsMap
   919  
   920  	// wait till the update has propagated
   921  	<-updateCh
   922  	<-updateCh
   923  	time.Sleep(10 * time.Millisecond)
   924  
   925  	// ensure the namespaces have old properties
   926  	nses = d.Namespaces()
   927  	require.Len(t, nses, 2)
   928  	ns1, ok := d.Namespace(defaultTestNs1ID)
   929  	require.True(t, ok)
   930  	require.Equal(t, defaultTestNs1Opts, ns1.Options())
   931  	ns2, ok := d.Namespace(defaultTestNs2ID)
   932  	require.True(t, ok)
   933  	require.Equal(t, defaultTestNs2Opts, ns2.Options())
   934  
   935  	// Ensure schema is not set and no error
   936  	require.Nil(t, ns1.Schema())
   937  	require.Nil(t, ns2.Schema())
   938  	schema, err := d.Options().SchemaRegistry().GetLatestSchema(defaultTestNs2ID)
   939  	require.NoError(t, err)
   940  	require.Nil(t, schema)
   941  }
   942  
   943  func TestDatabaseCreateSchemaNotSet(t *testing.T) {
   944  	protoTestDatabaseOptions := DefaultTestOptions().
   945  		SetSchemaRegistry(namespace.NewSchemaRegistry(true, nil))
   946  
   947  	ctrl := xtest.NewController(t)
   948  	defer ctrl.Finish()
   949  
   950  	// Start the database with two namespaces, one miss configured (missing schema).
   951  	nsID1 := ident.StringID("testns1")
   952  	md1, err := namespace.NewMetadata(nsID1, defaultTestNs1Opts.SetSchemaHistory(testSchemaHistory))
   953  	require.NoError(t, err)
   954  	nsID2 := ident.StringID("testns2")
   955  	md2, err := namespace.NewMetadata(nsID2, defaultTestNs1Opts)
   956  	require.NoError(t, err)
   957  	nsMap, err := namespace.NewMap([]namespace.Metadata{md1, md2})
   958  	require.NoError(t, err)
   959  
   960  	d, mapCh, _ := newTestDatabase(t, ctrl, newTestDatabaseOpt{bs: Bootstrapped, nsMap: nsMap, dbOpt: protoTestDatabaseOptions})
   961  	require.NoError(t, d.Open())
   962  	defer func() {
   963  		close(mapCh)
   964  		require.NoError(t, d.Close())
   965  		leaktest.CheckTimeout(t, time.Second)()
   966  	}()
   967  
   968  	// check initial namespaces
   969  	nses := d.Namespaces()
   970  	require.Len(t, nses, 1)
   971  
   972  	_, ok := d.Namespace(nsID1)
   973  	require.True(t, ok)
   974  	_, ok = d.Namespace(nsID2)
   975  	require.False(t, ok)
   976  }
   977  
   978  func TestDatabaseUpdateNamespaceSchemaNotSet(t *testing.T) {
   979  	protoTestDatabaseOptions := DefaultTestOptions().
   980  		SetSchemaRegistry(namespace.NewSchemaRegistry(true, nil))
   981  
   982  	ctrl := xtest.NewController(t)
   983  	defer ctrl.Finish()
   984  
   985  	// Start db with no namespaces.
   986  	d, mapCh, _ := newTestDatabase(t, ctrl, newTestDatabaseOpt{bs: Bootstrapped, dbOpt: protoTestDatabaseOptions})
   987  	require.NoError(t, d.Open())
   988  	defer func() {
   989  		close(mapCh)
   990  		require.NoError(t, d.Close())
   991  		leaktest.CheckTimeout(t, time.Second)()
   992  	}()
   993  
   994  	// retrieve the update channel to track propatation
   995  	updateCh := d.opts.NamespaceInitializer().(*mockNsInitializer).updateCh
   996  
   997  	// check initial namespaces
   998  	nses := d.Namespaces()
   999  	require.Len(t, nses, 0)
  1000  
  1001  	// construct new namespace Map
  1002  	nsID3 := ident.StringID("testns3")
  1003  	md3, err := namespace.NewMetadata(nsID3, defaultTestNs1Opts)
  1004  	require.NoError(t, err)
  1005  	nsMap, err := namespace.NewMap([]namespace.Metadata{md3})
  1006  	require.NoError(t, err)
  1007  
  1008  	// update the database watch with new Map
  1009  	mapCh <- nsMap
  1010  
  1011  	// wait till the update has propagated
  1012  	time.Sleep(10 * time.Millisecond)
  1013  
  1014  	// ensure the namespace3 is not created successfully.
  1015  	nses = d.Namespaces()
  1016  	require.Len(t, nses, 0)
  1017  
  1018  	// Update nsID3 schema
  1019  	md3, err = namespace.NewMetadata(nsID3, defaultTestNs1Opts.SetSchemaHistory(testSchemaHistory))
  1020  	require.NoError(t, err)
  1021  	nsMap, err = namespace.NewMap([]namespace.Metadata{md3})
  1022  	require.NoError(t, err)
  1023  
  1024  	// update the database watch with new Map
  1025  	mapCh <- nsMap
  1026  
  1027  	// wait till the update has propagated
  1028  	time.Sleep(10 * time.Millisecond)
  1029  
  1030  	// Ensure the namespace3 is created successfully.
  1031  	nses = d.Namespaces()
  1032  	require.Len(t, nses, 1)
  1033  	ns3, ok := d.Namespace(nsID3)
  1034  	require.True(t, ok)
  1035  
  1036  	// Ensure schema is set
  1037  	require.NotNil(t, ns3.Schema())
  1038  
  1039  	schema, err := d.Options().SchemaRegistry().GetLatestSchema(nsID3)
  1040  	require.NoError(t, err)
  1041  	require.NotNil(t, schema)
  1042  
  1043  	// Update nsID3 schema to empty
  1044  	md3, err = namespace.NewMetadata(nsID3, defaultTestNs1Opts)
  1045  	require.NoError(t, err)
  1046  	nsMap, err = namespace.NewMap([]namespace.Metadata{md3})
  1047  	require.NoError(t, err)
  1048  
  1049  	// update the database watch with new Map
  1050  	mapCh <- nsMap
  1051  
  1052  	// wait till the update has propagated
  1053  	<-updateCh
  1054  	time.Sleep(10 * time.Millisecond)
  1055  
  1056  	// Ensure schema is not set to empty
  1057  	require.NotNil(t, ns3.Schema())
  1058  
  1059  	schema, err = d.Options().SchemaRegistry().GetLatestSchema(nsID3)
  1060  	require.NoError(t, err)
  1061  	require.NotNil(t, schema)
  1062  }
  1063  
  1064  func TestDatabaseNamespaceIndexFunctions(t *testing.T) {
  1065  	testDatabaseNamespaceIndexFunctions(t, true)
  1066  }
  1067  
  1068  func TestDatabaseNamespaceIndexFunctionsNoCommitlog(t *testing.T) {
  1069  	testDatabaseNamespaceIndexFunctions(t, false)
  1070  }
  1071  
  1072  func testDatabaseNamespaceIndexFunctions(t *testing.T, commitlogEnabled bool) {
  1073  	ctrl := xtest.NewController(t)
  1074  	defer ctrl.Finish()
  1075  
  1076  	d, mapCh, _ := defaultTestDatabase(t, ctrl, BootstrapNotStarted)
  1077  	defer func() {
  1078  		close(mapCh)
  1079  	}()
  1080  
  1081  	commitLog := d.commitLog
  1082  	if !commitlogEnabled {
  1083  		// We don't mock the commitlog so set this to nil to ensure its
  1084  		// not being used as the test will panic if any methods are called
  1085  		// on it.
  1086  		d.commitLog = nil
  1087  	}
  1088  
  1089  	ns := dbAddNewMockNamespace(ctrl, d, "testns")
  1090  	nsOptions := namespace.NewOptions().
  1091  		SetWritesToCommitLog(commitlogEnabled)
  1092  
  1093  	ns.EXPECT().OwnedShards().Return([]databaseShard{}).AnyTimes()
  1094  	ns.EXPECT().Tick(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  1095  	ns.EXPECT().ShardBootstrapState().Return(ShardBootstrapStates{}).AnyTimes()
  1096  	ns.EXPECT().Options().Return(nsOptions).AnyTimes()
  1097  	require.NoError(t, d.Open())
  1098  
  1099  	var (
  1100  		now         = xtime.Now()
  1101  		namespace   = ident.StringID("testns")
  1102  		ctx         = context.NewBackground()
  1103  		id          = ident.StringID("foo")
  1104  		tagsIter    = ident.EmptyTagIterator
  1105  		seriesWrite = SeriesWrite{
  1106  			Series: ts.Series{
  1107  				ID:        id,
  1108  				Namespace: namespace,
  1109  			},
  1110  			WasWritten: true,
  1111  		}
  1112  	)
  1113  
  1114  	// create initial span from a mock tracer and get ctx
  1115  	mtr := mocktracer.New()
  1116  	sp := mtr.StartSpan("root")
  1117  	ctx.SetGoContext(opentracing.ContextWithSpan(stdlibctx.Background(), sp))
  1118  
  1119  	ns.EXPECT().WriteTagged(gomock.Any(), ident.NewIDMatcher("foo"), gomock.Any(),
  1120  		now, 1.0, xtime.Second, nil).Return(seriesWrite, nil)
  1121  	require.NoError(t, d.WriteTagged(ctx, namespace,
  1122  		id, convert.NewTagsIterMetadataResolver(tagsIter), now,
  1123  		1.0, xtime.Second, nil))
  1124  
  1125  	ns.EXPECT().WriteTagged(gomock.Any(), ident.NewIDMatcher("foo"), gomock.Any(),
  1126  		now, 1.0, xtime.Second, nil).Return(SeriesWrite{}, fmt.Errorf("random err"))
  1127  	require.Error(t, d.WriteTagged(ctx, namespace,
  1128  		ident.StringID("foo"), convert.EmptyTagMetadataResolver, now,
  1129  		1.0, xtime.Second, nil))
  1130  
  1131  	var (
  1132  		q = index.Query{
  1133  			Query: idx.NewTermQuery([]byte("foo"), []byte("bar")),
  1134  		}
  1135  		opts    = index.QueryOptions{}
  1136  		res     = index.QueryResult{}
  1137  		aggOpts = index.AggregationOptions{}
  1138  		aggRes  = index.AggregateQueryResult{}
  1139  		err     error
  1140  	)
  1141  	ctx.SetGoContext(opentracing.ContextWithSpan(stdlibctx.Background(), sp))
  1142  	ns.EXPECT().QueryIDs(gomock.Any(), q, opts).Return(res, nil)
  1143  	_, err = d.QueryIDs(ctx, ident.StringID("testns"), q, opts)
  1144  	require.NoError(t, err)
  1145  
  1146  	ns.EXPECT().QueryIDs(gomock.Any(), q, opts).Return(res, fmt.Errorf("random err"))
  1147  	_, err = d.QueryIDs(ctx, ident.StringID("testns"), q, opts)
  1148  	require.Error(t, err)
  1149  
  1150  	ns.EXPECT().AggregateQuery(gomock.Any(), q, aggOpts).Return(aggRes, nil)
  1151  	_, err = d.AggregateQuery(ctx, ident.StringID("testns"), q, aggOpts)
  1152  	require.NoError(t, err)
  1153  
  1154  	ns.EXPECT().AggregateQuery(gomock.Any(), q, aggOpts).
  1155  		Return(aggRes, fmt.Errorf("random err"))
  1156  	_, err = d.AggregateQuery(ctx, ident.StringID("testns"), q, aggOpts)
  1157  	require.Error(t, err)
  1158  
  1159  	ns.EXPECT().Close().Return(nil)
  1160  
  1161  	// Ensure commitlog is set before closing because this will call commitlog.Close()
  1162  	d.commitLog = commitLog
  1163  	require.NoError(t, d.Close())
  1164  
  1165  	sp.Finish()
  1166  	spans := mtr.FinishedSpans()
  1167  	spanStrs := make([]string, 0, len(spans))
  1168  	for _, s := range spans {
  1169  		spanStrs = append(spanStrs, s.OperationName)
  1170  	}
  1171  	exSpans := []string{
  1172  		tracepoint.DBQueryIDs,
  1173  		tracepoint.DBQueryIDs,
  1174  		tracepoint.DBAggregateQuery,
  1175  		tracepoint.DBAggregateQuery,
  1176  		"root",
  1177  	}
  1178  
  1179  	assert.Equal(t, exSpans, spanStrs)
  1180  }
  1181  
  1182  func TestDatabaseWriteBatchNoNamespace(t *testing.T) {
  1183  	ctrl := xtest.NewController(t)
  1184  	defer ctrl.Finish()
  1185  
  1186  	d, mapCh, _ := defaultTestDatabase(t, ctrl, BootstrapNotStarted)
  1187  	defer func() {
  1188  		close(mapCh)
  1189  	}()
  1190  	require.NoError(t, d.Open())
  1191  
  1192  	var (
  1193  		notExistNamespace = ident.StringID("not-exist-namespace")
  1194  		batchSize         = 100
  1195  	)
  1196  	_, err := d.BatchWriter(notExistNamespace, batchSize)
  1197  	require.Error(t, err)
  1198  
  1199  	err = d.WriteBatch(context.NewBackground(), notExistNamespace, nil, nil)
  1200  	require.Error(t, err)
  1201  
  1202  	require.NoError(t, d.Close())
  1203  }
  1204  
  1205  func TestDatabaseWriteTaggedBatchNoNamespace(t *testing.T) {
  1206  	ctrl := xtest.NewController(t)
  1207  	defer ctrl.Finish()
  1208  
  1209  	d, mapCh, _ := defaultTestDatabase(t, ctrl, BootstrapNotStarted)
  1210  	defer func() {
  1211  		close(mapCh)
  1212  	}()
  1213  	require.NoError(t, d.Open())
  1214  
  1215  	var (
  1216  		notExistNamespace = ident.StringID("not-exist-namespace")
  1217  		batchSize         = 100
  1218  	)
  1219  	_, err := d.BatchWriter(notExistNamespace, batchSize)
  1220  	require.Error(t, err)
  1221  
  1222  	err = d.WriteTaggedBatch(context.NewBackground(), notExistNamespace, nil, nil)
  1223  	require.Error(t, err)
  1224  
  1225  	require.NoError(t, d.Close())
  1226  }
  1227  
  1228  func TestDatabaseWrite(t *testing.T) {
  1229  	dbWriteTests := []struct {
  1230  		name                              string
  1231  		tagged, commitlogEnabled, skipAll bool
  1232  	}{
  1233  		{"batch", false, false, false},
  1234  		{"tagged batch", true, false, false},
  1235  		{"batch no commitlog", false, true, false},
  1236  		{"tagged batch no commitlog", true, true, false},
  1237  		{"batch skip all", false, false, true},
  1238  		{"tagged batch skip all", true, false, true},
  1239  		{"batch no commitlog skip all", false, true, true},
  1240  		{"tagged batch no commitlog skip all", true, true, true},
  1241  	}
  1242  
  1243  	for _, tt := range dbWriteTests {
  1244  		t.Run(tt.name, func(t *testing.T) {
  1245  			testDatabaseWriteBatch(t, tt.tagged, tt.commitlogEnabled, tt.skipAll)
  1246  		})
  1247  	}
  1248  }
  1249  
  1250  type fakeIndexedErrorHandler struct {
  1251  	errs []indexedErr
  1252  }
  1253  
  1254  func (f *fakeIndexedErrorHandler) HandleError(index int, err error) {
  1255  	f.errs = append(f.errs, indexedErr{index, err})
  1256  }
  1257  
  1258  type indexedErr struct {
  1259  	index int
  1260  	err   error
  1261  }
  1262  
  1263  func testDatabaseWriteBatch(t *testing.T,
  1264  	tagged bool, commitlogEnabled bool, skipAll bool) {
  1265  	ctrl := xtest.NewController(t)
  1266  	defer ctrl.Finish()
  1267  
  1268  	d, mapCh, _ := defaultTestDatabase(t, ctrl, BootstrapNotStarted)
  1269  	defer func() {
  1270  		close(mapCh)
  1271  	}()
  1272  
  1273  	commitLog := d.commitLog
  1274  	if !commitlogEnabled {
  1275  		// We don't mock the commitlog so set this to nil to ensure its
  1276  		// not being used as the test will panic if any methods are called
  1277  		// on it.
  1278  		d.commitLog = nil
  1279  	}
  1280  
  1281  	ns := dbAddNewMockNamespace(ctrl, d, "testns")
  1282  	nsOptions := namespace.NewOptions().
  1283  		SetWritesToCommitLog(commitlogEnabled)
  1284  
  1285  	ns.EXPECT().OwnedShards().Return([]databaseShard{}).AnyTimes()
  1286  	ns.EXPECT().Tick(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  1287  	ns.EXPECT().ShardBootstrapState().Return(ShardBootstrapStates{}).AnyTimes()
  1288  	ns.EXPECT().Options().Return(nsOptions).AnyTimes()
  1289  	ns.EXPECT().Close().Return(nil).Times(1)
  1290  	require.NoError(t, d.Open())
  1291  
  1292  	var (
  1293  		namespace = ident.StringID("testns")
  1294  		ctx       = context.NewBackground()
  1295  		tags      = ident.NewTags(ident.Tag{
  1296  			Name:  ident.StringID("foo"),
  1297  			Value: ident.StringID("bar"),
  1298  		}, ident.Tag{
  1299  			Name:  ident.StringID("baz"),
  1300  			Value: ident.StringID("qux"),
  1301  		})
  1302  		tagsIter = ident.NewTagsIterator(tags)
  1303  	)
  1304  
  1305  	testTagEncodingPool := serialize.NewTagEncoderPool(serialize.NewTagEncoderOptions(),
  1306  		pool.NewObjectPoolOptions().SetSize(1))
  1307  	testTagEncodingPool.Init()
  1308  	encoder := testTagEncodingPool.Get()
  1309  	err := encoder.Encode(tagsIter)
  1310  	require.NoError(t, err)
  1311  
  1312  	encodedTags, ok := encoder.Data()
  1313  	require.True(t, ok)
  1314  
  1315  	testWrites := []struct {
  1316  		series string
  1317  		t      xtime.UnixNano
  1318  		v      float64
  1319  		skip   bool
  1320  		err    error
  1321  	}{
  1322  		{
  1323  			series: "won't appear - always skipped",
  1324  			t:      xtime.UnixNano(0 * time.Second),
  1325  			skip:   true,
  1326  			v:      0.0,
  1327  		},
  1328  		{
  1329  			series: "foo",
  1330  			t:      xtime.UnixNano(10 * time.Second),
  1331  			skip:   skipAll,
  1332  			v:      1.0,
  1333  		},
  1334  		{
  1335  			series: "bar",
  1336  			t:      xtime.UnixNano(20 * time.Second),
  1337  			skip:   skipAll,
  1338  			v:      2.0,
  1339  		},
  1340  		{
  1341  			series: "baz",
  1342  			t:      xtime.UnixNano(20 * time.Second),
  1343  			skip:   skipAll,
  1344  			v:      3.0,
  1345  		},
  1346  		{
  1347  			series: "qux",
  1348  			t:      xtime.UnixNano(30 * time.Second),
  1349  			skip:   skipAll,
  1350  			v:      4.0,
  1351  		},
  1352  		{
  1353  			series: "won't appear - always skipped",
  1354  			t:      xtime.UnixNano(40 * time.Second),
  1355  			skip:   true,
  1356  			v:      5.0,
  1357  		},
  1358  		{
  1359  			series: "error-series",
  1360  			err:    errors.New("some-error"),
  1361  		},
  1362  	}
  1363  
  1364  	batchWriter, err := d.BatchWriter(namespace, 10)
  1365  	require.NoError(t, err)
  1366  
  1367  	var i int
  1368  	for _, write := range testWrites {
  1369  		// Write with the provided index as i*2 so we can assert later that the
  1370  		// ErrorHandler is called with the provided index, not the actual position
  1371  		// in the WriteBatch slice.
  1372  		if tagged {
  1373  			batchWriter.AddTagged(i*2, ident.StringID(write.series),
  1374  				encodedTags.Bytes(), write.t, write.v, xtime.Second, nil)
  1375  			wasWritten := write.err == nil
  1376  			ns.EXPECT().
  1377  				WriteTagged(ctx, ident.NewIDMatcher(write.series), gomock.Any(),
  1378  					write.t, write.v, xtime.Second, nil).
  1379  				Return(SeriesWrite{
  1380  					Series: ts.Series{
  1381  						ID:        ident.StringID(write.series + "-updated"),
  1382  						Namespace: namespace,
  1383  					}, WasWritten: wasWritten,
  1384  				}, write.err)
  1385  		} else {
  1386  			batchWriter.Add(i*2, ident.StringID(write.series),
  1387  				write.t, write.v, xtime.Second, nil)
  1388  			wasWritten := write.err == nil
  1389  			ns.EXPECT().
  1390  				Write(ctx, ident.NewIDMatcher(write.series),
  1391  					write.t, write.v, xtime.Second, nil).
  1392  				Return(SeriesWrite{
  1393  					Series: ts.Series{
  1394  						ID:        ident.StringID(write.series + "-updated"),
  1395  						Namespace: namespace,
  1396  					},
  1397  					WasWritten: wasWritten,
  1398  				}, write.err)
  1399  		}
  1400  		i++
  1401  	}
  1402  
  1403  	errHandler := &fakeIndexedErrorHandler{}
  1404  	if tagged {
  1405  		err = d.WriteTaggedBatch(ctx, namespace, batchWriter.(writes.WriteBatch),
  1406  			errHandler)
  1407  	} else {
  1408  		err = d.WriteBatch(ctx, namespace, batchWriter.(writes.WriteBatch),
  1409  			errHandler)
  1410  	}
  1411  
  1412  	require.NoError(t, err)
  1413  	require.Len(t, errHandler.errs, 1)
  1414  	// Make sure it calls the error handler with the "original" provided index, not the position
  1415  	// of the write in the WriteBatch slice.
  1416  	require.Equal(t, (i-1)*2, errHandler.errs[0].index)
  1417  
  1418  	// Ensure commitlog is set before closing because this will call commitlog.Close()
  1419  	d.commitLog = commitLog
  1420  	require.NoError(t, d.Close())
  1421  }
  1422  
  1423  func TestDatabaseBootstrapState(t *testing.T) {
  1424  	ctrl := xtest.NewController(t)
  1425  	defer ctrl.Finish()
  1426  
  1427  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
  1428  	defer func() {
  1429  		close(mapCh)
  1430  	}()
  1431  
  1432  	ns1 := dbAddNewMockNamespace(ctrl, d, "testns1")
  1433  	ns1.EXPECT().ShardBootstrapState().Return(ShardBootstrapStates{
  1434  		1: Bootstrapping,
  1435  	})
  1436  	ns2 := dbAddNewMockNamespace(ctrl, d, "testns2")
  1437  	ns2.EXPECT().ShardBootstrapState().Return(ShardBootstrapStates{
  1438  		2: Bootstrapped,
  1439  	})
  1440  
  1441  	dbBootstrapState := d.BootstrapState()
  1442  	require.Equal(t, DatabaseBootstrapState{
  1443  		NamespaceBootstrapStates: NamespaceBootstrapStates{
  1444  			"testns1": ShardBootstrapStates{
  1445  				1: Bootstrapping,
  1446  			},
  1447  			"testns2": ShardBootstrapStates{
  1448  				2: Bootstrapped,
  1449  			},
  1450  		},
  1451  	}, dbBootstrapState)
  1452  }
  1453  
  1454  func TestDatabaseFlushState(t *testing.T) {
  1455  	ctrl := xtest.NewController(t)
  1456  	defer ctrl.Finish()
  1457  
  1458  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
  1459  	defer func() {
  1460  		close(mapCh)
  1461  	}()
  1462  
  1463  	var (
  1464  		shardID            = uint32(0)
  1465  		blockStart         = xtime.Now().Truncate(2 * time.Hour)
  1466  		expectedFlushState = fileOpState{
  1467  			ColdVersionRetrievable: 2,
  1468  		}
  1469  		nsID = "testns1"
  1470  		ns   = dbAddNewMockNamespace(ctrl, d, nsID)
  1471  	)
  1472  	ns.EXPECT().FlushState(shardID, blockStart).Return(expectedFlushState, nil)
  1473  
  1474  	flushState, err := d.FlushState(ident.StringID(nsID), shardID, blockStart)
  1475  	require.NoError(t, err)
  1476  	require.Equal(t, expectedFlushState, flushState)
  1477  
  1478  	_, err = d.FlushState(ident.StringID("not-exist"), shardID, blockStart)
  1479  	require.Error(t, err)
  1480  }
  1481  
  1482  func TestDatabaseIsBootstrapped(t *testing.T) {
  1483  	ctrl := xtest.NewController(t)
  1484  	defer ctrl.Finish()
  1485  
  1486  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
  1487  	defer func() {
  1488  		close(mapCh)
  1489  	}()
  1490  
  1491  	md := NewMockdatabaseMediator(ctrl)
  1492  	md.EXPECT().IsBootstrapped().Return(true)
  1493  	md.EXPECT().IsBootstrapped().Return(false)
  1494  	d.mediator = md
  1495  
  1496  	assert.True(t, d.IsBootstrapped())
  1497  	assert.False(t, d.IsBootstrapped())
  1498  }
  1499  
  1500  func TestUpdateBatchWriterBasedOnShardResults(t *testing.T) {
  1501  	ctrl := xtest.NewController(t)
  1502  	defer ctrl.Finish()
  1503  
  1504  	d, mapCh, _ := defaultTestDatabase(t, ctrl, BootstrapNotStarted)
  1505  	defer func() {
  1506  		close(mapCh)
  1507  	}()
  1508  
  1509  	commitLog := d.commitLog
  1510  	d.commitLog = nil
  1511  
  1512  	ns := dbAddNewMockNamespace(ctrl, d, "testns")
  1513  	nsOptions := namespace.NewOptions().
  1514  		SetWritesToCommitLog(false)
  1515  	ns.EXPECT().OwnedShards().Return([]databaseShard{}).AnyTimes()
  1516  	ns.EXPECT().Tick(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  1517  	ns.EXPECT().ShardBootstrapState().Return(ShardBootstrapStates{}).AnyTimes()
  1518  	ns.EXPECT().Options().Return(nsOptions).AnyTimes()
  1519  	ns.EXPECT().Close().Return(nil).Times(1)
  1520  	require.NoError(t, d.Open())
  1521  
  1522  	var (
  1523  		namespace    = ident.StringID("testns")
  1524  		ctx          = context.NewBackground()
  1525  		seriesWrite1 = SeriesWrite{Series: ts.Series{UniqueIndex: 0}, WasWritten: true}
  1526  		seriesWrite2 = SeriesWrite{Series: ts.Series{UniqueIndex: 1}, WasWritten: true}
  1527  		seriesWrite3 = SeriesWrite{Series: ts.Series{UniqueIndex: 2}, WasWritten: false}
  1528  		seriesWrite4 = SeriesWrite{Series: ts.Series{UniqueIndex: 3}, WasWritten: false}
  1529  		err          = fmt.Errorf("err")
  1530  	)
  1531  
  1532  	gomock.InOrder(
  1533  		ns.EXPECT().
  1534  			Write(ctx, gomock.Any(), gomock.Any(), gomock.Any(),
  1535  				gomock.Any(), gomock.Any()).
  1536  			Return(seriesWrite1, nil),
  1537  		ns.EXPECT().
  1538  			Write(ctx, gomock.Any(), gomock.Any(), gomock.Any(),
  1539  				gomock.Any(), gomock.Any()).
  1540  			Return(seriesWrite2, err),
  1541  		ns.EXPECT().
  1542  			Write(ctx, gomock.Any(), gomock.Any(), gomock.Any(),
  1543  				gomock.Any(), gomock.Any()).
  1544  			Return(seriesWrite3, err),
  1545  		ns.EXPECT().
  1546  			Write(ctx, gomock.Any(), gomock.Any(), gomock.Any(),
  1547  				gomock.Any(), gomock.Any()).
  1548  			Return(seriesWrite4, nil),
  1549  	)
  1550  
  1551  	write := writes.Write{
  1552  		Series: ts.Series{ID: ident.StringID("foo")},
  1553  	}
  1554  
  1555  	iters := []writes.BatchWrite{
  1556  		{Write: write},
  1557  		{Write: write},
  1558  		{Write: write},
  1559  		{Write: write},
  1560  	}
  1561  
  1562  	batchWriter := writes.NewMockWriteBatch(ctrl)
  1563  	gomock.InOrder(
  1564  		batchWriter.EXPECT().Iter().Return(iters),
  1565  		batchWriter.EXPECT().SetSeries(0, seriesWrite1.Series),
  1566  		batchWriter.EXPECT().SetError(1, err),
  1567  		batchWriter.EXPECT().SetError(2, err),
  1568  		batchWriter.EXPECT().SetSeries(3, seriesWrite4.Series),
  1569  		batchWriter.EXPECT().SetSkipWrite(3),
  1570  		batchWriter.EXPECT().PendingIndex().Return(nil),
  1571  		batchWriter.EXPECT().Finalize(),
  1572  	)
  1573  
  1574  	errHandler := &fakeIndexedErrorHandler{}
  1575  	d.WriteBatch(ctx, namespace, batchWriter, errHandler)
  1576  	require.Equal(t, 2, len(errHandler.errs))
  1577  	require.Equal(t, err, errHandler.errs[0].err)
  1578  	require.Equal(t, err, errHandler.errs[1].err)
  1579  	d.commitLog = commitLog
  1580  	require.NoError(t, d.Close())
  1581  }
  1582  
  1583  func TestDatabaseIsOverloaded(t *testing.T) {
  1584  	ctrl := xtest.NewController(t)
  1585  	defer ctrl.Finish()
  1586  
  1587  	d, mapCh, _ := defaultTestDatabase(t, ctrl, BootstrapNotStarted)
  1588  	defer func() {
  1589  		close(mapCh)
  1590  	}()
  1591  
  1592  	d.opts = d.opts.SetCommitLogOptions(
  1593  		d.opts.CommitLogOptions().SetBacklogQueueSize(100),
  1594  	)
  1595  
  1596  	mockCL := commitlog.NewMockCommitLog(ctrl)
  1597  	d.commitLog = mockCL
  1598  
  1599  	mockCL.EXPECT().QueueLength().Return(int64(89))
  1600  	require.Equal(t, false, d.IsOverloaded())
  1601  
  1602  	mockCL.EXPECT().QueueLength().Return(int64(90))
  1603  	require.Equal(t, true, d.IsOverloaded())
  1604  }
  1605  
  1606  func TestDatabaseAggregateTiles(t *testing.T) {
  1607  	ctrl := xtest.NewController(t)
  1608  	defer ctrl.Finish()
  1609  
  1610  	ctx := context.NewBackground()
  1611  	defer ctx.Close()
  1612  
  1613  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
  1614  	defer func() {
  1615  		close(mapCh)
  1616  	}()
  1617  
  1618  	var (
  1619  		sourceNsID = ident.StringID("source")
  1620  		targetNsID = ident.StringID("target")
  1621  		start      = xtime.Now().Truncate(time.Hour)
  1622  		process    = AggregateTilesAPI
  1623  	)
  1624  
  1625  	opts, err := NewAggregateTilesOptions(
  1626  		start, start.Add(-time.Second), time.Minute, targetNsID, process,
  1627  		false, false, nil, d.opts.InstrumentOptions())
  1628  	require.Error(t, err)
  1629  	opts.InsOptions = d.opts.InstrumentOptions()
  1630  
  1631  	sourceNs := dbAddNewMockNamespace(ctrl, d, sourceNsID.String())
  1632  	targetNs := dbAddNewMockNamespace(ctrl, d, targetNsID.String())
  1633  	targetNs.EXPECT().AggregateTiles(ctx, sourceNs, opts).Return(int64(4), nil)
  1634  
  1635  	processedTileCount, err := d.AggregateTiles(ctx, sourceNsID, targetNsID, opts)
  1636  	require.NoError(t, err)
  1637  	assert.Equal(t, int64(4), processedTileCount)
  1638  }
  1639  
  1640  func TestNewAggregateTilesOptions(t *testing.T) {
  1641  	var (
  1642  		start    = xtime.Now().Truncate(time.Hour)
  1643  		end      = start.Add(time.Second)
  1644  		targetNs = ident.StringID("target")
  1645  		insOpts  = instrument.NewOptions()
  1646  		process  = AggregateTilesRegular
  1647  	)
  1648  
  1649  	_, err := NewAggregateTilesOptions(start, start.Add(-time.Second), time.Minute, targetNs, process,
  1650  		false, false, nil, insOpts)
  1651  	assert.Error(t, err)
  1652  
  1653  	_, err = NewAggregateTilesOptions(start, start, time.Minute, targetNs, process,
  1654  		false, false, nil, insOpts)
  1655  	assert.Error(t, err)
  1656  
  1657  	_, err = NewAggregateTilesOptions(start, end, -time.Minute, targetNs, process,
  1658  		false, false, nil, insOpts)
  1659  	assert.Error(t, err)
  1660  
  1661  	_, err = NewAggregateTilesOptions(start, end, 0, targetNs, process,
  1662  		false, false, nil, insOpts)
  1663  	assert.Error(t, err)
  1664  
  1665  	_, err = NewAggregateTilesOptions(start, end, time.Minute, targetNs, process,
  1666  		false, false, nil, insOpts)
  1667  	assert.NoError(t, err)
  1668  
  1669  	_, err = NewAggregateTilesOptions(start, end, time.Minute, targetNs, process,
  1670  		true, false, nil, insOpts)
  1671  	assert.Error(t, err)
  1672  
  1673  	_, err = NewAggregateTilesOptions(start, end, time.Minute, targetNs, process,
  1674  		false, true, nil, insOpts)
  1675  	assert.Error(t, err)
  1676  
  1677  	_, err = NewAggregateTilesOptions(start, end, time.Minute, targetNs, process,
  1678  		true, true, nil, insOpts)
  1679  	assert.Error(t, err)
  1680  
  1681  	_, err = NewAggregateTilesOptions(start, end, time.Minute, targetNs, process,
  1682  		true, true, map[string]annotation.Payload{}, insOpts)
  1683  	assert.NoError(t, err)
  1684  }
  1685  
  1686  func TestShardsDelta(t *testing.T) {
  1687  	ctrl := xtest.NewController(t)
  1688  	defer ctrl.Finish()
  1689  
  1690  	ctx := context.NewBackground()
  1691  	defer ctx.Close()
  1692  
  1693  	d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped)
  1694  	defer func() {
  1695  		close(mapCh)
  1696  	}()
  1697  
  1698  	shards := append(sharding.NewShards([]uint32{0, 1}, shard.Available),
  1699  		sharding.NewShards([]uint32{2}, shard.Initializing)...)
  1700  	shardSet, err := sharding.NewShardSet(shards, nil)
  1701  	require.NoError(t, err)
  1702  
  1703  	d.shardSet = shardSet
  1704  
  1705  	t.Run("unchanged", func(t *testing.T) {
  1706  		incoming := append(sharding.NewShards([]uint32{0, 1}, shard.Available),
  1707  			sharding.NewShards([]uint32{2}, shard.Initializing)...)
  1708  		shardSet, err = sharding.NewShardSet(incoming, nil)
  1709  		require.NoError(t, err)
  1710  
  1711  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1712  		require.False(t, added)
  1713  		require.False(t, removed)
  1714  		require.False(t, updated)
  1715  	})
  1716  
  1717  	t.Run("added-updated-deleted", func(t *testing.T) {
  1718  		incomingAddedRemovedUpdated := append(sharding.NewShards([]uint32{1, 2}, shard.Available),
  1719  			sharding.NewShards([]uint32{3}, shard.Initializing)...)
  1720  		shardSet, err = sharding.NewShardSet(incomingAddedRemovedUpdated, nil)
  1721  		require.NoError(t, err)
  1722  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1723  		require.True(t, added)
  1724  		require.True(t, removed)
  1725  		require.True(t, updated)
  1726  	})
  1727  
  1728  	t.Run("added", func(t *testing.T) {
  1729  		incomingAdded := append(sharding.NewShards([]uint32{0, 1}, shard.Available),
  1730  			sharding.NewShards([]uint32{2, 3}, shard.Initializing)...)
  1731  		shardSet, err = sharding.NewShardSet(incomingAdded, nil)
  1732  		require.NoError(t, err)
  1733  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1734  		require.True(t, added)
  1735  		require.False(t, removed)
  1736  		require.False(t, updated)
  1737  	})
  1738  
  1739  	t.Run("updated", func(t *testing.T) {
  1740  		incomingUpdated := sharding.NewShards([]uint32{0, 1, 2}, shard.Available)
  1741  		shardSet, err = sharding.NewShardSet(incomingUpdated, nil)
  1742  		require.NoError(t, err)
  1743  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1744  		require.False(t, added)
  1745  		require.False(t, removed)
  1746  		require.True(t, updated)
  1747  	})
  1748  
  1749  	t.Run("removed", func(t *testing.T) {
  1750  		incomingRemoved := sharding.NewShards([]uint32{0, 1}, shard.Available)
  1751  		shardSet, err = sharding.NewShardSet(incomingRemoved, nil)
  1752  		require.NoError(t, err)
  1753  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1754  		require.False(t, added)
  1755  		require.True(t, removed)
  1756  		require.False(t, updated)
  1757  	})
  1758  
  1759  	t.Run("added-updated", func(t *testing.T) {
  1760  		incomingAddedUpdated := append(sharding.NewShards([]uint32{0, 1, 2}, shard.Available),
  1761  			sharding.NewShards([]uint32{3}, shard.Initializing)...)
  1762  		shardSet, err = sharding.NewShardSet(incomingAddedUpdated, nil)
  1763  		require.NoError(t, err)
  1764  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1765  		require.True(t, added)
  1766  		require.False(t, removed)
  1767  		require.True(t, updated)
  1768  	})
  1769  
  1770  	t.Run("added-removed", func(t *testing.T) {
  1771  		incomingAddedRemoved := append(sharding.NewShards([]uint32{1}, shard.Available),
  1772  			sharding.NewShards([]uint32{3}, shard.Initializing)...)
  1773  		shardSet, err = sharding.NewShardSet(incomingAddedRemoved, nil)
  1774  		require.NoError(t, err)
  1775  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1776  		require.True(t, added)
  1777  		require.True(t, removed)
  1778  		require.False(t, updated)
  1779  	})
  1780  
  1781  	t.Run("updated-removed", func(t *testing.T) {
  1782  		incomingUpdatedRemoved := append(sharding.NewShards([]uint32{0}, shard.Available),
  1783  			sharding.NewShards([]uint32{1}, shard.Initializing)...)
  1784  		shardSet, err = sharding.NewShardSet(incomingUpdatedRemoved, nil)
  1785  		require.NoError(t, err)
  1786  		added, removed, updated := d.shardsDeltaWithLock(shardSet)
  1787  		require.False(t, added)
  1788  		require.True(t, removed)
  1789  		require.True(t, updated)
  1790  	})
  1791  }
  1792  
  1793  func assertFileOpsEnabled(t *testing.T, d *db) {
  1794  	mediator := d.mediator.(*mediator)
  1795  	coldFlushManager := mediator.databaseColdFlushManager.(*coldFlushManager)
  1796  	fileSystemManager := mediator.databaseFileSystemManager.(*fileSystemManager)
  1797  
  1798  	coldFlushManager.RLock()
  1799  	require.True(t, coldFlushManager.enabled)
  1800  	coldFlushManager.RUnlock()
  1801  
  1802  	fileSystemManager.RLock()
  1803  	require.True(t, fileSystemManager.enabled)
  1804  	fileSystemManager.RUnlock()
  1805  }