github.com/matrixorigin/matrixone@v1.2.0/pkg/bootstrap/versions/upgrade_tenant_task.go (about) 1 // Copyright 2024 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package versions 16 17 import ( 18 "fmt" 19 20 "github.com/matrixorigin/matrixone/pkg/catalog" 21 "github.com/matrixorigin/matrixone/pkg/common/moerr" 22 "github.com/matrixorigin/matrixone/pkg/container/vector" 23 "github.com/matrixorigin/matrixone/pkg/pb/lock" 24 "github.com/matrixorigin/matrixone/pkg/util/executor" 25 ) 26 27 func AddUpgradeTenantTask( 28 upgradeID uint64, 29 version string, 30 fromAccountID int32, 31 toAccountID int32, 32 txn executor.TxnExecutor) error { 33 sql := fmt.Sprintf(`insert into %s ( 34 upgrade_id, 35 target_version, 36 from_account_id, 37 to_account_id, 38 ready, 39 create_at, 40 update_at) values (%d, '%s', %d, %d, %d, current_timestamp(), current_timestamp())`, 41 catalog.MOUpgradeTenantTable, 42 upgradeID, 43 version, 44 fromAccountID, 45 toAccountID, 46 No) 47 res, err := txn.Exec(sql, executor.StatementOption{}) 48 if err != nil { 49 return err 50 } 51 res.Close() 52 return nil 53 } 54 55 func UpdateUpgradeTenantTaskState( 56 taskID uint64, 57 state int32, 58 txn executor.TxnExecutor) error { 59 sql := fmt.Sprintf("update %s set ready = %d where id = %d", 60 catalog.MOUpgradeTenantTable, 61 state, 62 taskID) 63 res, err := txn.Exec(sql, executor.StatementOption{}) 64 if err != nil { 65 return err 66 } 67 res.Close() 68 return nil 69 } 70 71 func GetUpgradeTenantTasks( 72 upgradeID uint64, 73 txn executor.TxnExecutor) (uint64, []int32, []string, error) { 74 taskID := uint64(0) 75 tenants := make([]int32, 0) 76 versions := make([]string, 0) 77 after := int32(0) 78 for { 79 sql := fmt.Sprintf("select id, from_account_id, to_account_id from %s where from_account_id >= %d and upgrade_id = %d and ready = %d order by id limit 1", 80 catalog.MOUpgradeTenantTable, 81 after, 82 upgradeID, 83 No) 84 res, err := txn.Exec(sql, executor.StatementOption{}) 85 if err != nil { 86 return 0, nil, nil, err 87 } 88 from := int32(-1) 89 to := int32(-1) 90 res.ReadRows(func(rows int, cols []*vector.Vector) bool { 91 taskID = vector.GetFixedAt[uint64](cols[0], 0) 92 from = vector.GetFixedAt[int32](cols[1], 0) 93 to = vector.GetFixedAt[int32](cols[2], 0) 94 return true 95 }) 96 res.Close() 97 if from == -1 { 98 return 0, nil, nil, nil 99 } 100 101 sql = fmt.Sprintf("select account_id, create_version from mo_account where account_id >= %d and account_id <= %d for update", 102 from, to) 103 res, err = txn.Exec(sql, executor.StatementOption{}.WithWaitPolicy(lock.WaitPolicy_FastFail)) 104 if err != nil { 105 if isConflictError(err) { 106 after = to + 1 107 continue 108 } 109 return 0, nil, nil, err 110 } 111 res.ReadRows(func(rows int, cols []*vector.Vector) bool { 112 for i := 0; i < rows; i++ { 113 tenants = append(tenants, vector.GetFixedAt[int32](cols[0], i)) 114 versions = append(versions, cols[1].GetStringAt(i)) 115 } 116 return true 117 }) 118 res.Close() 119 return taskID, tenants, versions, nil 120 } 121 } 122 123 func GetTenantCreateVersionForUpdate( 124 tenantID int32, 125 txn executor.TxnExecutor) (string, error) { 126 sql := fmt.Sprintf("select create_version from mo_account where account_id = %d for update", tenantID) 127 res, err := txn.Exec(sql, executor.StatementOption{}) 128 if err != nil { 129 return "", err 130 } 131 defer res.Close() 132 version := "" 133 res.ReadRows(func(rows int, cols []*vector.Vector) bool { 134 version = cols[0].GetStringAt(0) 135 return true 136 }) 137 if version == "" { 138 panic(fmt.Sprintf("BUG: missing tenant: %d", tenantID)) 139 } 140 return version, nil 141 } 142 143 func UpgradeTenantVersion( 144 tenantID int32, 145 version string, 146 txn executor.TxnExecutor) error { 147 sql := fmt.Sprintf("update mo_account set create_version = '%s' where account_id = %d", 148 version, 149 tenantID) 150 res, err := txn.Exec(sql, executor.StatementOption{}) 151 if err != nil { 152 return err 153 } 154 defer res.Close() 155 if res.AffectedRows != 1 { 156 panic(fmt.Sprintf("BUG: update tenant: %d failed with AffectedRows %d", 157 tenantID, res.AffectedRows)) 158 } 159 return nil 160 } 161 162 func isConflictError(err error) bool { 163 return moerr.IsMoErrCode(err, moerr.ErrLockConflict) 164 } 165 166 func GetTenantVersion( 167 tenantID int32, 168 txn executor.TxnExecutor) (string, error) { 169 sql := fmt.Sprintf("select create_version from mo_account where account_id = %d", tenantID) 170 res, err := txn.Exec(sql, executor.StatementOption{}) 171 if err != nil { 172 return "", err 173 } 174 defer res.Close() 175 version := "" 176 res.ReadRows(func(rows int, cols []*vector.Vector) bool { 177 version = cols[0].GetStringAt(0) 178 return true 179 }) 180 if version == "" { 181 panic(fmt.Sprintf("BUG: missing tenant: %d", tenantID)) 182 } 183 return version, nil 184 }