github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/store/imagestore/migrate.go (about) 1 // Copyright 2015 The rkt Authors 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 imagestore 16 17 import ( 18 "database/sql" 19 "fmt" 20 "time" 21 22 "github.com/hashicorp/errwrap" 23 "github.com/jonboulle/clockwork" 24 ) 25 26 type migrateFunc func(*sql.Tx) error 27 28 var ( 29 // migrateTable is a map of migrate functions. The key is the db 30 // version to migrate to. 31 migrateTable = map[int]migrateFunc{ 32 1: migrateToV1, 33 2: migrateToV2, 34 3: migrateToV3, 35 4: migrateToV4, 36 5: migrateToV5, 37 6: migrateToV6, 38 7: migrateToV7, 39 } 40 41 clock = clockwork.NewRealClock() 42 ) 43 44 func migrate(tx *sql.Tx, finalVersion int) error { 45 if finalVersion > dbVersion { 46 return fmt.Errorf("required migrate final version greater than the last supported db version") 47 } 48 version, err := getDBVersion(tx) 49 if err != nil { 50 return err 51 } 52 53 for v := version + 1; v <= finalVersion; v++ { 54 migrate, ok := migrateTable[v] 55 if !ok { 56 return fmt.Errorf("missing migrate function for version %d", v) 57 } 58 59 if err := migrate(tx); err != nil { 60 return errwrap.Wrap(fmt.Errorf("failed to migrate db to version %d", v), err) 61 } 62 63 if err := updateDBVersion(tx, v); err != nil { 64 return errwrap.Wrap(fmt.Errorf("updateDBVersion() failed to update the db to version %d", v), err) 65 } 66 } 67 return nil 68 } 69 70 func migrateToV1(tx *sql.Tx) error { 71 return nil 72 } 73 74 func migrateToV2(tx *sql.Tx) error { 75 _, err := tx.Exec("ALTER TABLE remote ADD cachemaxage int") 76 if err != nil { 77 return err 78 } 79 _, err = tx.Exec("ALTER TABLE remote ADD downloadedtime time") 80 if err != nil { 81 return err 82 } 83 // Set the default values for the new columns on the current rows 84 _, err = tx.Exec("UPDATE remote cachemaxage = 0") 85 if err != nil { 86 return err 87 } 88 t := time.Time{}.UTC() 89 _, err = tx.Exec("UPDATE remote downloadedtime = $1", t) 90 if err != nil { 91 return err 92 } 93 return nil 94 } 95 96 func migrateToV3(tx *sql.Tx) error { 97 for _, t := range []string{ 98 "CREATE TABLE aciinfo_tmp (blobkey string, name string, importtime time, latest bool);", 99 "INSERT INTO aciinfo_tmp (blobkey, name, importtime, latest) SELECT blobkey, appname, importtime, latest from aciinfo", 100 "DROP TABLE aciinfo", 101 "CREATE TABLE aciinfo (blobkey string, name string, importtime time, latest bool);", 102 "CREATE UNIQUE INDEX IF NOT EXISTS blobkeyidx ON aciinfo (blobkey)", 103 "CREATE INDEX IF NOT EXISTS nameidx ON aciinfo (name)", 104 "INSERT INTO aciinfo SELECT * from aciinfo_tmp", 105 "DROP TABLE aciinfo_tmp", 106 } { 107 _, err := tx.Exec(t) 108 if err != nil { 109 return err 110 } 111 } 112 return nil 113 } 114 115 func migrateToV4(tx *sql.Tx) error { 116 for _, t := range []string{ 117 "CREATE TABLE aciinfo_tmp (blobkey string, name string, importtime time, lastusedtime time, latest bool);", 118 "INSERT INTO aciinfo_tmp (blobkey, name, importtime, latest) SELECT blobkey, name, importtime, latest from aciinfo", 119 "DROP TABLE aciinfo", 120 // We don't use now() as a DEFAULT for lastusedtime because it doesn't 121 // return a UTC time, which is what we want. Instead, we UPDATE it 122 // below. 123 "CREATE TABLE aciinfo (blobkey string, name string, importtime time, lastusedtime time, latest bool);", 124 "CREATE UNIQUE INDEX IF NOT EXISTS blobkeyidx ON aciinfo (blobkey)", 125 "CREATE INDEX IF NOT EXISTS nameidx ON aciinfo (name)", 126 "INSERT INTO aciinfo SELECT * from aciinfo_tmp", 127 "DROP TABLE aciinfo_tmp", 128 } { 129 _, err := tx.Exec(t) 130 if err != nil { 131 return err 132 } 133 } 134 t := clock.Now().UTC() 135 _, err := tx.Exec("UPDATE aciinfo lastusedtime = $1", t) 136 if err != nil { 137 return err 138 } 139 return nil 140 } 141 142 func migrateToV5(tx *sql.Tx) error { 143 for _, t := range []string{ 144 "CREATE TABLE aciinfo_tmp (blobkey string, name string, importtime time, lastused time, latest bool, size int64, treestoresize int64);", 145 "INSERT INTO aciinfo_tmp (blobkey, name, importtime, lastused, latest) SELECT blobkey, name, importtime, lastusedtime, latest from aciinfo", 146 "DROP TABLE aciinfo", 147 "CREATE TABLE aciinfo (blobkey string, name string, importtime time, lastused time, latest bool, size int64 DEFAULT 0, treestoresize int64 DEFAULT 0);", 148 "CREATE UNIQUE INDEX IF NOT EXISTS blobkeyidx ON aciinfo (blobkey)", 149 "CREATE INDEX IF NOT EXISTS nameidx ON aciinfo (name)", 150 "INSERT INTO aciinfo SELECT * from aciinfo_tmp", 151 "DROP TABLE aciinfo_tmp", 152 } { 153 _, err := tx.Exec(t) 154 if err != nil { 155 return err 156 } 157 } 158 159 return nil 160 } 161 162 func migrateToV6(tx *sql.Tx) error { 163 for _, t := range []string{ 164 "CREATE TABLE aciinfo_tmp (blobkey string, name string, importtime time, lastused time, latest bool, size int64, treestoresize int64, insecureoptions int64 DEFAULT 0);", 165 "INSERT INTO aciinfo_tmp (blobkey, name, importtime, lastused, latest, size, treestoresize) SELECT blobkey, name, importtime, lastused, latest, size, treestoresize from aciinfo", 166 "DROP TABLE aciinfo", 167 "CREATE TABLE aciinfo (blobkey string, name string, importtime time, lastused time, latest bool, size int64 DEFAULT 0, treestoresize int64 DEFAULT 0, insecureoptions int64 DEFAULT 0);", 168 "CREATE UNIQUE INDEX IF NOT EXISTS blobkeyidx ON aciinfo (blobkey)", 169 "CREATE INDEX IF NOT EXISTS nameidx ON aciinfo (name)", 170 "INSERT INTO aciinfo SELECT * from aciinfo_tmp", 171 "DROP TABLE aciinfo_tmp", 172 } { 173 _, err := tx.Exec(t) 174 if err != nil { 175 return err 176 } 177 } 178 179 return nil 180 } 181 182 func migrateToV7(tx *sql.Tx) error { 183 for _, t := range []string{ 184 "CREATE TABLE aciinfo_tmp (blobkey string, name string, importtime time, lastused time, latest bool, size int64, treestoresize int64, insecureoptions int64 DEFAULT 0);", 185 "INSERT INTO aciinfo_tmp (blobkey, name, importtime, lastused, latest, size, treestoresize) SELECT blobkey, name, importtime, lastused, latest, size, treestoresize from aciinfo", 186 "DROP TABLE aciinfo", 187 "CREATE TABLE aciinfo (blobkey string, name string, importtime time, lastused time, latest bool, size int64 DEFAULT 0, treestoresize int64 DEFAULT 0);", 188 "CREATE UNIQUE INDEX IF NOT EXISTS blobkeyidx ON aciinfo (blobkey)", 189 "CREATE INDEX IF NOT EXISTS nameidx ON aciinfo (name)", 190 "INSERT INTO aciinfo SELECT blobkey, name, importtime, lastused, latest, size, treestoresize from aciinfo_tmp", 191 "DROP TABLE aciinfo_tmp", 192 } { 193 _, err := tx.Exec(t) 194 if err != nil { 195 return err 196 } 197 } 198 199 return nil 200 }