// Copyright 2023 Dolthub, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "os" "path/filepath" "strconv" "strings" "testing" sqldriver "database/sql/driver" "github.com/stretchr/testify/require" driver "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils/sql_server_driver" ) func TestGCConjoinsOldgen(t *testing.T) { t.Parallel() var ports DynamicResources ports.global = &GlobalPorts ports.t = t u, err := driver.NewDoltUser() require.NoError(t, err) t.Cleanup(func() { u.Cleanup() }) rs, err := u.MakeRepoStore() require.NoError(t, err) repo, err := rs.MakeRepo("concurrent_gc_test") require.NoError(t, err) server := MakeServer(t, repo, &driver.Server{ Args: []string{"--port", `{{get_port "server"}}`}, DynamicPort: "server", }, &ports) server.DBName = "concurrent_gc_test" db, err := server.DB(driver.Connection{User: "root"}) require.NoError(t, err) defer db.Close() ctx := context.Background() // Create the database... func() { conn, err := db.Conn(ctx) require.NoError(t, err) defer conn.Close() _, err = conn.ExecContext(ctx, "create table vals (id bigint primary key, val bigint)") require.NoError(t, err) _, err = conn.ExecContext(ctx, "call dolt_commit('-Am', 'create vals table')") require.NoError(t, err) }() // Each 1024 leaf entries is approximately one chunk. // We create 512 commits, each of which adds the next 1024 rows sequentially. // After we create each commit, we dolt_gc(), which moves the new chunks to // the oldgen. At the end of the test, we will assert that there are not // too many table files in the old gen. for i := 0; i < 512; i++ { var vals []string for j := i*1024; j < (i+1)*1024; j++ { vals = append(vals, "(" + strconv.Itoa(j) + ",0)") } func() { conn, err := db.Conn(ctx) defer func() { // After calling dolt_gc, the connection is bad. Remove it from the connection pool. conn.Raw(func(_ any) error { return sqldriver.ErrBadConn }) }() _, err = conn.ExecContext(ctx, "insert into vals values " + strings.Join(vals, ",")) require.NoError(t, err) _, err = conn.ExecContext(ctx, "call dolt_commit('-am', 'insert from " + strconv.Itoa(i*1024) + "')") require.NoError(t, err) _, err = conn.ExecContext(ctx, "call dolt_gc()") require.NoError(t, err) }() } entries, err := os.ReadDir(filepath.Join(repo.Dir, ".dolt/noms/oldgen")) require.NoError(t, err) require.Greater(t, len(entries), 2) // defaultMaxTables == 256, plus a few files extra like |manifest| and |LOCK|. require.Less(t, len(entries), 272) }