From 59b767aa42df45c98b61d1800afe30242a06bcd9 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Wed, 25 Sep 2024 15:54:15 +0530 Subject: [PATCH 01/33] base CPU based logic for adapting parallelism --- .../adaptive_parallelism.go | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go new file mode 100644 index 000000000..04e165d27 --- /dev/null +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -0,0 +1,92 @@ +/* +Copyright (c) YugabyteDB, 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 adaptiveparallelism + +import ( + "fmt" + "strconv" + "time" + + "github.com/yugabyte/yb-voyager/yb-voyager/src/utils" +) + +const ( + CPU_USAGE_USER = "cpu_usage_user" + CPU_USAGE_SYSTEM = "cpu_usage_system" + MAX_CPU_THRESHOLD = 70 +) + +type TargetYugabyteDBWithConnectionPool interface { + IsAdaptiveParallelismSupported() bool + GetClusterMetrics() (map[string]map[string]string, error) // node_uuid:metric_name:metric_value + GetNumConnectionsInPool() int + UpdateNumConnectionsInPool(int) bool +} + +func AdaptParalleism(yb TargetYugabyteDBWithConnectionPool) error { + if !yb.IsAdaptiveParallelismSupported() { + return fmt.Errorf("adaptive parallelism not supported in target YB database.") + } + for { + utils.PrintAndLog("--------------------------------------------------------") + clusterMetrics, err := yb.GetClusterMetrics() + if err != nil { + utils.PrintAndLog("error getting cluster metrics: %v", err) + } + utils.PrintAndLog("PARALLELISM: cluster metrics: %v", clusterMetrics) + + // max cpu + maxCpuUsage, err := getMaxCpuUsageInCluster(clusterMetrics) + if err != nil { + return fmt.Errorf("getting max cpu usage in cluster: %w", err) + } + + if maxCpuUsage > MAX_CPU_THRESHOLD { + utils.PrintAndLog("PARALLELISM: found CPU usage = %d > %d, reducing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()-1) + updated := yb.UpdateNumConnectionsInPool(yb.GetNumConnectionsInPool() - 1) + if !updated { + utils.PrintAndLog("PARALLELISM: no update. pending change request or change out of bounds") + } + } else { + utils.PrintAndLog("PARALLELISM: found CPU usage = %d <= %d, increasing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()+1) + updated := yb.UpdateNumConnectionsInPool(yb.GetNumConnectionsInPool() + 1) + if !updated { + utils.PrintAndLog("PARALLELISM: no update. pending change request or change out of bounds") + } + } + time.Sleep(20 * time.Second) + } +} + +func getMaxCpuUsageInCluster(clusterMetrics map[string]map[string]string) (int, error) { + var maxCpuPct int + for _, nodeMetrics := range clusterMetrics { + cpuUsageUser, err := strconv.ParseFloat(nodeMetrics[CPU_USAGE_USER], 64) + if err != nil { + return -1, fmt.Errorf("parsing cpu usage user as float: %w", err) + } + cpuUsageSystem, err := strconv.ParseFloat(nodeMetrics[CPU_USAGE_SYSTEM], 64) + if err != nil { + return -1, fmt.Errorf("parsing cpu usage system as float: %w", err) + } + + cpuUsagePct := int((cpuUsageUser + cpuUsageSystem) * 100) + if cpuUsagePct > maxCpuPct { + maxCpuPct = cpuUsagePct + } + } + return maxCpuPct, nil +} From c12aeb67909a9639f47012bdbfe7ae862bcc9a42 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Wed, 25 Sep 2024 16:08:27 +0530 Subject: [PATCH 02/33] implement GetClusterMetrics --- yb-voyager/cmd/importData.go | 8 +++++ .../adaptive_parallelism.go | 8 +++-- yb-voyager/src/tgtdb/yugabytedb.go | 36 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/yb-voyager/cmd/importData.go b/yb-voyager/cmd/importData.go index ce9f53fa9..9e6954b80 100644 --- a/yb-voyager/cmd/importData.go +++ b/yb-voyager/cmd/importData.go @@ -36,6 +36,7 @@ import ( "github.com/spf13/cobra" "golang.org/x/exp/slices" + "github.com/yugabyte/yb-voyager/yb-voyager/src/adaptiveparallelism" "github.com/yugabyte/yb-voyager/yb-voyager/src/callhome" "github.com/yugabyte/yb-voyager/yb-voyager/src/cp" "github.com/yugabyte/yb-voyager/yb-voyager/src/datafile" @@ -436,6 +437,13 @@ func importData(importFileTasks []*ImportFileTask) { utils.ErrExit("Failed to initialize the target DB connection pool: %s", err) } utils.PrintAndLog("Using %d parallel jobs.", tconf.Parallelism) + if importerRole == TARGET_DB_IMPORTER_ROLE || importerRole == IMPORT_FILE_ROLE { + yb, ok := tdb.(*tgtdb.TargetYugabyteDB) + if !ok { + utils.ErrExit("adaptive parallelism is only supported if target DB is YugabyteDB") + } + go adaptiveparallelism.AdaptParallelism(yb) + } targetDBVersion := tdb.GetVersion() fmt.Printf("%s version: %s\n", tconf.TargetDBType, targetDBVersion) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index 04e165d27..75625b4e9 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -36,7 +36,7 @@ type TargetYugabyteDBWithConnectionPool interface { UpdateNumConnectionsInPool(int) bool } -func AdaptParalleism(yb TargetYugabyteDBWithConnectionPool) error { +func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { if !yb.IsAdaptiveParallelismSupported() { return fmt.Errorf("adaptive parallelism not supported in target YB database.") } @@ -46,13 +46,14 @@ func AdaptParalleism(yb TargetYugabyteDBWithConnectionPool) error { if err != nil { utils.PrintAndLog("error getting cluster metrics: %v", err) } - utils.PrintAndLog("PARALLELISM: cluster metrics: %v", clusterMetrics) + // utils.PrintAndLog("PARALLELISM: cluster metrics: %v", clusterMetrics) // max cpu maxCpuUsage, err := getMaxCpuUsageInCluster(clusterMetrics) if err != nil { return fmt.Errorf("getting max cpu usage in cluster: %w", err) } + utils.PrintAndLog("PARALLELISM: max cpu usage in cluster = %d", maxCpuUsage) if maxCpuUsage > MAX_CPU_THRESHOLD { utils.PrintAndLog("PARALLELISM: found CPU usage = %d > %d, reducing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()-1) @@ -67,8 +68,9 @@ func AdaptParalleism(yb TargetYugabyteDBWithConnectionPool) error { utils.PrintAndLog("PARALLELISM: no update. pending change request or change out of bounds") } } - time.Sleep(20 * time.Second) + time.Sleep(10 * time.Second) } + return nil } func getMaxCpuUsageInCluster(clusterMetrics map[string]map[string]string) (int, error) { diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 8679cfc1a..a799536db 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -29,6 +29,7 @@ import ( "time" "github.com/davecgh/go-spew/spew" + "github.com/goccy/go-json" "github.com/google/uuid" "github.com/jackc/pgconn" "github.com/jackc/pgx/v4" @@ -1164,6 +1165,41 @@ func (yb *TargetYugabyteDB) isQueryResultNonEmpty(query string) bool { return rows.Next() } +func (yb *TargetYugabyteDB) IsAdaptiveParallelismSupported() bool { + return true +} + +func (yb *TargetYugabyteDB) GetClusterMetrics() (map[string]map[string]string, error) { + result := make(map[string]map[string]string) + + query := "select uuid, metrics, status, error from yb_servers_metrics();" + rows, err := yb.Query(query) + if err != nil { + return result, fmt.Errorf("querying yb_servers_metrics(): %w", err) + } + defer rows.Close() + for rows.Next() { + var uuid, metrics, status, errorStr string + if err := rows.Scan(&uuid, &metrics, &status, &errorStr); err != nil { + return result, fmt.Errorf("scanning row for yb_servers_metrics(): %w", err) + } + var metricsMap map[string]string + if err := json.Unmarshal([]byte(metrics), &metricsMap); err != nil { + return result, fmt.Errorf("unmarshalling metrics json string: %w", err) + } + result[uuid] = metricsMap + } + return result, nil +} + +func (yb *TargetYugabyteDB) GetNumConnectionsInPool() int { + return 0 +} + +func (yb *TargetYugabyteDB) UpdateNumConnectionsInPool(newSize int) bool { + return true +} + func (yb *TargetYugabyteDB) ClearMigrationState(migrationUUID uuid.UUID, exportDir string) error { log.Infof("clearing migration state for migrationUUID: %s", migrationUUID) schema := BATCH_METADATA_TABLE_SCHEMA From 6566cc08f12593b03599bd906783aa8045ae260d Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Thu, 26 Sep 2024 13:16:48 +0530 Subject: [PATCH 03/33] max connections in pool, change requests --- yb-voyager/src/tgtdb/conn_pool.go | 65 ++++++++++++++++++++++++++++-- yb-voyager/src/tgtdb/yugabytedb.go | 5 ++- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index 8365e1270..d6c333bbf 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -36,6 +36,7 @@ var defaultSessionVars = []string{ type ConnectionParams struct { NumConnections int + NumMaxConnections int ConnUriList []string SessionInitScript []string } @@ -44,20 +45,31 @@ type ConnectionPool struct { sync.Mutex params *ConnectionParams conns chan *pgx.Conn + idleConns chan *pgx.Conn connIdToPreparedStmtCache map[uint32]map[string]bool // cache list of prepared statements per connection nextUriIndex int disableThrottling bool + size int // current size of the pool + sizeChangeRequests chan int + connLock sync.Mutex } func NewConnectionPool(params *ConnectionParams) *ConnectionPool { pool := &ConnectionPool{ params: params, - conns: make(chan *pgx.Conn, params.NumConnections), - connIdToPreparedStmtCache: make(map[uint32]map[string]bool, params.NumConnections), + conns: make(chan *pgx.Conn, params.NumMaxConnections), + idleConns: make(chan *pgx.Conn, params.NumMaxConnections), + connIdToPreparedStmtCache: make(map[uint32]map[string]bool, params.NumMaxConnections), disableThrottling: false, + size: params.NumConnections, + sizeChangeRequests: make(chan int, 1), //only allow one change request. + } + for i := 0; i < params.NumMaxConnections; i++ { + pool.idleConns <- nil } for i := 0; i < params.NumConnections; i++ { - pool.conns <- nil + c := <-pool.idleConns + pool.conns <- c } if pool.params.SessionInitScript == nil { pool.params.SessionInitScript = defaultSessionVars @@ -65,10 +77,50 @@ func NewConnectionPool(params *ConnectionParams) *ConnectionPool { return pool } +func (pool *ConnectionPool) GetNumConnections() int { + return pool.size +} + +func (pool *ConnectionPool) UpdateNumConnections(newSize int) bool { + if newSize < 1 || newSize > pool.params.NumMaxConnections { + return false + } + select { + case pool.sizeChangeRequests <- newSize: + return true + default: + return false + } +} + func (pool *ConnectionPool) DisableThrottling() { pool.disableThrottling = true } +func (pool *ConnectionPool) applySizeChangeRequest() { + select { + case newSize := <-pool.sizeChangeRequests: + if newSize > pool.size { + for i := 0; i < newSize-pool.size; i++ { + conn := <-pool.idleConns + pool.conns <- conn + } + } else if newSize < pool.size { + for i := 0; i < pool.size-newSize; i++ { + conn := <-pool.conns + pool.idleConns <- conn + // if conn != nil { + // conn.Close(context.Background()) + // } + } + } + oldSize := pool.size + pool.size = newSize + utils.PrintAndLog("PARALLELISM: Updated pool size from %d to %d", oldSize, newSize) + default: + } +} + func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { var err error retry := true @@ -77,15 +129,22 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { var conn *pgx.Conn var gotIt bool if pool.disableThrottling { + pool.connLock.Lock() + pool.applySizeChangeRequest() conn = <-pool.conns + pool.connLock.Unlock() } else { + pool.connLock.Lock() + pool.applySizeChangeRequest() conn, gotIt = <-pool.conns if !gotIt { + pool.connLock.Unlock() // The following sleep is intentional. It is added so that voyager does not // overwhelm the database. See the description in PR https://github.com/yugabyte/yb-voyager/pull/920 . time.Sleep(2 * time.Second) continue } + pool.connLock.Unlock() } if conn == nil { conn, err = pool.createNewConnection() diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index a799536db..b466b90f3 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -222,6 +222,7 @@ func (yb *TargetYugabyteDB) InitConnPool() error { params := &ConnectionParams{ NumConnections: yb.tconf.Parallelism, + NumMaxConnections: yb.tconf.Parallelism * 2, ConnUriList: targetUriList, SessionInitScript: getYBSessionInitScript(yb.tconf), } @@ -1193,11 +1194,11 @@ func (yb *TargetYugabyteDB) GetClusterMetrics() (map[string]map[string]string, e } func (yb *TargetYugabyteDB) GetNumConnectionsInPool() int { - return 0 + return yb.connPool.GetNumConnections() } func (yb *TargetYugabyteDB) UpdateNumConnectionsInPool(newSize int) bool { - return true + return yb.connPool.UpdateNumConnections(newSize) } func (yb *TargetYugabyteDB) ClearMigrationState(migrationUUID uuid.UUID, exportDir string) error { From d54e249a280ed47f4c2b562fcdf12157a0a4fd20 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Thu, 26 Sep 2024 15:48:34 +0530 Subject: [PATCH 04/33] proper setting of max parallelism in the batch import pool as well --- yb-voyager/cmd/importData.go | 9 ++++++++- .../src/adaptiveparallelism/adaptive_parallelism.go | 1 + yb-voyager/src/tgtdb/yugabytedb.go | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/yb-voyager/cmd/importData.go b/yb-voyager/cmd/importData.go index 9e6954b80..92eabe88d 100644 --- a/yb-voyager/cmd/importData.go +++ b/yb-voyager/cmd/importData.go @@ -56,6 +56,7 @@ var tablesProgressMetadata map[string]*utils.TableProgressMetadata var importerRole string var identityColumnsMetaDBKey string var importPhase string +var enableAdaptiveParallelism bool // stores the data files description in a struct var dataFileDescriptor *datafile.Descriptor @@ -437,7 +438,8 @@ func importData(importFileTasks []*ImportFileTask) { utils.ErrExit("Failed to initialize the target DB connection pool: %s", err) } utils.PrintAndLog("Using %d parallel jobs.", tconf.Parallelism) - if importerRole == TARGET_DB_IMPORTER_ROLE || importerRole == IMPORT_FILE_ROLE { + enableAdaptiveParallelism = true + if enableAdaptiveParallelism { yb, ok := tdb.(*tgtdb.TargetYugabyteDB) if !ok { utils.ErrExit("adaptive parallelism is only supported if target DB is YugabyteDB") @@ -491,6 +493,10 @@ func importData(importFileTasks []*ImportFileTask) { utils.PrintAndLog("Tables to import: %v", importFileTasksToTableNames(pendingTasks)) prepareTableToColumns(pendingTasks) //prepare the tableToColumns map poolSize := tconf.Parallelism * 2 + if enableAdaptiveParallelism { + yb := tdb.(*tgtdb.TargetYugabyteDB) + poolSize = yb.GetNumMaxConnectionsInPool() * 2 + } progressReporter := NewImportDataProgressReporter(bool(disablePb)) if importerRole == TARGET_DB_IMPORTER_ROLE { @@ -502,6 +508,7 @@ func importData(importFileTasks []*ImportFileTask) { // The code can produce `poolSize` number of batches at a time. But, it can consume only // `parallelism` number of batches at a time. batchImportPool = pool.New().WithMaxGoroutines(poolSize) + log.Info("created batch import pool of size: ", poolSize) totalProgressAmount := getTotalProgressAmount(task) progressReporter.ImportFileStarted(task, totalProgressAmount) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index 75625b4e9..1311d20c3 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -33,6 +33,7 @@ type TargetYugabyteDBWithConnectionPool interface { IsAdaptiveParallelismSupported() bool GetClusterMetrics() (map[string]map[string]string, error) // node_uuid:metric_name:metric_value GetNumConnectionsInPool() int + GetNumMaxConnectionsInPool() int UpdateNumConnectionsInPool(int) bool } diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index b466b90f3..1fdef891a 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -227,6 +227,7 @@ func (yb *TargetYugabyteDB) InitConnPool() error { SessionInitScript: getYBSessionInitScript(yb.tconf), } yb.connPool = NewConnectionPool(params) + log.Info("Initialized connection pool with settings: ", spew.Sdump(params)) return nil } @@ -1197,6 +1198,10 @@ func (yb *TargetYugabyteDB) GetNumConnectionsInPool() int { return yb.connPool.GetNumConnections() } +func (yb *TargetYugabyteDB) GetNumMaxConnectionsInPool() int { + return yb.connPool.params.NumMaxConnections +} + func (yb *TargetYugabyteDB) UpdateNumConnectionsInPool(newSize int) bool { return yb.connPool.UpdateNumConnections(newSize) } From d70f58f0d5df46054bcc705004cbce97b22f407f Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Fri, 27 Sep 2024 16:03:58 +0530 Subject: [PATCH 05/33] new implementation wip --- .../adaptive_parallelism.go | 14 +- yb-voyager/src/tgtdb/conn_pool.go | 137 ++++++++++++------ yb-voyager/src/tgtdb/yugabytedb.go | 4 +- 3 files changed, 102 insertions(+), 53 deletions(-) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index 1311d20c3..23b05f05f 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -34,7 +34,7 @@ type TargetYugabyteDBWithConnectionPool interface { GetClusterMetrics() (map[string]map[string]string, error) // node_uuid:metric_name:metric_value GetNumConnectionsInPool() int GetNumMaxConnectionsInPool() int - UpdateNumConnectionsInPool(int) bool + UpdateNumConnectionsInPool(int) error } func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { @@ -58,15 +58,15 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { if maxCpuUsage > MAX_CPU_THRESHOLD { utils.PrintAndLog("PARALLELISM: found CPU usage = %d > %d, reducing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()-1) - updated := yb.UpdateNumConnectionsInPool(yb.GetNumConnectionsInPool() - 1) - if !updated { - utils.PrintAndLog("PARALLELISM: no update. pending change request or change out of bounds") + err = yb.UpdateNumConnectionsInPool(-1) + if err != nil { + utils.PrintAndLog("PARALLELISM: error updating parallelism: %v", err) } } else { utils.PrintAndLog("PARALLELISM: found CPU usage = %d <= %d, increasing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()+1) - updated := yb.UpdateNumConnectionsInPool(yb.GetNumConnectionsInPool() + 1) - if !updated { - utils.PrintAndLog("PARALLELISM: no update. pending change request or change out of bounds") + err := yb.UpdateNumConnectionsInPool(1) + if err != nil { + utils.PrintAndLog("PARALLELISM: error updating parallelism: %v", err) } } time.Sleep(10 * time.Second) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index d6c333bbf..1f6c50b00 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -50,8 +50,10 @@ type ConnectionPool struct { nextUriIndex int disableThrottling bool size int // current size of the pool - sizeChangeRequests chan int - connLock sync.Mutex + pendingConnsToClose int + pendingConnsToCloseLock sync.Mutex + // sizeChangeRequests chan int + // connLock sync.Mutex } func NewConnectionPool(params *ConnectionParams) *ConnectionPool { @@ -62,7 +64,8 @@ func NewConnectionPool(params *ConnectionParams) *ConnectionPool { connIdToPreparedStmtCache: make(map[uint32]map[string]bool, params.NumMaxConnections), disableThrottling: false, size: params.NumConnections, - sizeChangeRequests: make(chan int, 1), //only allow one change request. + pendingConnsToClose: 0, + // sizeChangeRequests: make(chan int, 1), //only allow one change request. } for i := 0; i < params.NumMaxConnections; i++ { pool.idleConns <- nil @@ -78,48 +81,82 @@ func NewConnectionPool(params *ConnectionParams) *ConnectionPool { } func (pool *ConnectionPool) GetNumConnections() int { - return pool.size + pool.pendingConnsToCloseLock.Lock() + defer pool.pendingConnsToCloseLock.Unlock() + return pool.size - pool.pendingConnsToClose } -func (pool *ConnectionPool) UpdateNumConnections(newSize int) bool { - if newSize < 1 || newSize > pool.params.NumMaxConnections { - return false +func (pool *ConnectionPool) UpdateNumConnections(delta int) error { + pool.pendingConnsToCloseLock.Lock() + defer pool.pendingConnsToCloseLock.Unlock() + + effectiveSize := pool.size - pool.pendingConnsToClose + newEffectiveSize := effectiveSize + delta + + if newEffectiveSize < 1 || newEffectiveSize > pool.params.NumMaxConnections { + return fmt.Errorf("invalid new pool size %d. "+ + "Must be between 1 and %d", newEffectiveSize, pool.params.NumMaxConnections) } - select { - case pool.sizeChangeRequests <- newSize: - return true - default: - return false + + if delta == 0 { + utils.PrintAndLog("PARALLELISM: No change in pool size. Current size is %d", pool.size) + return nil } + if delta > 0 { + if pool.pendingConnsToClose >= 0 { + // since we are increasing, we can just reduce the pending close count + if pool.pendingConnsToClose > delta { + pool.pendingConnsToClose -= delta + } else { + delta -= pool.pendingConnsToClose + pool.pendingConnsToClose = 0 + } + } + for i := 0; i < delta; i++ { + conn := <-pool.idleConns + pool.conns <- conn + } + pool.size = newEffectiveSize + utils.PrintAndLog("PARALLELISM: Added %d new connections. Pool size is now %d", delta, pool.size) + } else { + pool.pendingConnsToClose += -delta + } + return nil + // select { + // case pool.sizeChangeRequests <- newSize: + // return true + // default: + // return false + // } } func (pool *ConnectionPool) DisableThrottling() { pool.disableThrottling = true } -func (pool *ConnectionPool) applySizeChangeRequest() { - select { - case newSize := <-pool.sizeChangeRequests: - if newSize > pool.size { - for i := 0; i < newSize-pool.size; i++ { - conn := <-pool.idleConns - pool.conns <- conn - } - } else if newSize < pool.size { - for i := 0; i < pool.size-newSize; i++ { - conn := <-pool.conns - pool.idleConns <- conn - // if conn != nil { - // conn.Close(context.Background()) - // } - } - } - oldSize := pool.size - pool.size = newSize - utils.PrintAndLog("PARALLELISM: Updated pool size from %d to %d", oldSize, newSize) - default: - } -} +// func (pool *ConnectionPool) applySizeChangeRequest() { +// select { +// case newSize := <-pool.sizeChangeRequests: +// if newSize > pool.size { +// for i := 0; i < newSize-pool.size; i++ { +// conn := <-pool.idleConns +// pool.conns <- conn +// } +// } else if newSize < pool.size { +// for i := 0; i < pool.size-newSize; i++ { +// conn := <-pool.conns +// pool.idleConns <- conn +// // if conn != nil { +// // conn.Close(context.Background()) +// // } +// } +// } +// oldSize := pool.size +// pool.size = newSize +// utils.PrintAndLog("PARALLELISM: Updated pool size from %d to %d", oldSize, newSize) +// default: +// } +// } func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { var err error @@ -129,22 +166,15 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { var conn *pgx.Conn var gotIt bool if pool.disableThrottling { - pool.connLock.Lock() - pool.applySizeChangeRequest() conn = <-pool.conns - pool.connLock.Unlock() } else { - pool.connLock.Lock() - pool.applySizeChangeRequest() conn, gotIt = <-pool.conns if !gotIt { - pool.connLock.Unlock() // The following sleep is intentional. It is added so that voyager does not // overwhelm the database. See the description in PR https://github.com/yugabyte/yb-voyager/pull/920 . time.Sleep(2 * time.Second) continue } - pool.connLock.Unlock() } if conn == nil { conn, err = pool.createNewConnection() @@ -161,9 +191,28 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { // assuming PID will still be available delete(pool.connIdToPreparedStmtCache, conn.PgConn().PID()) pool.Unlock() - pool.conns <- nil + + pool.pendingConnsToCloseLock.Lock() + if pool.pendingConnsToClose > 0 { + pool.pendingConnsToClose-- + pool.size-- + pool.idleConns <- nil + utils.PrintAndLog("PARALLELISM: Connection moved to idle pool. New size: %d", pool.size) + } else { + pool.conns <- nil + } + pool.pendingConnsToCloseLock.Unlock() } else { - pool.conns <- conn + pool.pendingConnsToCloseLock.Lock() + if pool.pendingConnsToClose > 0 { + pool.pendingConnsToClose-- + pool.size-- + pool.idleConns <- conn + utils.PrintAndLog("PARALLELISM: Connection moved to idle pool. New size: %d", pool.size) + } else { + pool.conns <- conn + } + pool.pendingConnsToCloseLock.Unlock() } } diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 1fdef891a..4463a2f36 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -1202,8 +1202,8 @@ func (yb *TargetYugabyteDB) GetNumMaxConnectionsInPool() int { return yb.connPool.params.NumMaxConnections } -func (yb *TargetYugabyteDB) UpdateNumConnectionsInPool(newSize int) bool { - return yb.connPool.UpdateNumConnections(newSize) +func (yb *TargetYugabyteDB) UpdateNumConnectionsInPool(delta int) error { + return yb.connPool.UpdateNumConnections(delta) } func (yb *TargetYugabyteDB) ClearMigrationState(migrationUUID uuid.UUID, exportDir string) error { From 103fd00c01da8db2f8c737d19758ccf118dccd21 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Fri, 27 Sep 2024 16:09:39 +0530 Subject: [PATCH 06/33] fix --- .../data/gather-assessment-metadata.tar.gz | Bin 9278 -> 9227 bytes yb-voyager/src/tgtdb/conn_pool.go | 50 +++--------------- 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index 7be29d652e629334f8a5cd5e4cfc672c264ef73c..0bfa456f6465bcb4b0c9a4c458e845a4f9c04c02 100644 GIT binary patch literal 9227 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 literal 9278 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 diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index 1f6c50b00..71cedcd9e 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -81,21 +81,18 @@ func NewConnectionPool(params *ConnectionParams) *ConnectionPool { } func (pool *ConnectionPool) GetNumConnections() int { - pool.pendingConnsToCloseLock.Lock() - defer pool.pendingConnsToCloseLock.Unlock() - return pool.size - pool.pendingConnsToClose + return pool.size } func (pool *ConnectionPool) UpdateNumConnections(delta int) error { pool.pendingConnsToCloseLock.Lock() defer pool.pendingConnsToCloseLock.Unlock() - effectiveSize := pool.size - pool.pendingConnsToClose - newEffectiveSize := effectiveSize + delta + newSize := pool.size + delta - if newEffectiveSize < 1 || newEffectiveSize > pool.params.NumMaxConnections { + if newSize < 1 || newSize > pool.params.NumMaxConnections { return fmt.Errorf("invalid new pool size %d. "+ - "Must be between 1 and %d", newEffectiveSize, pool.params.NumMaxConnections) + "Must be between 1 and %d", newSize, pool.params.NumMaxConnections) } if delta == 0 { @@ -116,48 +113,19 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { conn := <-pool.idleConns pool.conns <- conn } - pool.size = newEffectiveSize + utils.PrintAndLog("PARALLELISM: Added %d new connections. Pool size is now %d", delta, pool.size) } else { pool.pendingConnsToClose += -delta } + pool.size = newSize return nil - // select { - // case pool.sizeChangeRequests <- newSize: - // return true - // default: - // return false - // } } func (pool *ConnectionPool) DisableThrottling() { pool.disableThrottling = true } -// func (pool *ConnectionPool) applySizeChangeRequest() { -// select { -// case newSize := <-pool.sizeChangeRequests: -// if newSize > pool.size { -// for i := 0; i < newSize-pool.size; i++ { -// conn := <-pool.idleConns -// pool.conns <- conn -// } -// } else if newSize < pool.size { -// for i := 0; i < pool.size-newSize; i++ { -// conn := <-pool.conns -// pool.idleConns <- conn -// // if conn != nil { -// // conn.Close(context.Background()) -// // } -// } -// } -// oldSize := pool.size -// pool.size = newSize -// utils.PrintAndLog("PARALLELISM: Updated pool size from %d to %d", oldSize, newSize) -// default: -// } -// } - func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { var err error retry := true @@ -195,9 +163,8 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { pool.pendingConnsToCloseLock.Lock() if pool.pendingConnsToClose > 0 { pool.pendingConnsToClose-- - pool.size-- pool.idleConns <- nil - utils.PrintAndLog("PARALLELISM: Connection moved to idle pool. New size: %d", pool.size) + utils.PrintAndLog("PARALLELISM: Connection moved to idle pool.") } else { pool.conns <- nil } @@ -206,9 +173,8 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { pool.pendingConnsToCloseLock.Lock() if pool.pendingConnsToClose > 0 { pool.pendingConnsToClose-- - pool.size-- pool.idleConns <- conn - utils.PrintAndLog("PARALLELISM: Connection moved to idle pool. New size: %d", pool.size) + utils.PrintAndLog("PARALLELISM: Connection moved to idle pool") } else { pool.conns <- conn } From ee77137a82880deeaa3dcbb8b513d765e38db7f3 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 11:01:42 +0530 Subject: [PATCH 07/33] error handling --- yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index 23b05f05f..35939f192 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -42,10 +42,12 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { return fmt.Errorf("adaptive parallelism not supported in target YB database.") } for { + time.Sleep(10 * time.Second) utils.PrintAndLog("--------------------------------------------------------") clusterMetrics, err := yb.GetClusterMetrics() if err != nil { utils.PrintAndLog("error getting cluster metrics: %v", err) + continue } // utils.PrintAndLog("PARALLELISM: cluster metrics: %v", clusterMetrics) @@ -69,7 +71,7 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { utils.PrintAndLog("PARALLELISM: error updating parallelism: %v", err) } } - time.Sleep(10 * time.Second) + } return nil } From 1605fc3d4bd31bc22b4ef020ca73378f01db8014 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 11:30:08 +0530 Subject: [PATCH 08/33] add flags --- yb-voyager/cmd/import.go | 19 ++++++++++++++++++ yb-voyager/cmd/importData.go | 9 +++++---- yb-voyager/cmd/importDataFileCommand.go | 1 + yb-voyager/cmd/importDataState.go | 5 +++-- .../data/gather-assessment-metadata.tar.gz | Bin 9227 -> 9227 bytes yb-voyager/src/tgtdb/tconf.go | 2 ++ yb-voyager/src/tgtdb/yugabytedb.go | 11 +++++++++- 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/yb-voyager/cmd/import.go b/yb-voyager/cmd/import.go index d8d859e1a..8a689c22f 100644 --- a/yb-voyager/cmd/import.go +++ b/yb-voyager/cmd/import.go @@ -89,6 +89,7 @@ func validateImportFlags(cmd *cobra.Command, importerRole string) error { case SOURCE_DB_IMPORTER_ROLE: getSourceDBPassword(cmd) } + validateParallelismFlags() return nil } @@ -345,6 +346,11 @@ func registerFlagsForTarget(cmd *cobra.Command) { "number of cores N and use N/4 as parallel jobs. "+ "Otherwise, it fall back to using twice the number of nodes in the cluster. "+ "Any value less than 1 reverts to the default calculation.") + BoolVar(cmd.Flags(), &tconf.EnableAdaptiveParallelism, "enable-adaptive-parallelism", false, + "Adapt parallelism based on the resource usage (CPU, memory) of the target YugabyteDB cluster") + cmd.Flags().IntVar(&tconf.MaxParallelism, "adaptive-parallelism-max", 0, + "number of max parallel jobs to use while importing data when adaptive parallelism is enabled."+ + "By default, voyager will try if it can determine the total number of cores N and use N/2 as the max parallel jobs. ") } func registerFlagsForSourceReplica(cmd *cobra.Command) { @@ -387,3 +393,16 @@ func validateFFDBSchemaFlag() { utils.ErrExit("Error: --source-replica-db-schema flag is mandatory for import data to source-replica") } } + +func validateParallelismFlags() { + if tconf.EnableAdaptiveParallelism { + if tconf.Parallelism > 0 { + utils.ErrExit("Error: --parallel-jobs flag cannot be used with --enable-adaptive-parallelism flag") + } + } + if tconf.MaxParallelism > 0 { + if !tconf.EnableAdaptiveParallelism { + utils.ErrExit("Error: --adaptive-parallelism-max flag can only be used with --enable-adaptive-parallelism true") + } + } +} diff --git a/yb-voyager/cmd/importData.go b/yb-voyager/cmd/importData.go index 92eabe88d..aa0e48188 100644 --- a/yb-voyager/cmd/importData.go +++ b/yb-voyager/cmd/importData.go @@ -56,7 +56,6 @@ var tablesProgressMetadata map[string]*utils.TableProgressMetadata var importerRole string var identityColumnsMetaDBKey string var importPhase string -var enableAdaptiveParallelism bool // stores the data files description in a struct var dataFileDescriptor *datafile.Descriptor @@ -438,8 +437,7 @@ func importData(importFileTasks []*ImportFileTask) { utils.ErrExit("Failed to initialize the target DB connection pool: %s", err) } utils.PrintAndLog("Using %d parallel jobs.", tconf.Parallelism) - enableAdaptiveParallelism = true - if enableAdaptiveParallelism { + if tconf.EnableAdaptiveParallelism { yb, ok := tdb.(*tgtdb.TargetYugabyteDB) if !ok { utils.ErrExit("adaptive parallelism is only supported if target DB is YugabyteDB") @@ -459,8 +457,10 @@ func importData(importFileTasks []*ImportFileTask) { var pendingTasks, completedTasks []*ImportFileTask state := NewImportDataState(exportDir) if startClean { + utils.PrintAndLog("cleaning import state") cleanImportState(state, importFileTasks) pendingTasks = importFileTasks + utils.PrintAndLog("import state cleaned") } else { pendingTasks, completedTasks, err = classifyTasks(state, importFileTasks) if err != nil { @@ -474,6 +474,7 @@ func importData(importFileTasks []*ImportFileTask) { if msr.SourceDBConf != nil { source = *msr.SourceDBConf } + utils.PrintAndLog("getting import table list") importTableList, err := getImportTableList(sourceTableList) if err != nil { utils.ErrExit("Error generating table list to import: %v", err) @@ -493,7 +494,7 @@ func importData(importFileTasks []*ImportFileTask) { utils.PrintAndLog("Tables to import: %v", importFileTasksToTableNames(pendingTasks)) prepareTableToColumns(pendingTasks) //prepare the tableToColumns map poolSize := tconf.Parallelism * 2 - if enableAdaptiveParallelism { + if tconf.EnableAdaptiveParallelism { yb := tdb.(*tgtdb.TargetYugabyteDB) poolSize = yb.GetNumMaxConnectionsInPool() * 2 } diff --git a/yb-voyager/cmd/importDataFileCommand.go b/yb-voyager/cmd/importDataFileCommand.go index da5f9fe70..61694c513 100644 --- a/yb-voyager/cmd/importDataFileCommand.go +++ b/yb-voyager/cmd/importDataFileCommand.go @@ -207,6 +207,7 @@ func checkImportDataFileFlags(cmd *cobra.Command) { getTargetPassword(cmd) validateTargetPortRange() validateTargetSchemaFlag() + validateParallelismFlags() } func checkFileFormat() { diff --git a/yb-voyager/cmd/importDataState.go b/yb-voyager/cmd/importDataState.go index 112d7ad3a..5dd24a44f 100644 --- a/yb-voyager/cmd/importDataState.go +++ b/yb-voyager/cmd/importDataState.go @@ -175,11 +175,12 @@ func (s *ImportDataState) Clean(filePath string, tableNameTup sqlname.NameTuple) if err != nil { return fmt.Errorf("error while removing %q: %w", fileStateDir, err) } - + utils.PrintAndLog("cleaning import state from db") err = s.cleanFileImportStateFromDB(filePath, tableNameTup) if err != nil { return fmt.Errorf("error while cleaning file import state for %q: %w", tableNameTup, err) } + utils.PrintAndLog("cleaned import state from db") return nil } @@ -628,7 +629,7 @@ func (s *ImportDataState) GetImportedEventsStatsForTableList(tableNameTupList [] return nil, fmt.Errorf("error in getting import stats from target db: %w", err) } defer rows.Close() - + for rows.Next() { var eventCounter tgtdb.EventCounter var tableName string diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index 0bfa456f6465bcb4b0c9a4c458e845a4f9c04c02..03ba0361e4edd5b5eca95d18ea7ec87224d1b4e3 100644 GIT binary patch delta 16 XcmeD7==NZj@8)3GXZ~v=JBtbcE&K&9 delta 16 XcmeD7==NZj@8)0->-x5lokaxzD?$X; diff --git a/yb-voyager/src/tgtdb/tconf.go b/yb-voyager/src/tgtdb/tconf.go index 23892a83f..8079217f2 100644 --- a/yb-voyager/src/tgtdb/tconf.go +++ b/yb-voyager/src/tgtdb/tconf.go @@ -54,6 +54,8 @@ type TargetConf struct { EnableUpsert utils.BoolStr `json:"enable_upsert"` DisableTransactionalWrites utils.BoolStr `json:"disable_transactional_writes"` Parallelism int `json:"parallelism"` + EnableAdaptiveParallelism utils.BoolStr `json:"enable_adaptive_parallelism"` + MaxParallelism int `json:"max_parallelism"` // in case adaptive parallelism is enabled. } func (t *TargetConf) Clone() *TargetConf { diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 4463a2f36..43ec92403 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -220,9 +220,18 @@ func (yb *TargetYugabyteDB) InitConnPool() error { log.Infof("Using %d parallel jobs by default. Use --parallel-jobs to specify a custom value", yb.tconf.Parallelism) } + if yb.tconf.EnableAdaptiveParallelism { + if yb.tconf.MaxParallelism <= 0 { + yb.tconf.MaxParallelism = yb.tconf.Parallelism * 2 + } else { + yb.tconf.MaxParallelism = yb.tconf.MaxParallelism + } + } else { + yb.tconf.MaxParallelism = yb.tconf.Parallelism + } params := &ConnectionParams{ NumConnections: yb.tconf.Parallelism, - NumMaxConnections: yb.tconf.Parallelism * 2, + NumMaxConnections: yb.tconf.MaxParallelism, ConnUriList: targetUriList, SessionInitScript: getYBSessionInitScript(yb.tconf), } From 6776cc49879a091dd4d19fcbdde04cd8a93fe599 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 12:35:50 +0530 Subject: [PATCH 09/33] minor fixes --- yb-voyager/cmd/importData.go | 2 +- .../adaptive_parallelism.go | 2 +- .../data/gather-assessment-metadata.tar.gz | Bin 9227 -> 9227 bytes yb-voyager/src/tgtdb/conn_pool.go | 2 +- yb-voyager/src/tgtdb/yugabytedb.go | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yb-voyager/cmd/importData.go b/yb-voyager/cmd/importData.go index aa0e48188..d28bd7e91 100644 --- a/yb-voyager/cmd/importData.go +++ b/yb-voyager/cmd/importData.go @@ -509,7 +509,7 @@ func importData(importFileTasks []*ImportFileTask) { // The code can produce `poolSize` number of batches at a time. But, it can consume only // `parallelism` number of batches at a time. batchImportPool = pool.New().WithMaxGoroutines(poolSize) - log.Info("created batch import pool of size: ", poolSize) + utils.PrintAndLog("created batch import pool of size: ", poolSize) totalProgressAmount := getTotalProgressAmount(task) progressReporter.ImportFileStarted(task, totalProgressAmount) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index 35939f192..38c841ee7 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -26,7 +26,7 @@ import ( const ( CPU_USAGE_USER = "cpu_usage_user" CPU_USAGE_SYSTEM = "cpu_usage_system" - MAX_CPU_THRESHOLD = 70 + MAX_CPU_THRESHOLD = 100 ) type TargetYugabyteDBWithConnectionPool interface { diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index 03ba0361e4edd5b5eca95d18ea7ec87224d1b4e3..d8be8a0b1b273eff20b05ebc4c7d9de6ee1c9761 100644 GIT binary patch delta 15 WcmeD7==NZf@8)30wA;wWssaEb-UH?U delta 15 WcmeD7==NZf@8)3GXTFh*RRsVgxdb!- diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index 71cedcd9e..ef215e761 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -114,7 +114,7 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { pool.conns <- conn } - utils.PrintAndLog("PARALLELISM: Added %d new connections. Pool size is now %d", delta, pool.size) + utils.PrintAndLog("PARALLELISM: Added %d new connections. Pool size is now %d", delta, newSize) } else { pool.pendingConnsToClose += -delta } diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 43ec92403..18dfe8d1f 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -236,7 +236,7 @@ func (yb *TargetYugabyteDB) InitConnPool() error { SessionInitScript: getYBSessionInitScript(yb.tconf), } yb.connPool = NewConnectionPool(params) - log.Info("Initialized connection pool with settings: ", spew.Sdump(params)) + utils.PrintAndLog("Initialized connection pool with settings: ", spew.Sdump(params)) return nil } From 71f00e27f61b153a9e55f671fa9c21c97350c55d Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 12:55:15 +0530 Subject: [PATCH 10/33] logs --- yb-voyager/cmd/importData.go | 6 ++--- yb-voyager/cmd/importDataState.go | 3 +-- .../adaptive_parallelism.go | 27 ++++++++++--------- yb-voyager/src/tgtdb/conn_pool.go | 16 +++++------ yb-voyager/src/tgtdb/yugabytedb.go | 5 ++-- 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/yb-voyager/cmd/importData.go b/yb-voyager/cmd/importData.go index d28bd7e91..956b6c596 100644 --- a/yb-voyager/cmd/importData.go +++ b/yb-voyager/cmd/importData.go @@ -457,10 +457,8 @@ func importData(importFileTasks []*ImportFileTask) { var pendingTasks, completedTasks []*ImportFileTask state := NewImportDataState(exportDir) if startClean { - utils.PrintAndLog("cleaning import state") cleanImportState(state, importFileTasks) pendingTasks = importFileTasks - utils.PrintAndLog("import state cleaned") } else { pendingTasks, completedTasks, err = classifyTasks(state, importFileTasks) if err != nil { @@ -474,7 +472,6 @@ func importData(importFileTasks []*ImportFileTask) { if msr.SourceDBConf != nil { source = *msr.SourceDBConf } - utils.PrintAndLog("getting import table list") importTableList, err := getImportTableList(sourceTableList) if err != nil { utils.ErrExit("Error generating table list to import: %v", err) @@ -495,6 +492,7 @@ func importData(importFileTasks []*ImportFileTask) { prepareTableToColumns(pendingTasks) //prepare the tableToColumns map poolSize := tconf.Parallelism * 2 if tconf.EnableAdaptiveParallelism { + // in case of adaptive parallelism, we need to use maxParalllelism * 2 yb := tdb.(*tgtdb.TargetYugabyteDB) poolSize = yb.GetNumMaxConnectionsInPool() * 2 } @@ -509,7 +507,7 @@ func importData(importFileTasks []*ImportFileTask) { // The code can produce `poolSize` number of batches at a time. But, it can consume only // `parallelism` number of batches at a time. batchImportPool = pool.New().WithMaxGoroutines(poolSize) - utils.PrintAndLog("created batch import pool of size: ", poolSize) + log.Info("created batch import pool of size: ", poolSize) totalProgressAmount := getTotalProgressAmount(task) progressReporter.ImportFileStarted(task, totalProgressAmount) diff --git a/yb-voyager/cmd/importDataState.go b/yb-voyager/cmd/importDataState.go index 5dd24a44f..459daa860 100644 --- a/yb-voyager/cmd/importDataState.go +++ b/yb-voyager/cmd/importDataState.go @@ -175,12 +175,11 @@ func (s *ImportDataState) Clean(filePath string, tableNameTup sqlname.NameTuple) if err != nil { return fmt.Errorf("error while removing %q: %w", fileStateDir, err) } - utils.PrintAndLog("cleaning import state from db") + err = s.cleanFileImportStateFromDB(filePath, tableNameTup) if err != nil { return fmt.Errorf("error while cleaning file import state for %q: %w", tableNameTup, err) } - utils.PrintAndLog("cleaned import state from db") return nil } diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index 38c841ee7..6425eb20c 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -20,13 +20,15 @@ import ( "strconv" "time" - "github.com/yugabyte/yb-voyager/yb-voyager/src/utils" + "github.com/davecgh/go-spew/spew" + log "github.com/sirupsen/logrus" ) const ( - CPU_USAGE_USER = "cpu_usage_user" - CPU_USAGE_SYSTEM = "cpu_usage_system" - MAX_CPU_THRESHOLD = 100 + CPU_USAGE_USER = "cpu_usage_user" + CPU_USAGE_SYSTEM = "cpu_usage_system" + MAX_CPU_THRESHOLD = 100 + ADAPTIVE_PARALLELISM_FREQUENCY = 10 * time.Second ) type TargetYugabyteDBWithConnectionPool interface { @@ -42,33 +44,32 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { return fmt.Errorf("adaptive parallelism not supported in target YB database.") } for { - time.Sleep(10 * time.Second) - utils.PrintAndLog("--------------------------------------------------------") + time.Sleep(ADAPTIVE_PARALLELISM_FREQUENCY) clusterMetrics, err := yb.GetClusterMetrics() + log.Infof("adaptive: clusterMetrics: %v", spew.Sdump(clusterMetrics)) if err != nil { - utils.PrintAndLog("error getting cluster metrics: %v", err) + log.Warnf("adaptive: error getting cluster metrics: %v", err) continue } - // utils.PrintAndLog("PARALLELISM: cluster metrics: %v", clusterMetrics) // max cpu maxCpuUsage, err := getMaxCpuUsageInCluster(clusterMetrics) if err != nil { return fmt.Errorf("getting max cpu usage in cluster: %w", err) } - utils.PrintAndLog("PARALLELISM: max cpu usage in cluster = %d", maxCpuUsage) + log.Infof("adaptive: max cpu usage in cluster = %d", maxCpuUsage) if maxCpuUsage > MAX_CPU_THRESHOLD { - utils.PrintAndLog("PARALLELISM: found CPU usage = %d > %d, reducing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()-1) + log.Infof("adaptive: found CPU usage = %d > %d, reducing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()-1) err = yb.UpdateNumConnectionsInPool(-1) if err != nil { - utils.PrintAndLog("PARALLELISM: error updating parallelism: %v", err) + log.Warnf("adaptive: error updating parallelism: %v", err) } } else { - utils.PrintAndLog("PARALLELISM: found CPU usage = %d <= %d, increasing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()+1) + log.Infof("adaptive: found CPU usage = %d <= %d, increasing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()+1) err := yb.UpdateNumConnectionsInPool(1) if err != nil { - utils.PrintAndLog("PARALLELISM: error updating parallelism: %v", err) + log.Warnf("adaptive: error updating parallelism: %v", err) } } diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index ef215e761..ea038c406 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -52,8 +52,6 @@ type ConnectionPool struct { size int // current size of the pool pendingConnsToClose int pendingConnsToCloseLock sync.Mutex - // sizeChangeRequests chan int - // connLock sync.Mutex } func NewConnectionPool(params *ConnectionParams) *ConnectionPool { @@ -65,7 +63,6 @@ func NewConnectionPool(params *ConnectionParams) *ConnectionPool { disableThrottling: false, size: params.NumConnections, pendingConnsToClose: 0, - // sizeChangeRequests: make(chan int, 1), //only allow one change request. } for i := 0; i < params.NumMaxConnections; i++ { pool.idleConns <- nil @@ -96,7 +93,7 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { } if delta == 0 { - utils.PrintAndLog("PARALLELISM: No change in pool size. Current size is %d", pool.size) + utils.PrintAndLog("adaptive: No change in pool size. Current size is %d", pool.size) return nil } if delta > 0 { @@ -114,9 +111,10 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { pool.conns <- conn } - utils.PrintAndLog("PARALLELISM: Added %d new connections. Pool size is now %d", delta, newSize) + log.Info("adaptive: Added %d new connections. Pool size is now %d", delta, newSize) } else { pool.pendingConnsToClose += -delta + log.Info("adaptive: registered request to close %d conns. Total pending conns to close=%d", -delta, pool.pendingConnsToClose) } pool.size = newSize return nil @@ -162,9 +160,9 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { pool.pendingConnsToCloseLock.Lock() if pool.pendingConnsToClose > 0 { - pool.pendingConnsToClose-- pool.idleConns <- nil - utils.PrintAndLog("PARALLELISM: Connection moved to idle pool.") + log.Info("adaptive: Closed and moved connection to idle pool because pendingConnsToClose = %d", pool.pendingConnsToClose) + pool.pendingConnsToClose-- } else { pool.conns <- nil } @@ -172,9 +170,9 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { } else { pool.pendingConnsToCloseLock.Lock() if pool.pendingConnsToClose > 0 { - pool.pendingConnsToClose-- pool.idleConns <- conn - utils.PrintAndLog("PARALLELISM: Connection moved to idle pool") + log.Info("adaptive: Moved connection to idle pool because pendingConnsToClose = %d", pool.pendingConnsToClose) + pool.pendingConnsToClose-- } else { pool.conns <- conn } diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 18dfe8d1f..78a91a2ab 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -223,8 +223,6 @@ func (yb *TargetYugabyteDB) InitConnPool() error { if yb.tconf.EnableAdaptiveParallelism { if yb.tconf.MaxParallelism <= 0 { yb.tconf.MaxParallelism = yb.tconf.Parallelism * 2 - } else { - yb.tconf.MaxParallelism = yb.tconf.MaxParallelism } } else { yb.tconf.MaxParallelism = yb.tconf.Parallelism @@ -236,7 +234,7 @@ func (yb *TargetYugabyteDB) InitConnPool() error { SessionInitScript: getYBSessionInitScript(yb.tconf), } yb.connPool = NewConnectionPool(params) - utils.PrintAndLog("Initialized connection pool with settings: ", spew.Sdump(params)) + log.Info("Initialized connection pool with settings: ", spew.Sdump(params)) return nil } @@ -1177,6 +1175,7 @@ func (yb *TargetYugabyteDB) isQueryResultNonEmpty(query string) bool { } func (yb *TargetYugabyteDB) IsAdaptiveParallelismSupported() bool { + // TODO: return true } From 9774b95c886328044bd134ed12dce0f54d4745d8 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 12:56:23 +0530 Subject: [PATCH 11/33] small fix --- yb-voyager/src/tgtdb/conn_pool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index ea038c406..7d371f302 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -93,7 +93,7 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { } if delta == 0 { - utils.PrintAndLog("adaptive: No change in pool size. Current size is %d", pool.size) + log.Infof("adaptive: No change in pool size. Current size is %d", pool.size) return nil } if delta > 0 { From 5325e2bd61201243d550a36b1a5d545aade3d896 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 12:59:14 +0530 Subject: [PATCH 12/33] hide flags --- yb-voyager/cmd/import.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yb-voyager/cmd/import.go b/yb-voyager/cmd/import.go index 8a689c22f..062f9af9d 100644 --- a/yb-voyager/cmd/import.go +++ b/yb-voyager/cmd/import.go @@ -348,9 +348,11 @@ func registerFlagsForTarget(cmd *cobra.Command) { "Any value less than 1 reverts to the default calculation.") BoolVar(cmd.Flags(), &tconf.EnableAdaptiveParallelism, "enable-adaptive-parallelism", false, "Adapt parallelism based on the resource usage (CPU, memory) of the target YugabyteDB cluster") + cmd.Flags().MarkHidden("enable-adaptive-parallelism") // not officially released cmd.Flags().IntVar(&tconf.MaxParallelism, "adaptive-parallelism-max", 0, "number of max parallel jobs to use while importing data when adaptive parallelism is enabled."+ "By default, voyager will try if it can determine the total number of cores N and use N/2 as the max parallel jobs. ") + cmd.Flags().MarkHidden("adaptive-parallelism-max") // not officially released } func registerFlagsForSourceReplica(cmd *cobra.Command) { From ff30b210b7ce9da374846ef580ec37108ce8bf07 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 13:01:50 +0530 Subject: [PATCH 13/33] IsAdaptiveParallelismSupported --- yb-voyager/src/tgtdb/yugabytedb.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 78a91a2ab..49bb84bfb 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -1175,8 +1175,8 @@ func (yb *TargetYugabyteDB) isQueryResultNonEmpty(query string) bool { } func (yb *TargetYugabyteDB) IsAdaptiveParallelismSupported() bool { - // TODO: - return true + query := "SELECT * FROM pg_proc WHERE proname='yb_servers_metrics'" + return yb.isQueryResultNonEmpty(query) } func (yb *TargetYugabyteDB) GetClusterMetrics() (map[string]map[string]string, error) { From 8f02d75e354e1869bb3a2f79a30ba5e6ea7aa6d8 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 13:06:02 +0530 Subject: [PATCH 14/33] minor fixes --- .../adaptive_parallelism.go | 6 ++---- .../data/gather-assessment-metadata.tar.gz | Bin 9227 -> 9227 bytes yb-voyager/src/tgtdb/conn_pool.go | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index 6425eb20c..a860a8509 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -27,7 +27,7 @@ import ( const ( CPU_USAGE_USER = "cpu_usage_user" CPU_USAGE_SYSTEM = "cpu_usage_system" - MAX_CPU_THRESHOLD = 100 + MAX_CPU_THRESHOLD = 70 ADAPTIVE_PARALLELISM_FREQUENCY = 10 * time.Second ) @@ -46,7 +46,7 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { for { time.Sleep(ADAPTIVE_PARALLELISM_FREQUENCY) clusterMetrics, err := yb.GetClusterMetrics() - log.Infof("adaptive: clusterMetrics: %v", spew.Sdump(clusterMetrics)) + log.Infof("adaptive: clusterMetrics: %v", spew.Sdump(clusterMetrics)) // TODO: move to debug? if err != nil { log.Warnf("adaptive: error getting cluster metrics: %v", err) continue @@ -72,9 +72,7 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { log.Warnf("adaptive: error updating parallelism: %v", err) } } - } - return nil } func getMaxCpuUsageInCluster(clusterMetrics map[string]map[string]string) (int, error) { diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index d8be8a0b1b273eff20b05ebc4c7d9de6ee1c9761..bed5342a3d93ee9c3a31b008e4db2a226524855f 100644 GIT binary patch delta 15 WcmeD7==NZf@8)257QB&-RRsViH3WD7 delta 15 WcmeD7==NZf@8)30wA;wWssaEb-UH?U diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index 7d371f302..bf4b7dbec 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -111,10 +111,10 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { pool.conns <- conn } - log.Info("adaptive: Added %d new connections. Pool size is now %d", delta, newSize) + log.Infof("adaptive: Added %d new connections. Pool size is now %d", delta, newSize) } else { pool.pendingConnsToClose += -delta - log.Info("adaptive: registered request to close %d conns. Total pending conns to close=%d", -delta, pool.pendingConnsToClose) + log.Infof("adaptive: registered request to close %d conns. Total pending conns to close=%d", -delta, pool.pendingConnsToClose) } pool.size = newSize return nil @@ -161,7 +161,7 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { pool.pendingConnsToCloseLock.Lock() if pool.pendingConnsToClose > 0 { pool.idleConns <- nil - log.Info("adaptive: Closed and moved connection to idle pool because pendingConnsToClose = %d", pool.pendingConnsToClose) + log.Infof("adaptive: Closed and moved connection to idle pool because pendingConnsToClose = %d", pool.pendingConnsToClose) pool.pendingConnsToClose-- } else { pool.conns <- nil @@ -171,7 +171,7 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { pool.pendingConnsToCloseLock.Lock() if pool.pendingConnsToClose > 0 { pool.idleConns <- conn - log.Info("adaptive: Moved connection to idle pool because pendingConnsToClose = %d", pool.pendingConnsToClose) + log.Infof("adaptive: Moved connection to idle pool because pendingConnsToClose = %d", pool.pendingConnsToClose) pool.pendingConnsToClose-- } else { pool.conns <- conn From a503a5ec22da2f3f1b03c323d5945da92cb34264 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 13:23:55 +0530 Subject: [PATCH 15/33] fix static check --- yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index a860a8509..b40e76493 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -41,7 +41,7 @@ type TargetYugabyteDBWithConnectionPool interface { func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { if !yb.IsAdaptiveParallelismSupported() { - return fmt.Errorf("adaptive parallelism not supported in target YB database.") + return fmt.Errorf("adaptive parallelism not supported in target YB database") } for { time.Sleep(ADAPTIVE_PARALLELISM_FREQUENCY) From 5c3f317e7a87bfaae85a4c42e241903d31d1f88e Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 13:35:54 +0530 Subject: [PATCH 16/33] fix fallf case --- yb-voyager/src/tgtdb/postgres.go | 1 + 1 file changed, 1 insertion(+) diff --git a/yb-voyager/src/tgtdb/postgres.go b/yb-voyager/src/tgtdb/postgres.go index 417d227e7..f4f823b8e 100644 --- a/yb-voyager/src/tgtdb/postgres.go +++ b/yb-voyager/src/tgtdb/postgres.go @@ -230,6 +230,7 @@ func (pg *TargetPostgreSQL) InitConnPool() error { params := &ConnectionParams{ NumConnections: pg.tconf.Parallelism, + NumMaxConnections: pg.tconf.Parallelism, ConnUriList: targetUriList, SessionInitScript: getYBSessionInitScript(pg.tconf), // works fine as we check the support of any session variable before using it in the script. From 2cdcdb76e2728afceddae69c46b24d7d8ad1a96d Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 14:56:15 +0530 Subject: [PATCH 17/33] docs --- .../src/adaptiveparallelism/adaptive_parallelism.go | 10 ++++++++-- yb-voyager/src/tgtdb/conn_pool.go | 12 +++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index b40e76493..bab754d72 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -36,7 +36,7 @@ type TargetYugabyteDBWithConnectionPool interface { GetClusterMetrics() (map[string]map[string]string, error) // node_uuid:metric_name:metric_value GetNumConnectionsInPool() int GetNumMaxConnectionsInPool() int - UpdateNumConnectionsInPool(int) error + UpdateNumConnectionsInPool(int) error // (delta) } func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { @@ -48,11 +48,17 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { clusterMetrics, err := yb.GetClusterMetrics() log.Infof("adaptive: clusterMetrics: %v", spew.Sdump(clusterMetrics)) // TODO: move to debug? if err != nil { + // we don't want to return here, just log the error and continue. log.Warnf("adaptive: error getting cluster metrics: %v", err) continue } - // max cpu + // get max CPU + // Note that right now, voyager ingests data into the target in parallel, + // but one table at a time. Therefore, in cases where there is a single tablet for a table, + // either due to pre-split or colocated table, it is possible that the load on the cluster + // will be uneven. Nevertheless, we still want to ensure that the cluster is not overloaded, + // therefore we use the max CPU usage across all nodes in the cluster. maxCpuUsage, err := getMaxCpuUsageInCluster(clusterMetrics) if err != nil { return fmt.Errorf("getting max cpu usage in cluster: %w", err) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index bf4b7dbec..a64badef2 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -97,6 +97,8 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { return nil } if delta > 0 { + // for increases, process them synchronously. + // If there is non-zero pendingConnsToClose, then we reduce that count. if pool.pendingConnsToClose >= 0 { // since we are increasing, we can just reduce the pending close count if pool.pendingConnsToClose > delta { @@ -106,13 +108,21 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { pool.pendingConnsToClose = 0 } } + // Additionally, pick conns from the idle pool, and add it to the main pool. for i := 0; i < delta; i++ { conn := <-pool.idleConns pool.conns <- conn } - log.Infof("adaptive: Added %d new connections. Pool size is now %d", delta, newSize) } else { + // for decreases, process them asynchronously. + // The problem with processing them synchronously is that we may have to wait for the + // connections to be returned to the pool. Not only that, this goroutine that is trying to + // update the pool size by reading from the channel is also competing with multiple + // other goroutines that are trying to ingest data. + // This might take significant time depending on the query execution time and the lock contention + // So, instead, we just register the request to close the connections, + // and the connections are returned to the idle pool when the query execution is done. pool.pendingConnsToClose += -delta log.Infof("adaptive: registered request to close %d conns. Total pending conns to close=%d", -delta, pool.pendingConnsToClose) } From 183c88001e9f52163ef7eb86b54282fc22aa1b4d Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Mon, 30 Sep 2024 15:23:21 +0530 Subject: [PATCH 18/33] tests --- .../adaptive_parallelism.go | 60 +++++----- .../adaptive_parallelism_test.go | 106 ++++++++++++++++++ 2 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 yb-voyager/src/adaptiveparallelism/adaptive_parallelism_test.go diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index bab754d72..f8bd5e7cb 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -45,40 +45,46 @@ func AdaptParallelism(yb TargetYugabyteDBWithConnectionPool) error { } for { time.Sleep(ADAPTIVE_PARALLELISM_FREQUENCY) - clusterMetrics, err := yb.GetClusterMetrics() - log.Infof("adaptive: clusterMetrics: %v", spew.Sdump(clusterMetrics)) // TODO: move to debug? + err := fetchClusterMetricsAndUpdateParallelism(yb) if err != nil { - // we don't want to return here, just log the error and continue. - log.Warnf("adaptive: error getting cluster metrics: %v", err) - continue + log.Warnf("adaptive: error updating parallelism: %v", err) } + } +} + +func fetchClusterMetricsAndUpdateParallelism(yb TargetYugabyteDBWithConnectionPool) error { + clusterMetrics, err := yb.GetClusterMetrics() + log.Infof("adaptive: clusterMetrics: %v", spew.Sdump(clusterMetrics)) // TODO: move to debug? + if err != nil { + return fmt.Errorf("getting cluster metrics: %w", err) + } - // get max CPU - // Note that right now, voyager ingests data into the target in parallel, - // but one table at a time. Therefore, in cases where there is a single tablet for a table, - // either due to pre-split or colocated table, it is possible that the load on the cluster - // will be uneven. Nevertheless, we still want to ensure that the cluster is not overloaded, - // therefore we use the max CPU usage across all nodes in the cluster. - maxCpuUsage, err := getMaxCpuUsageInCluster(clusterMetrics) + // get max CPU + // Note that right now, voyager ingests data into the target in parallel, + // but one table at a time. Therefore, in cases where there is a single tablet for a table, + // either due to pre-split or colocated table, it is possible that the load on the cluster + // will be uneven. Nevertheless, we still want to ensure that the cluster is not overloaded, + // therefore we use the max CPU usage across all nodes in the cluster. + maxCpuUsage, err := getMaxCpuUsageInCluster(clusterMetrics) + if err != nil { + return fmt.Errorf("getting max cpu usage in cluster: %w", err) + } + log.Infof("adaptive: max cpu usage in cluster = %d", maxCpuUsage) + + if maxCpuUsage > MAX_CPU_THRESHOLD { + log.Infof("adaptive: found CPU usage = %d > %d, reducing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()-1) + err = yb.UpdateNumConnectionsInPool(-1) if err != nil { - return fmt.Errorf("getting max cpu usage in cluster: %w", err) + return fmt.Errorf("updating parallelism with -1: %w", err) } - log.Infof("adaptive: max cpu usage in cluster = %d", maxCpuUsage) - - if maxCpuUsage > MAX_CPU_THRESHOLD { - log.Infof("adaptive: found CPU usage = %d > %d, reducing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()-1) - err = yb.UpdateNumConnectionsInPool(-1) - if err != nil { - log.Warnf("adaptive: error updating parallelism: %v", err) - } - } else { - log.Infof("adaptive: found CPU usage = %d <= %d, increasing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()+1) - err := yb.UpdateNumConnectionsInPool(1) - if err != nil { - log.Warnf("adaptive: error updating parallelism: %v", err) - } + } else { + log.Infof("adaptive: found CPU usage = %d <= %d, increasing parallelism to %d", maxCpuUsage, MAX_CPU_THRESHOLD, yb.GetNumConnectionsInPool()+1) + err := yb.UpdateNumConnectionsInPool(1) + if err != nil { + return fmt.Errorf("updating parallelism with +1 : %w", err) } } + return nil } func getMaxCpuUsageInCluster(clusterMetrics map[string]map[string]string) (int, error) { diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism_test.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism_test.go new file mode 100644 index 000000000..610749897 --- /dev/null +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism_test.go @@ -0,0 +1,106 @@ +/* +Copyright (c) YugabyteDB, 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 adaptiveparallelism + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +type dummyTargetYugabyteDB struct { + size int + maxSize int + cpuUsageUser1 float64 + cpuUsageSys1 float64 + cpuUsageUser2 float64 + cpuUsageSys2 float64 +} + +func (d *dummyTargetYugabyteDB) IsAdaptiveParallelismSupported() bool { + return true +} + +func (d *dummyTargetYugabyteDB) GetClusterMetrics() (map[string]map[string]string, error) { + result := make(map[string]map[string]string) + result["node1"] = make(map[string]string) + result["node1"]["cpu_usage_user"] = strconv.FormatFloat(d.cpuUsageUser1, 'f', -1, 64) + result["node1"]["cpu_usage_system"] = strconv.FormatFloat(d.cpuUsageSys1, 'f', -1, 64) + result["node2"] = make(map[string]string) + result["node2"]["cpu_usage_user"] = strconv.FormatFloat(d.cpuUsageUser2, 'f', -1, 64) + result["node2"]["cpu_usage_system"] = strconv.FormatFloat(d.cpuUsageSys2, 'f', -1, 64) + return result, nil +} + +func (d *dummyTargetYugabyteDB) GetNumConnectionsInPool() int { + return d.size +} + +func (d *dummyTargetYugabyteDB) GetNumMaxConnectionsInPool() int { + return d.maxSize +} + +func (d *dummyTargetYugabyteDB) UpdateNumConnectionsInPool(delta int) error { + d.size += delta + return nil +} + +func TestMaxCpuUsage(t *testing.T) { + yb := &dummyTargetYugabyteDB{ + size: 3, + maxSize: 6, + cpuUsageUser1: 0.5, + cpuUsageSys1: 0.1, + cpuUsageUser2: 0.1, + cpuUsageSys2: 0.1, + } + + clusterMetrics, _ := yb.GetClusterMetrics() + maxCpuUsage, err := getMaxCpuUsageInCluster(clusterMetrics) + assert.NoError(t, err) + assert.Equal(t, 60, maxCpuUsage) +} + +func TestIncreaseParallelism(t *testing.T) { + yb := &dummyTargetYugabyteDB{ + size: 3, + maxSize: 6, + cpuUsageUser1: 0.5, + cpuUsageSys1: 0.1, + cpuUsageUser2: 0.5, + cpuUsageSys2: 0.1, + } + + err := fetchClusterMetricsAndUpdateParallelism(yb) + assert.NoErrorf(t, err, "failed to fetch cluster metrics and update parallelism") + assert.Equal(t, 4, yb.GetNumConnectionsInPool()) +} + +func TestDecreaseParallelismBasedOnCpu(t *testing.T) { + yb := &dummyTargetYugabyteDB{ + size: 3, + maxSize: 6, + cpuUsageUser1: 0.8, // above threshold + cpuUsageSys1: 0.1, + cpuUsageUser2: 0.5, + cpuUsageSys2: 0.1, + } + + err := fetchClusterMetricsAndUpdateParallelism(yb) + assert.NoErrorf(t, err, "failed to fetch cluster metrics and update parallelism") + assert.Equal(t, 2, yb.GetNumConnectionsInPool()) +} From e2ff70b780602e8fcdf661ce6eb5d2fd407bc96d Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 1 Oct 2024 11:55:45 +0530 Subject: [PATCH 19/33] basic conn pool test --- yb-voyager/go.mod | 3 ++ yb-voyager/go.sum | 6 +++ yb-voyager/src/tgtdb/conn_pool_test.go | 71 ++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 yb-voyager/src/tgtdb/conn_pool_test.go diff --git a/yb-voyager/go.mod b/yb-voyager/go.mod index 1a4bb3ef5..34b3af391 100644 --- a/yb-voyager/go.mod +++ b/yb-voyager/go.mod @@ -41,8 +41,11 @@ require ( ) require ( + github.com/fergusstrange/embedded-postgres v1.29.0 // indirect github.com/jackc/puddle v1.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.9.0 // indirect ) diff --git a/yb-voyager/go.sum b/yb-voyager/go.sum index 6b2be4f61..e94834673 100644 --- a/yb-voyager/go.sum +++ b/yb-voyager/go.sum @@ -890,6 +890,8 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fergusstrange/embedded-postgres v1.29.0 h1:Uv8hdhoiaNMuH0w8UuGXDHr60VoAQPFdgx7Qf3bzXJM= +github.com/fergusstrange/embedded-postgres v1.29.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -1430,6 +1432,8 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linode/linodego v1.4.0/go.mod h1:PVsRxSlOiJyvG4/scTszpmZDTdgS+to3X6eS8pRrWI8= github.com/linode/linodego v1.12.0/go.mod h1:NJlzvlNtdMRRkXb0oN6UWzUkj6t+IBsyveHgZ5Ppjyk= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= @@ -1880,6 +1884,8 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= diff --git a/yb-voyager/src/tgtdb/conn_pool_test.go b/yb-voyager/src/tgtdb/conn_pool_test.go new file mode 100644 index 000000000..5790bb4e5 --- /dev/null +++ b/yb-voyager/src/tgtdb/conn_pool_test.go @@ -0,0 +1,71 @@ +/* +Copyright (c) YugabyteDB, 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 tgtdb + +import ( + "fmt" + "sync" + "testing" + "time" + + "github.com/jackc/pgx/v4" + "github.com/stretchr/testify/assert" + + embeddedpostgres "github.com/fergusstrange/embedded-postgres" +) + +func TestBasic(t *testing.T) { + // GIVEN: a conn pool of size 10. + size := 10 + postgres := embeddedpostgres.NewDatabase(embeddedpostgres.DefaultConfig(). + Username("postgres"). + Password("postgres"). + Database("test"). + Port(9876). + StartTimeout(45 * time.Second)) + err := postgres.Start() + assert.NoError(t, err) + defer postgres.Stop() + + connParams := &ConnectionParams{ + NumConnections: size, + NumMaxConnections: size, + ConnUriList: []string{fmt.Sprintf("postgresql://postgres:postgres@localhost:%d/test", 9876)}, + SessionInitScript: []string{}, + } + pool := NewConnectionPool(connParams) + assert.Equal(t, size, len(pool.conns)) + + // WHEN: multiple goroutines acquire connection, perform some operation + // and release connection back to pool + var wg sync.WaitGroup + for i := 0; i < 100; i++ { + wg.Add(1) + go dummyProcess(pool, 1, &wg) + } + wg.Wait() + + // THEN: all connections are released back to pool + assert.Equal(t, size, len(pool.conns)) +} + +func dummyProcess(pool *ConnectionPool, seconds int, wg *sync.WaitGroup) { + defer wg.Done() + _ = pool.WithConn(func(conn *pgx.Conn) (retry bool, err error) { + time.Sleep(time.Duration(seconds) * time.Second) + return false, nil + }) +} From f3a98ca5a04afe0821802c4f687b274d183044ab Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 1 Oct 2024 12:30:41 +0530 Subject: [PATCH 20/33] more tests --- yb-voyager/src/tgtdb/conn_pool_test.go | 73 +++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/yb-voyager/src/tgtdb/conn_pool_test.go b/yb-voyager/src/tgtdb/conn_pool_test.go index 5790bb4e5..5f73ab357 100644 --- a/yb-voyager/src/tgtdb/conn_pool_test.go +++ b/yb-voyager/src/tgtdb/conn_pool_test.go @@ -27,18 +27,34 @@ import ( embeddedpostgres "github.com/fergusstrange/embedded-postgres" ) -func TestBasic(t *testing.T) { - // GIVEN: a conn pool of size 10. - size := 10 +// var postgres *embeddedpostgres.EmbeddedPostgres + +func setupPostgres(t *testing.T) *embeddedpostgres.EmbeddedPostgres { postgres := embeddedpostgres.NewDatabase(embeddedpostgres.DefaultConfig(). Username("postgres"). Password("postgres"). Database("test"). Port(9876). - StartTimeout(45 * time.Second)) + StartTimeout(30 * time.Second)) err := postgres.Start() - assert.NoError(t, err) - defer postgres.Stop() + if err != nil { + t.Fatal(err) + } + return postgres +} + +func shutdownPostgres(postgres *embeddedpostgres.EmbeddedPostgres, t *testing.T) { + err := postgres.Stop() + if err != nil { + t.Fatal(err) + } +} + +func TestBasic(t *testing.T) { + postgres := setupPostgres(t) + defer shutdownPostgres(postgres, t) + // GIVEN: a conn pool of size 10. + size := 10 connParams := &ConnectionParams{ NumConnections: size, @@ -69,3 +85,48 @@ func dummyProcess(pool *ConnectionPool, seconds int, wg *sync.WaitGroup) { return false, nil }) } + +func TestIncreaseConnectionsUptoMax(t *testing.T) { + postgres := setupPostgres(t) + defer shutdownPostgres(postgres, t) + // GIVEN: a conn pool of size 10, with max 20 connections. + size := 10 + maxSize := 20 + + connParams := &ConnectionParams{ + NumConnections: size, + NumMaxConnections: maxSize, + ConnUriList: []string{fmt.Sprintf("postgresql://postgres:postgres@localhost:%d/test", 9876)}, + SessionInitScript: []string{}, + } + pool := NewConnectionPool(connParams) + assert.Equal(t, size, len(pool.conns)) + + // WHEN: multiple goroutines acquire connection, perform some operation + // and release connection back to pool + // WHEN: we keep increasing the connnections upto the max.. + + var wg sync.WaitGroup + wg.Add(1) + go func() { + for i := 0; i < maxSize-size; i++ { + err := pool.UpdateNumConnections(1) + assert.NoError(t, err) + time.Sleep(1 * time.Second) + assert.Equal(t, size+i+1, pool.size) // assert that size is increasing + } + // now that we will increase beyond maxSize, we should get an error. + err := pool.UpdateNumConnections(1) + assert.Error(t, err) + wg.Done() + }() + + for i := 0; i < 100; i++ { + wg.Add(1) + go dummyProcess(pool, 1, &wg) + } + wg.Wait() + + // THEN: we should have as many as maxSize connections in pool now. + assert.Equal(t, maxSize, len(pool.conns)) +} From c54af7d3c1e9effccbe83c390b972763f57bb4c8 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 1 Oct 2024 12:40:59 +0530 Subject: [PATCH 21/33] mintest --- yb-voyager/src/tgtdb/conn_pool_test.go | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/yb-voyager/src/tgtdb/conn_pool_test.go b/yb-voyager/src/tgtdb/conn_pool_test.go index 5f73ab357..56d9d40fe 100644 --- a/yb-voyager/src/tgtdb/conn_pool_test.go +++ b/yb-voyager/src/tgtdb/conn_pool_test.go @@ -130,3 +130,48 @@ func TestIncreaseConnectionsUptoMax(t *testing.T) { // THEN: we should have as many as maxSize connections in pool now. assert.Equal(t, maxSize, len(pool.conns)) } + +func TestDecreaseConnectionsUptoMin(t *testing.T) { + postgres := setupPostgres(t) + defer shutdownPostgres(postgres, t) + // GIVEN: a conn pool of size 10, with max 20 connections. + size := 10 + maxSize := 20 + + connParams := &ConnectionParams{ + NumConnections: size, + NumMaxConnections: maxSize, + ConnUriList: []string{fmt.Sprintf("postgresql://postgres:postgres@localhost:%d/test", 9876)}, + SessionInitScript: []string{}, + } + pool := NewConnectionPool(connParams) + assert.Equal(t, size, len(pool.conns)) + + // WHEN: multiple goroutines acquire connection, perform some operation + // and release connection back to pool + // WHEN: we keep decrease the connnections upto the minimum(1).. + + var wg sync.WaitGroup + wg.Add(1) + go func() { + for i := 0; i < size-1; i++ { + err := pool.UpdateNumConnections(-1) + assert.NoError(t, err) + time.Sleep(1 * time.Second) + assert.Equal(t, size-(i+1), pool.size) // assert that size is increasing + } + // now that we will decrease beyond 1, we should get an error. + err := pool.UpdateNumConnections(-1) + assert.Error(t, err) + wg.Done() + }() + + for i := 0; i < 100; i++ { + wg.Add(1) + go dummyProcess(pool, 1, &wg) + } + wg.Wait() + + // THEN: we should have as many as maxSize connections in pool now. + assert.Equal(t, 1, len(pool.conns)) +} From ac693db1947aff621b5c38781320250fa246236e Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 1 Oct 2024 13:31:09 +0530 Subject: [PATCH 22/33] bug fix; random test --- yb-voyager/src/tgtdb/conn_pool.go | 3 ++ yb-voyager/src/tgtdb/conn_pool_test.go | 52 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index a64badef2..abaf67f90 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -102,8 +102,11 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { if pool.pendingConnsToClose >= 0 { // since we are increasing, we can just reduce the pending close count if pool.pendingConnsToClose > delta { + log.Infof("adaptive: Decreasing pendingConnsToClose by %d", delta) pool.pendingConnsToClose -= delta + delta = 0 } else { + log.Infof("adaptive: Decreasing pendingConnsToClose to 0 by %d", pool.pendingConnsToClose) delta -= pool.pendingConnsToClose pool.pendingConnsToClose = 0 } diff --git a/yb-voyager/src/tgtdb/conn_pool_test.go b/yb-voyager/src/tgtdb/conn_pool_test.go index 56d9d40fe..d1353fd35 100644 --- a/yb-voyager/src/tgtdb/conn_pool_test.go +++ b/yb-voyager/src/tgtdb/conn_pool_test.go @@ -17,6 +17,7 @@ package tgtdb import ( "fmt" + "math/rand" "sync" "testing" "time" @@ -175,3 +176,54 @@ func TestDecreaseConnectionsUptoMin(t *testing.T) { // THEN: we should have as many as maxSize connections in pool now. assert.Equal(t, 1, len(pool.conns)) } + +func TestUpdateConnectionsRandom(t *testing.T) { + postgres := setupPostgres(t) + defer shutdownPostgres(postgres, t) + // GIVEN: a conn pool of size 10, with max 20 connections. + size := 10 + maxSize := 20 + + connParams := &ConnectionParams{ + NumConnections: size, + NumMaxConnections: maxSize, + ConnUriList: []string{fmt.Sprintf("postgresql://postgres:postgres@localhost:%d/test", 9876)}, + SessionInitScript: []string{}, + } + pool := NewConnectionPool(connParams) + assert.Equal(t, size, len(pool.conns)) + + // WHEN: multiple goroutines acquire connection, perform some operation + // and release connection back to pool + // WHEN: we keep increasing and decreasing the connnections randomly.. + + expectedFinalSize := size + var wg sync.WaitGroup + wg.Add(1) + go func(expectedFinalSize *int) { + // 100 random updates either increase or decrease + for i := 0; i < 10; i++ { + randomNumber := rand.Intn(11) - 5 // Generates a number between -5 and 5 + if pool.size+randomNumber < 1 || (pool.size+randomNumber > pool.params.NumMaxConnections) { + continue + } + // fmt.Printf("i=%d, updating by %d. New pool size expected = %d\n", i, randomNumber, *expectedFinalSize+randomNumber) + err := pool.UpdateNumConnections(randomNumber) + assert.NoError(t, err) + time.Sleep(100 * time.Millisecond) + *expectedFinalSize = *expectedFinalSize + randomNumber + assert.Equal(t, *expectedFinalSize, pool.size) // assert that size is increasing + } + // fmt.Printf("done updating. expectedFinalSize=%d\n", *expectedFinalSize) + wg.Done() + }(&expectedFinalSize) + + for i := 0; i < 100; i++ { + wg.Add(1) + go dummyProcess(pool, 1, &wg) + } + wg.Wait() + + // THEN: we should have as many as maxSize connections in pool now. + assert.Equal(t, expectedFinalSize, len(pool.conns)) +} From 886103d340d8d81dcc416e348dadfa9d83437c03 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 1 Oct 2024 14:10:02 +0530 Subject: [PATCH 23/33] test changes --- yb-voyager/src/tgtdb/conn_pool.go | 2 +- yb-voyager/src/tgtdb/conn_pool_test.go | 35 +++++++++++++++----------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index abaf67f90..28e7f7f54 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -184,7 +184,7 @@ func (pool *ConnectionPool) WithConn(fn func(*pgx.Conn) (bool, error)) error { pool.pendingConnsToCloseLock.Lock() if pool.pendingConnsToClose > 0 { pool.idleConns <- conn - log.Infof("adaptive: Moved connection to idle pool because pendingConnsToClose = %d", pool.pendingConnsToClose) + log.Infof("adaptive: Moved connection to idle pool because pendingConnsToClose = %d. main connection pool size=%d", pool.pendingConnsToClose, len(pool.conns)) pool.pendingConnsToClose-- } else { pool.conns <- conn diff --git a/yb-voyager/src/tgtdb/conn_pool_test.go b/yb-voyager/src/tgtdb/conn_pool_test.go index d1353fd35..59fd4dad4 100644 --- a/yb-voyager/src/tgtdb/conn_pool_test.go +++ b/yb-voyager/src/tgtdb/conn_pool_test.go @@ -71,7 +71,7 @@ func TestBasic(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) - go dummyProcess(pool, 1, &wg) + go dummyProcess(pool, 1000, &wg) } wg.Wait() @@ -79,10 +79,10 @@ func TestBasic(t *testing.T) { assert.Equal(t, size, len(pool.conns)) } -func dummyProcess(pool *ConnectionPool, seconds int, wg *sync.WaitGroup) { +func dummyProcess(pool *ConnectionPool, milliseconds int, wg *sync.WaitGroup) { defer wg.Done() _ = pool.WithConn(func(conn *pgx.Conn) (retry bool, err error) { - time.Sleep(time.Duration(seconds) * time.Second) + time.Sleep(time.Duration(milliseconds) * time.Millisecond) return false, nil }) } @@ -124,7 +124,7 @@ func TestIncreaseConnectionsUptoMax(t *testing.T) { for i := 0; i < 100; i++ { wg.Add(1) - go dummyProcess(pool, 1, &wg) + go dummyProcess(pool, 1000, &wg) } wg.Wait() @@ -169,11 +169,11 @@ func TestDecreaseConnectionsUptoMin(t *testing.T) { for i := 0; i < 100; i++ { wg.Add(1) - go dummyProcess(pool, 1, &wg) + go dummyProcess(pool, 1000, &wg) } wg.Wait() - // THEN: we should have as many as maxSize connections in pool now. + // THEN: we should have as many as 1 connections in pool now. assert.Equal(t, 1, len(pool.conns)) } @@ -202,28 +202,35 @@ func TestUpdateConnectionsRandom(t *testing.T) { wg.Add(1) go func(expectedFinalSize *int) { // 100 random updates either increase or decrease - for i := 0; i < 10; i++ { + for i := 0; i < 1000; i++ { randomNumber := rand.Intn(11) - 5 // Generates a number between -5 and 5 if pool.size+randomNumber < 1 || (pool.size+randomNumber > pool.params.NumMaxConnections) { continue } - // fmt.Printf("i=%d, updating by %d. New pool size expected = %d\n", i, randomNumber, *expectedFinalSize+randomNumber) + fmt.Printf("i=%d, updating by %d. New pool size expected = %d\n", i, randomNumber, *expectedFinalSize+randomNumber) err := pool.UpdateNumConnections(randomNumber) assert.NoError(t, err) - time.Sleep(100 * time.Millisecond) + time.Sleep(10 * time.Millisecond) *expectedFinalSize = *expectedFinalSize + randomNumber assert.Equal(t, *expectedFinalSize, pool.size) // assert that size is increasing } - // fmt.Printf("done updating. expectedFinalSize=%d\n", *expectedFinalSize) + fmt.Printf("done updating. expectedFinalSize=%d\n", *expectedFinalSize) wg.Done() }(&expectedFinalSize) - for i := 0; i < 100; i++ { + for i := 0; i < 1000; i++ { wg.Add(1) - go dummyProcess(pool, 1, &wg) + go dummyProcess(pool, 100, &wg) } wg.Wait() - // THEN: we should have as many as maxSize connections in pool now. - assert.Equal(t, expectedFinalSize, len(pool.conns)) + if pool.pendingConnsToClose > 0 { + // some are yet to be closed. but there are no jobs running at the end of which, they will be closed. + assert.Equal(t, expectedFinalSize, len(pool.conns)-pool.pendingConnsToClose) + } else { + // THEN: we should have as many as expectedFinalSize connections in pool now. + assert.Equal(t, expectedFinalSize, len(pool.conns)) + // idle connections should have the rest. + assert.Equal(t, maxSize-expectedFinalSize, len(pool.idleConns)) + } } From 50fc8c4fb685f811ec820384426c1c2912c50e99 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 8 Oct 2024 19:12:50 +0530 Subject: [PATCH 24/33] review comments --- yb-voyager/cmd/importData.go | 7 +++++-- yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go | 4 +--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/yb-voyager/cmd/importData.go b/yb-voyager/cmd/importData.go index 7a7c615b4..b4eb586fd 100644 --- a/yb-voyager/cmd/importData.go +++ b/yb-voyager/cmd/importData.go @@ -493,7 +493,10 @@ func importData(importFileTasks []*ImportFileTask) { poolSize := tconf.Parallelism * 2 if tconf.EnableAdaptiveParallelism { // in case of adaptive parallelism, we need to use maxParalllelism * 2 - yb := tdb.(*tgtdb.TargetYugabyteDB) + yb, ok := tdb.(*tgtdb.TargetYugabyteDB) + if !ok { + utils.ErrExit("adaptive parallelism is only supported if target DB is YugabyteDB") + } poolSize = yb.GetNumMaxConnectionsInPool() * 2 } progressReporter := NewImportDataProgressReporter(bool(disablePb)) @@ -507,7 +510,7 @@ func importData(importFileTasks []*ImportFileTask) { // The code can produce `poolSize` number of batches at a time. But, it can consume only // `parallelism` number of batches at a time. batchImportPool = pool.New().WithMaxGoroutines(poolSize) - log.Info("created batch import pool of size: ", poolSize) + log.Infof("created batch import pool of size: %d", poolSize) totalProgressAmount := getTotalProgressAmount(task) progressReporter.ImportFileStarted(task, totalProgressAmount) diff --git a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go index f8bd5e7cb..5d6f3e554 100644 --- a/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go +++ b/yb-voyager/src/adaptiveparallelism/adaptive_parallelism.go @@ -100,9 +100,7 @@ func getMaxCpuUsageInCluster(clusterMetrics map[string]map[string]string) (int, } cpuUsagePct := int((cpuUsageUser + cpuUsageSystem) * 100) - if cpuUsagePct > maxCpuPct { - maxCpuPct = cpuUsagePct - } + maxCpuPct = max(maxCpuPct, cpuUsagePct) } return maxCpuPct, nil } From b532e906c827f7762bacf3cb34f826e83f75e546 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 8 Oct 2024 19:18:42 +0530 Subject: [PATCH 25/33] review comments 2 --- yb-voyager/src/tgtdb/conn_pool.go | 14 ++++++++++---- yb-voyager/src/tgtdb/yugabytedb.go | 7 ++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index 28e7f7f54..3190ee267 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -43,15 +43,21 @@ type ConnectionParams struct { type ConnectionPool struct { sync.Mutex - params *ConnectionParams - conns chan *pgx.Conn + params *ConnectionParams + conns chan *pgx.Conn + // in adaptive parallelism, we may want to reduce the pool size, but + // we would not want to close the connection, as we might need to increase the pool + // size in the future. So, we move the connections to idleConns instead. idleConns chan *pgx.Conn connIdToPreparedStmtCache map[uint32]map[string]bool // cache list of prepared statements per connection nextUriIndex int disableThrottling bool size int // current size of the pool - pendingConnsToClose int - pendingConnsToCloseLock sync.Mutex + // in adaptive parallelism, we may want to reduce the pool size, but + // doing it synchronously may lead to contention. So, we increment the + // counter pendingConnsToClose, and close the connections asynchronously. + pendingConnsToClose int + pendingConnsToCloseLock sync.Mutex } func NewConnectionPool(params *ConnectionParams) *ConnectionPool { diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 8c8dfec23..172eab037 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -1186,7 +1186,12 @@ func (yb *TargetYugabyteDB) GetClusterMetrics() (map[string]map[string]string, e if err != nil { return result, fmt.Errorf("querying yb_servers_metrics(): %w", err) } - defer rows.Close() + defer func() { + if closeErr := rows.Close(); closeErr != nil { + log.Warnf("failed to close the result set for query [%v]", query) + } + }() + for rows.Next() { var uuid, metrics, status, errorStr string if err := rows.Scan(&uuid, &metrics, &status, &errorStr); err != nil { From 33dfc2708d4e23cd95737edd94951b70b5943877 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 8 Oct 2024 19:26:14 +0530 Subject: [PATCH 26/33] conn_pool comment --- yb-voyager/src/tgtdb/conn_pool.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index 3190ee267..3030b87b8 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -41,6 +41,15 @@ type ConnectionParams struct { SessionInitScript []string } +/* +ConnectionPool is a pool of connections to a YugabyteDB cluster. +It has for the following features: + 1. Re-use of connections. Connections are not closed after a query is executed. + They are returned to the pool, unless there is an error. + 2. Load balancing across multiple YugabyteDB nodes. Connections are created in a round-robin fashion. + 3. Prepared statements are cached per connection + 4. Dynamic pool size. The pool size can be increased or decreased +*/ type ConnectionPool struct { sync.Mutex params *ConnectionParams From 60668e3ab9f1311cffd33da2f3e51c26b03de474 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 8 Oct 2024 19:32:02 +0530 Subject: [PATCH 27/33] var name change --- yb-voyager/cmd/import.go | 6 +++--- yb-voyager/cmd/importData.go | 4 ++-- .../data/gather-assessment-metadata.tar.gz | Bin 9227 -> 9233 bytes yb-voyager/src/tgtdb/tconf.go | 14 +++++++------- yb-voyager/src/tgtdb/yugabytedb.go | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/yb-voyager/cmd/import.go b/yb-voyager/cmd/import.go index 062f9af9d..8020b8cd7 100644 --- a/yb-voyager/cmd/import.go +++ b/yb-voyager/cmd/import.go @@ -346,7 +346,7 @@ func registerFlagsForTarget(cmd *cobra.Command) { "number of cores N and use N/4 as parallel jobs. "+ "Otherwise, it fall back to using twice the number of nodes in the cluster. "+ "Any value less than 1 reverts to the default calculation.") - BoolVar(cmd.Flags(), &tconf.EnableAdaptiveParallelism, "enable-adaptive-parallelism", false, + BoolVar(cmd.Flags(), &tconf.EnableYBAdaptiveParallelism, "enable-adaptive-parallelism", false, "Adapt parallelism based on the resource usage (CPU, memory) of the target YugabyteDB cluster") cmd.Flags().MarkHidden("enable-adaptive-parallelism") // not officially released cmd.Flags().IntVar(&tconf.MaxParallelism, "adaptive-parallelism-max", 0, @@ -397,13 +397,13 @@ func validateFFDBSchemaFlag() { } func validateParallelismFlags() { - if tconf.EnableAdaptiveParallelism { + if tconf.EnableYBAdaptiveParallelism { if tconf.Parallelism > 0 { utils.ErrExit("Error: --parallel-jobs flag cannot be used with --enable-adaptive-parallelism flag") } } if tconf.MaxParallelism > 0 { - if !tconf.EnableAdaptiveParallelism { + if !tconf.EnableYBAdaptiveParallelism { utils.ErrExit("Error: --adaptive-parallelism-max flag can only be used with --enable-adaptive-parallelism true") } } diff --git a/yb-voyager/cmd/importData.go b/yb-voyager/cmd/importData.go index b4eb586fd..9367357db 100644 --- a/yb-voyager/cmd/importData.go +++ b/yb-voyager/cmd/importData.go @@ -437,7 +437,7 @@ func importData(importFileTasks []*ImportFileTask) { utils.ErrExit("Failed to initialize the target DB connection pool: %s", err) } utils.PrintAndLog("Using %d parallel jobs.", tconf.Parallelism) - if tconf.EnableAdaptiveParallelism { + if tconf.EnableYBAdaptiveParallelism { yb, ok := tdb.(*tgtdb.TargetYugabyteDB) if !ok { utils.ErrExit("adaptive parallelism is only supported if target DB is YugabyteDB") @@ -491,7 +491,7 @@ func importData(importFileTasks []*ImportFileTask) { utils.PrintAndLog("Tables to import: %v", importFileTasksToTableNames(pendingTasks)) prepareTableToColumns(pendingTasks) //prepare the tableToColumns map poolSize := tconf.Parallelism * 2 - if tconf.EnableAdaptiveParallelism { + if tconf.EnableYBAdaptiveParallelism { // in case of adaptive parallelism, we need to use maxParalllelism * 2 yb, ok := tdb.(*tgtdb.TargetYugabyteDB) if !ok { diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index bed5342a3d93ee9c3a31b008e4db2a226524855f..9a051413da0bf70cc1c36867081b3af0a82ec8ac 100644 GIT binary patch literal 9233 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 literal 9227 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 diff --git a/yb-voyager/src/tgtdb/tconf.go b/yb-voyager/src/tgtdb/tconf.go index 8079217f2..e064cf972 100644 --- a/yb-voyager/src/tgtdb/tconf.go +++ b/yb-voyager/src/tgtdb/tconf.go @@ -49,13 +49,13 @@ type TargetConf struct { ExcludeImportObjects string `json:"exclude_import_objects"` DBVersion string `json:"db_version"` - TargetEndpoints string `json:"target_endpoints"` - UsePublicIP utils.BoolStr `json:"use_public_ip"` - EnableUpsert utils.BoolStr `json:"enable_upsert"` - DisableTransactionalWrites utils.BoolStr `json:"disable_transactional_writes"` - Parallelism int `json:"parallelism"` - EnableAdaptiveParallelism utils.BoolStr `json:"enable_adaptive_parallelism"` - MaxParallelism int `json:"max_parallelism"` // in case adaptive parallelism is enabled. + TargetEndpoints string `json:"target_endpoints"` + UsePublicIP utils.BoolStr `json:"use_public_ip"` + EnableUpsert utils.BoolStr `json:"enable_upsert"` + DisableTransactionalWrites utils.BoolStr `json:"disable_transactional_writes"` + Parallelism int `json:"parallelism"` + EnableYBAdaptiveParallelism utils.BoolStr `json:"enable_adaptive_parallelism"` + MaxParallelism int `json:"max_parallelism"` // in case adaptive parallelism is enabled. } func (t *TargetConf) Clone() *TargetConf { diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index 172eab037..d9cd005d8 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -220,7 +220,7 @@ func (yb *TargetYugabyteDB) InitConnPool() error { log.Infof("Using %d parallel jobs by default. Use --parallel-jobs to specify a custom value", yb.tconf.Parallelism) } - if yb.tconf.EnableAdaptiveParallelism { + if yb.tconf.EnableYBAdaptiveParallelism { if yb.tconf.MaxParallelism <= 0 { yb.tconf.MaxParallelism = yb.tconf.Parallelism * 2 } From 5677cb9e492e21abd0a42258a4628aecc972cbf6 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 8 Oct 2024 19:32:47 +0530 Subject: [PATCH 28/33] empty From d4176d8b04668b419b4567187de60044e3965b66 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 8 Oct 2024 19:33:08 +0530 Subject: [PATCH 29/33] gather assessment tar --- .../data/gather-assessment-metadata.tar.gz | Bin 9233 -> 9233 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index 9a051413da0bf70cc1c36867081b3af0a82ec8ac..89a2d8d468af9cc511c6c445b6ceaf4322e7a029 100644 GIT binary patch delta 15 WcmbQ}G0}rfzMF%g&w3*pw+a9yVFVfg delta 15 WcmbQ}G0}rfzMF&LpXEk2ZWRD0_XLOl From 15efe8d536e4f8a83d965eee6a5e76b79ceb783b Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Tue, 8 Oct 2024 19:35:01 +0530 Subject: [PATCH 30/33] retar gather-assessments --- .../data/gather-assessment-metadata.tar.gz | Bin 9233 -> 9288 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index 89a2d8d468af9cc511c6c445b6ceaf4322e7a029..e9bbf462d767573f26ef82f95e52f493fd139d0d 100644 GIT binary patch literal 9288 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 From a1cc3f49298430320f1ef11e249c4000e4ea07e2 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Wed, 9 Oct 2024 12:25:01 +0530 Subject: [PATCH 31/33] conn pool review comment --- yb-voyager/src/tgtdb/conn_pool.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/yb-voyager/src/tgtdb/conn_pool.go b/yb-voyager/src/tgtdb/conn_pool.go index 3030b87b8..4ddbca719 100644 --- a/yb-voyager/src/tgtdb/conn_pool.go +++ b/yb-voyager/src/tgtdb/conn_pool.go @@ -116,15 +116,10 @@ func (pool *ConnectionPool) UpdateNumConnections(delta int) error { // If there is non-zero pendingConnsToClose, then we reduce that count. if pool.pendingConnsToClose >= 0 { // since we are increasing, we can just reduce the pending close count - if pool.pendingConnsToClose > delta { - log.Infof("adaptive: Decreasing pendingConnsToClose by %d", delta) - pool.pendingConnsToClose -= delta - delta = 0 - } else { - log.Infof("adaptive: Decreasing pendingConnsToClose to 0 by %d", pool.pendingConnsToClose) - delta -= pool.pendingConnsToClose - pool.pendingConnsToClose = 0 - } + pendingConnsToNotClose := min(pool.pendingConnsToClose, delta) + log.Infof("adaptive: Decreasing pendingConnsToClose by %d", pendingConnsToNotClose) + pool.pendingConnsToClose -= pendingConnsToNotClose + delta -= pendingConnsToNotClose } // Additionally, pick conns from the idle pool, and add it to the main pool. for i := 0; i < delta; i++ { From 446a94b31b2820d1b094ce7e47a52513b6260f73 Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Wed, 9 Oct 2024 12:39:05 +0530 Subject: [PATCH 32/33] nullstring --- yb-voyager/src/tgtdb/yugabytedb.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/yb-voyager/src/tgtdb/yugabytedb.go b/yb-voyager/src/tgtdb/yugabytedb.go index d9cd005d8..13f4ae2b4 100644 --- a/yb-voyager/src/tgtdb/yugabytedb.go +++ b/yb-voyager/src/tgtdb/yugabytedb.go @@ -1193,15 +1193,19 @@ func (yb *TargetYugabyteDB) GetClusterMetrics() (map[string]map[string]string, e }() for rows.Next() { - var uuid, metrics, status, errorStr string + var uuid, metrics, status, errorStr sql.NullString if err := rows.Scan(&uuid, &metrics, &status, &errorStr); err != nil { return result, fmt.Errorf("scanning row for yb_servers_metrics(): %w", err) } + if !uuid.Valid || !status.Valid || !errorStr.Valid || !metrics.Valid { + return result, fmt.Errorf("got invalid NULL values from yb_servers_metrics() : %v, %v, %v, %v", + uuid, metrics, status, errorStr) + } var metricsMap map[string]string - if err := json.Unmarshal([]byte(metrics), &metricsMap); err != nil { + if err := json.Unmarshal([]byte(metrics.String), &metricsMap); err != nil { return result, fmt.Errorf("unmarshalling metrics json string: %w", err) } - result[uuid] = metricsMap + result[uuid.String] = metricsMap } return result, nil } From 5cfce3734ec61da995703c2081172d293c3e788a Mon Sep 17 00:00:00 2001 From: Aneesh Makala Date: Wed, 9 Oct 2024 12:39:53 +0530 Subject: [PATCH 33/33] update tar --- .../data/gather-assessment-metadata.tar.gz | Bin 9288 -> 9512 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index e9bbf462d767573f26ef82f95e52f493fd139d0d..733bcfcf09f155fc4d11cfb479b525f09a019bcc 100644 GIT binary patch literal 9512 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 G(f|M&yKFB2 literal 9288 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 q{CkT5josv_gRA#E*S{Ex>4UASw!OC3_S#