github.com/eatigo/migrate@v3.0.2-0.20210729130915-7610befb1b6b+incompatible/migrate.go (about)

     1  // Package migrate reads migrations from sources and runs them against databases.
     2  // Sources are defined by the `source.Driver` and databases by the `database.Driver`
     3  // interface. The driver interfaces are kept "dump", all migration logic is kept
     4  // in this package.
     5  package migrate
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/eatigo/migrate/database"
    14  	"github.com/eatigo/migrate/source"
    15  )
    16  
    17  // DefaultPrefetchMigrations sets the number of migrations to pre-read
    18  // from the source. This is helpful if the source is remote, but has little
    19  // effect for a local source (i.e. file system).
    20  // Please note that this setting has a major impact on the memory usage,
    21  // since each pre-read migration is buffered in memory. See DefaultBufferSize.
    22  var DefaultPrefetchMigrations = uint(10)
    23  
    24  // DefaultLockTimeout sets the max time a database driver has to acquire a lock.
    25  var DefaultLockTimeout = 15 * time.Second
    26  
    27  var (
    28  	ErrNoChange    = fmt.Errorf("no change")
    29  	ErrNilVersion  = fmt.Errorf("no migration")
    30  	ErrLocked      = fmt.Errorf("database locked")
    31  	ErrLockTimeout = fmt.Errorf("timeout: can't acquire database lock")
    32  )
    33  
    34  // ErrShortLimit is an error returned when not enough migrations
    35  // can be returned by a source for a given limit.
    36  type ErrShortLimit struct {
    37  	Short uint
    38  }
    39  
    40  // Error implements the error interface.
    41  func (e ErrShortLimit) Error() string {
    42  	return fmt.Sprintf("limit %v short", e.Short)
    43  }
    44  
    45  type ErrDirty struct {
    46  	Version int
    47  }
    48  
    49  func (e ErrDirty) Error() string {
    50  	return fmt.Sprintf("Dirty database version %v. Fix and force version.", e.Version)
    51  }
    52  
    53  type Migrate struct {
    54  	sourceName   string
    55  	sourceDrv    source.Driver
    56  	databaseName string
    57  	databaseDrv  database.Driver
    58  
    59  	// Log accepts a Logger interface
    60  	Log Logger
    61  
    62  	// GracefulStop accepts `true` and will stop executing migrations
    63  	// as soon as possible at a safe break point, so that the database
    64  	// is not corrupted.
    65  	GracefulStop   chan bool
    66  	isGracefulStop bool
    67  
    68  	isLockedMu *sync.Mutex
    69  	isLocked   bool
    70  
    71  	// PrefetchMigrations defaults to DefaultPrefetchMigrations,
    72  	// but can be set per Migrate instance.
    73  	PrefetchMigrations uint
    74  
    75  	// LockTimeout defaults to DefaultLockTimeout,
    76  	// but can be set per Migrate instance.
    77  	LockTimeout time.Duration
    78  }
    79  
    80  // New returns a new Migrate instance from a source URL and a database URL.
    81  // The URL scheme is defined by each driver.
    82  func New(sourceUrl, databaseUrl string) (*Migrate, error) {
    83  	m := newCommon()
    84  
    85  	if sourceUrl != "" {
    86  		sourceName, err := schemeFromUrl(sourceUrl)
    87  		if err != nil {
    88  			return nil, err
    89  		}
    90  		m.sourceName = sourceName
    91  	}
    92  	databaseName, err := schemeFromUrl(databaseUrl)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	m.databaseName = databaseName
    97  
    98  	if sourceUrl != "" {
    99  		sourceDrv, err := source.Open(sourceUrl)
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  		m.sourceDrv = sourceDrv
   104  	}
   105  
   106  	databaseDrv, err := database.Open(databaseUrl)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	m.databaseDrv = databaseDrv
   111  
   112  	return m, nil
   113  }
   114  
   115  // NewWithDatabaseInstance returns a new Migrate instance from a source URL
   116  // and an existing database instance. The source URL scheme is defined by each driver.
   117  // Use any string that can serve as an identifier during logging as databaseName.
   118  // You are responsible for closing the underlying database client if necessary.
   119  func NewWithDatabaseInstance(sourceUrl string, databaseName string, databaseInstance database.Driver) (*Migrate, error) {
   120  	m := newCommon()
   121  
   122  	sourceName, err := schemeFromUrl(sourceUrl)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	m.sourceName = sourceName
   127  
   128  	m.databaseName = databaseName
   129  
   130  	sourceDrv, err := source.Open(sourceUrl)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  	m.sourceDrv = sourceDrv
   135  
   136  	m.databaseDrv = databaseInstance
   137  
   138  	return m, nil
   139  }
   140  
   141  // NewWithSourceInstance returns a new Migrate instance from an existing source instance
   142  // and a database URL. The database URL scheme is defined by each driver.
   143  // Use any string that can serve as an identifier during logging as sourceName.
   144  // You are responsible for closing the underlying source client if necessary.
   145  func NewWithSourceInstance(sourceName string, sourceInstance source.Driver, databaseUrl string) (*Migrate, error) {
   146  	m := newCommon()
   147  
   148  	databaseName, err := schemeFromUrl(databaseUrl)
   149  	if err != nil {
   150  		return nil, err
   151  	}
   152  	m.databaseName = databaseName
   153  
   154  	m.sourceName = sourceName
   155  
   156  	databaseDrv, err := database.Open(databaseUrl)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  	m.databaseDrv = databaseDrv
   161  
   162  	m.sourceDrv = sourceInstance
   163  
   164  	return m, nil
   165  }
   166  
   167  // NewWithInstance returns a new Migrate instance from an existing source and
   168  // database instance. Use any string that can serve as an identifier during logging
   169  // as sourceName and databaseName. You are responsible for closing down
   170  // the underlying source and database client if necessary.
   171  func NewWithInstance(sourceName string, sourceInstance source.Driver, databaseName string, databaseInstance database.Driver) (*Migrate, error) {
   172  	m := newCommon()
   173  
   174  	m.sourceName = sourceName
   175  	m.databaseName = databaseName
   176  
   177  	m.sourceDrv = sourceInstance
   178  	m.databaseDrv = databaseInstance
   179  
   180  	return m, nil
   181  }
   182  
   183  func newCommon() *Migrate {
   184  	return &Migrate{
   185  		GracefulStop:       make(chan bool, 1),
   186  		PrefetchMigrations: DefaultPrefetchMigrations,
   187  		LockTimeout:        DefaultLockTimeout,
   188  		isLockedMu:         &sync.Mutex{},
   189  	}
   190  }
   191  
   192  // Close closes the the source and the database.
   193  func (m *Migrate) Close() (source error, database error) {
   194  	databaseSrvClose := make(chan error)
   195  	sourceSrvClose := make(chan error)
   196  
   197  	m.logVerbosePrintf("Closing source and database\n")
   198  
   199  	go func() {
   200  		databaseSrvClose <- m.databaseDrv.Close()
   201  	}()
   202  
   203  	go func() {
   204  		if m.sourceDrv != nil {
   205  			sourceSrvClose <- m.sourceDrv.Close()
   206  		} else {
   207  			sourceSrvClose <- nil
   208  		}
   209  	}()
   210  
   211  	return <-sourceSrvClose, <-databaseSrvClose
   212  }
   213  
   214  // Migrate looks at the currently active migration version,
   215  // then migrates either up or down to the specified version.
   216  func (m *Migrate) Migrate(version uint) error {
   217  	if err := m.lock(); err != nil {
   218  		return err
   219  	}
   220  
   221  	curVersion, dirty, err := m.databaseDrv.Version()
   222  	if err != nil {
   223  		return m.unlockErr(err)
   224  	}
   225  
   226  	if dirty {
   227  		return m.unlockErr(ErrDirty{curVersion})
   228  	}
   229  
   230  	ret := make(chan interface{}, m.PrefetchMigrations)
   231  	go m.read(curVersion, int(version), ret)
   232  
   233  	return m.unlockErr(m.runMigrations(ret))
   234  }
   235  
   236  // Steps looks at the currently active migration version.
   237  // It will migrate up if n > 0, and down if n < 0.
   238  func (m *Migrate) Steps(n int) error {
   239  	if n == 0 {
   240  		return ErrNoChange
   241  	}
   242  
   243  	if err := m.lock(); err != nil {
   244  		return err
   245  	}
   246  
   247  	curVersion, dirty, err := m.databaseDrv.Version()
   248  	if err != nil {
   249  		return m.unlockErr(err)
   250  	}
   251  
   252  	if dirty {
   253  		return m.unlockErr(ErrDirty{curVersion})
   254  	}
   255  
   256  	ret := make(chan interface{}, m.PrefetchMigrations)
   257  
   258  	if n > 0 {
   259  		go m.readUp(curVersion, n, ret)
   260  	} else {
   261  		go m.readDown(curVersion, -n, ret)
   262  	}
   263  
   264  	return m.unlockErr(m.runMigrations(ret))
   265  }
   266  
   267  // Up looks at the currently active migration version
   268  // and will migrate all the way up (applying all up migrations).
   269  func (m *Migrate) Up() error {
   270  	if err := m.lock(); err != nil {
   271  		return err
   272  	}
   273  
   274  	curVersion, dirty, err := m.databaseDrv.Version()
   275  	if err != nil {
   276  		return m.unlockErr(err)
   277  	}
   278  
   279  	if dirty {
   280  		return m.unlockErr(ErrDirty{curVersion})
   281  	}
   282  
   283  	ret := make(chan interface{}, m.PrefetchMigrations)
   284  
   285  	go m.readUp(curVersion, -1, ret)
   286  	return m.unlockErr(m.runMigrations(ret))
   287  }
   288  
   289  // Down looks at the currently active migration version
   290  // and will migrate all the way down (applying all down migrations).
   291  func (m *Migrate) Down() error {
   292  	if err := m.lock(); err != nil {
   293  		return err
   294  	}
   295  
   296  	curVersion, dirty, err := m.databaseDrv.Version()
   297  	if err != nil {
   298  		return m.unlockErr(err)
   299  	}
   300  
   301  	if dirty {
   302  		return m.unlockErr(ErrDirty{curVersion})
   303  	}
   304  
   305  	ret := make(chan interface{}, m.PrefetchMigrations)
   306  	go m.readDown(curVersion, -1, ret)
   307  	return m.unlockErr(m.runMigrations(ret))
   308  }
   309  
   310  // Drop deletes everything in the database.
   311  func (m *Migrate) Drop() error {
   312  	if err := m.lock(); err != nil {
   313  		return err
   314  	}
   315  	if err := m.databaseDrv.Drop(); err != nil {
   316  		return m.unlockErr(err)
   317  	}
   318  	return m.unlock()
   319  }
   320  
   321  // Run runs any migration provided by you against the database.
   322  // It does not check any currently active version in database.
   323  // Usually you don't need this function at all. Use Migrate,
   324  // Steps, Up or Down instead.
   325  func (m *Migrate) Run(migration ...*Migration) error {
   326  	if len(migration) == 0 {
   327  		return ErrNoChange
   328  	}
   329  
   330  	if err := m.lock(); err != nil {
   331  		return err
   332  	}
   333  
   334  	curVersion, dirty, err := m.databaseDrv.Version()
   335  	if err != nil {
   336  		return m.unlockErr(err)
   337  	}
   338  
   339  	if dirty {
   340  		return m.unlockErr(ErrDirty{curVersion})
   341  	}
   342  
   343  	ret := make(chan interface{}, m.PrefetchMigrations)
   344  
   345  	go func() {
   346  		defer close(ret)
   347  		for _, migr := range migration {
   348  			if m.PrefetchMigrations > 0 && migr.Body != nil {
   349  				m.logVerbosePrintf("Start buffering %v\n", migr.LogString())
   350  			} else {
   351  				m.logVerbosePrintf("Scheduled %v\n", migr.LogString())
   352  			}
   353  
   354  			ret <- migr
   355  			go migr.Buffer()
   356  		}
   357  	}()
   358  
   359  	return m.unlockErr(m.runMigrations(ret))
   360  }
   361  
   362  // Force sets a migration version.
   363  // It does not check any currently active version in database.
   364  // It resets the dirty state to false.
   365  func (m *Migrate) Force(version int) error {
   366  	if version < -1 {
   367  		panic("version must be >= -1")
   368  	}
   369  
   370  	if err := m.lock(); err != nil {
   371  		return err
   372  	}
   373  
   374  	if err := m.databaseDrv.SetVersion(version, false); err != nil {
   375  		return m.unlockErr(err)
   376  	}
   377  
   378  	return m.unlock()
   379  }
   380  
   381  // Version returns the currently active migration version.
   382  // If no migration has been applied, yet, it will return ErrNilVersion.
   383  func (m *Migrate) Version() (version uint, dirty bool, err error) {
   384  	v, d, err := m.databaseDrv.Version()
   385  	if err != nil {
   386  		return 0, false, err
   387  	}
   388  
   389  	if v == database.NilVersion {
   390  		return 0, false, ErrNilVersion
   391  	}
   392  
   393  	return suint(v), d, nil
   394  }
   395  
   396  // read reads either up or down migrations from source `from` to `to`.
   397  // Each migration is then written to the ret channel.
   398  // If an error occurs during reading, that error is written to the ret channel, too.
   399  // Once read is done reading it will close the ret channel.
   400  func (m *Migrate) read(from int, to int, ret chan<- interface{}) {
   401  	defer close(ret)
   402  
   403  	// check if from version exists
   404  	if from >= 0 {
   405  		if m.versionExists(suint(from)) != nil {
   406  			ret <- os.ErrNotExist
   407  			return
   408  		}
   409  	}
   410  
   411  	// check if to version exists
   412  	if to >= 0 {
   413  		if m.versionExists(suint(to)) != nil {
   414  			ret <- os.ErrNotExist
   415  			return
   416  		}
   417  	}
   418  
   419  	// no change?
   420  	if from == to {
   421  		ret <- ErrNoChange
   422  		return
   423  	}
   424  
   425  	if from < to {
   426  		// it's going up
   427  		// apply first migration if from is nil version
   428  		if from == -1 {
   429  			firstVersion, err := m.sourceDrv.First()
   430  			if err != nil {
   431  				ret <- err
   432  				return
   433  			}
   434  
   435  			migr, err := m.newMigration(firstVersion, int(firstVersion))
   436  			if err != nil {
   437  				ret <- err
   438  				return
   439  			}
   440  
   441  			ret <- migr
   442  			go migr.Buffer()
   443  			from = int(firstVersion)
   444  		}
   445  
   446  		// run until we reach target ...
   447  		for from < to {
   448  			if m.stop() {
   449  				return
   450  			}
   451  
   452  			next, err := m.sourceDrv.Next(suint(from))
   453  			if err != nil {
   454  				ret <- err
   455  				return
   456  			}
   457  
   458  			migr, err := m.newMigration(next, int(next))
   459  			if err != nil {
   460  				ret <- err
   461  				return
   462  			}
   463  
   464  			ret <- migr
   465  			go migr.Buffer()
   466  			from = int(next)
   467  		}
   468  
   469  	} else {
   470  		// it's going down
   471  		// run until we reach target ...
   472  		for from > to && from >= 0 {
   473  			if m.stop() {
   474  				return
   475  			}
   476  
   477  			prev, err := m.sourceDrv.Prev(suint(from))
   478  			if os.IsNotExist(err) && to == -1 {
   479  				// apply nil migration
   480  				migr, err := m.newMigration(suint(from), -1)
   481  				if err != nil {
   482  					ret <- err
   483  					return
   484  				}
   485  				ret <- migr
   486  				go migr.Buffer()
   487  				return
   488  
   489  			} else if err != nil {
   490  				ret <- err
   491  				return
   492  			}
   493  
   494  			migr, err := m.newMigration(suint(from), int(prev))
   495  			if err != nil {
   496  				ret <- err
   497  				return
   498  			}
   499  
   500  			ret <- migr
   501  			go migr.Buffer()
   502  			from = int(prev)
   503  		}
   504  	}
   505  }
   506  
   507  // readUp reads up migrations from `from` limitted by `limit`.
   508  // limit can be -1, implying no limit and reading until there are no more migrations.
   509  // Each migration is then written to the ret channel.
   510  // If an error occurs during reading, that error is written to the ret channel, too.
   511  // Once readUp is done reading it will close the ret channel.
   512  func (m *Migrate) readUp(from int, limit int, ret chan<- interface{}) {
   513  	defer close(ret)
   514  
   515  	// check if from version exists
   516  	if from >= 0 {
   517  		if m.versionExists(suint(from)) != nil {
   518  			ret <- os.ErrNotExist
   519  			return
   520  		}
   521  	}
   522  
   523  	if limit == 0 {
   524  		ret <- ErrNoChange
   525  		return
   526  	}
   527  
   528  	count := 0
   529  	for count < limit || limit == -1 {
   530  		if m.stop() {
   531  			return
   532  		}
   533  
   534  		// apply first migration if from is nil version
   535  		if from == -1 {
   536  			firstVersion, err := m.sourceDrv.First()
   537  			if err != nil {
   538  				ret <- err
   539  				return
   540  			}
   541  
   542  			migr, err := m.newMigration(firstVersion, int(firstVersion))
   543  			if err != nil {
   544  				ret <- err
   545  				return
   546  			}
   547  
   548  			ret <- migr
   549  			go migr.Buffer()
   550  			from = int(firstVersion)
   551  			count++
   552  			continue
   553  		}
   554  
   555  		// apply next migration
   556  		next, err := m.sourceDrv.Next(suint(from))
   557  		if os.IsNotExist(err) {
   558  			// no limit, but no migrations applied?
   559  			if limit == -1 && count == 0 {
   560  				ret <- ErrNoChange
   561  				return
   562  			}
   563  
   564  			// no limit, reached end
   565  			if limit == -1 {
   566  				return
   567  			}
   568  
   569  			// reached end, and didn't apply any migrations
   570  			if limit > 0 && count == 0 {
   571  				ret <- os.ErrNotExist
   572  				return
   573  			}
   574  
   575  			// applied less migrations than limit?
   576  			if count < limit {
   577  				ret <- ErrShortLimit{suint(limit - count)}
   578  				return
   579  			}
   580  		}
   581  		if err != nil {
   582  			ret <- err
   583  			return
   584  		}
   585  
   586  		migr, err := m.newMigration(next, int(next))
   587  		if err != nil {
   588  			ret <- err
   589  			return
   590  		}
   591  
   592  		ret <- migr
   593  		go migr.Buffer()
   594  		from = int(next)
   595  		count++
   596  	}
   597  }
   598  
   599  // readDown reads down migrations from `from` limitted by `limit`.
   600  // limit can be -1, implying no limit and reading until there are no more migrations.
   601  // Each migration is then written to the ret channel.
   602  // If an error occurs during reading, that error is written to the ret channel, too.
   603  // Once readDown is done reading it will close the ret channel.
   604  func (m *Migrate) readDown(from int, limit int, ret chan<- interface{}) {
   605  	defer close(ret)
   606  
   607  	// check if from version exists
   608  	if from >= 0 {
   609  		if m.versionExists(suint(from)) != nil {
   610  			ret <- os.ErrNotExist
   611  			return
   612  		}
   613  	}
   614  
   615  	if limit == 0 {
   616  		ret <- ErrNoChange
   617  		return
   618  	}
   619  
   620  	// no change if already at nil version
   621  	if from == -1 && limit == -1 {
   622  		ret <- ErrNoChange
   623  		return
   624  	}
   625  
   626  	// can't go over limit if already at nil version
   627  	if from == -1 && limit > 0 {
   628  		ret <- os.ErrNotExist
   629  		return
   630  	}
   631  
   632  	count := 0
   633  	for count < limit || limit == -1 {
   634  		if m.stop() {
   635  			return
   636  		}
   637  
   638  		prev, err := m.sourceDrv.Prev(suint(from))
   639  		if os.IsNotExist(err) {
   640  			// no limit or haven't reached limit, apply "first" migration
   641  			if limit == -1 || limit-count > 0 {
   642  				firstVersion, err := m.sourceDrv.First()
   643  				if err != nil {
   644  					ret <- err
   645  					return
   646  				}
   647  
   648  				migr, err := m.newMigration(firstVersion, -1)
   649  				if err != nil {
   650  					ret <- err
   651  					return
   652  				}
   653  				ret <- migr
   654  				go migr.Buffer()
   655  				count++
   656  			}
   657  
   658  			if count < limit {
   659  				ret <- ErrShortLimit{suint(limit - count)}
   660  			}
   661  			return
   662  		}
   663  		if err != nil {
   664  			ret <- err
   665  			return
   666  		}
   667  
   668  		migr, err := m.newMigration(suint(from), int(prev))
   669  		if err != nil {
   670  			ret <- err
   671  			return
   672  		}
   673  
   674  		ret <- migr
   675  		go migr.Buffer()
   676  		from = int(prev)
   677  		count++
   678  	}
   679  }
   680  
   681  // runMigrations reads *Migration and error from a channel. Any other type
   682  // sent on this channel will result in a panic. Each migration is then
   683  // proxied to the database driver and run against the database.
   684  // Before running a newly received migration it will check if it's supposed
   685  // to stop execution because it might have received a stop signal on the
   686  // GracefulStop channel.
   687  func (m *Migrate) runMigrations(ret <-chan interface{}) error {
   688  	for r := range ret {
   689  
   690  		if m.stop() {
   691  			return nil
   692  		}
   693  
   694  		switch r.(type) {
   695  		case error:
   696  			return r.(error)
   697  
   698  		case *Migration:
   699  			migr := r.(*Migration)
   700  
   701  			// set version with dirty state
   702  			if err := m.databaseDrv.SetVersion(migr.TargetVersion, true); err != nil {
   703  				return err
   704  			}
   705  
   706  			if migr.Body != nil {
   707  				m.logVerbosePrintf("Read and execute %v\n", migr.LogString())
   708  				if err := m.databaseDrv.Run(migr.BufferedBody); err != nil {
   709  					return err
   710  				}
   711  			}
   712  
   713  			// set clean state
   714  			if err := m.databaseDrv.SetVersion(migr.TargetVersion, false); err != nil {
   715  				return err
   716  			}
   717  
   718  			endTime := time.Now()
   719  			readTime := migr.FinishedReading.Sub(migr.StartedBuffering)
   720  			runTime := endTime.Sub(migr.FinishedReading)
   721  
   722  			// log either verbose or normal
   723  			if m.Log != nil {
   724  				if m.Log.Verbose() {
   725  					m.logPrintf("Finished %v (read %v, ran %v)\n", migr.LogString(), readTime, runTime)
   726  				} else {
   727  					m.logPrintf("%v (%v)\n", migr.LogString(), readTime+runTime)
   728  				}
   729  			}
   730  
   731  		default:
   732  			panic("unknown type")
   733  		}
   734  	}
   735  	return nil
   736  }
   737  
   738  // versionExists checks the source if either the up or down migration for
   739  // the specified migration version exists.
   740  func (m *Migrate) versionExists(version uint) error {
   741  	// try up migration first
   742  	up, _, err := m.sourceDrv.ReadUp(version)
   743  	if err == nil {
   744  		defer up.Close()
   745  	}
   746  	if os.IsExist(err) {
   747  		return nil
   748  	} else if !os.IsNotExist(err) {
   749  		return err
   750  	}
   751  
   752  	// then try down migration
   753  	down, _, err := m.sourceDrv.ReadDown(version)
   754  	if err == nil {
   755  		defer down.Close()
   756  	}
   757  	if os.IsExist(err) {
   758  		return nil
   759  	} else if !os.IsNotExist(err) {
   760  		return err
   761  	}
   762  
   763  	return os.ErrNotExist
   764  }
   765  
   766  // stop returns true if no more migrations should be run against the database
   767  // because a stop signal was received on the GracefulStop channel.
   768  // Calls are cheap and this function is not blocking.
   769  func (m *Migrate) stop() bool {
   770  	if m.isGracefulStop {
   771  		return true
   772  	}
   773  
   774  	select {
   775  	case <-m.GracefulStop:
   776  		m.isGracefulStop = true
   777  		return true
   778  
   779  	default:
   780  		return false
   781  	}
   782  }
   783  
   784  // newMigration is a helper func that returns a *Migration for the
   785  // specified version and targetVersion.
   786  func (m *Migrate) newMigration(version uint, targetVersion int) (*Migration, error) {
   787  	var migr *Migration
   788  
   789  	if targetVersion >= int(version) {
   790  		r, identifier, err := m.sourceDrv.ReadUp(version)
   791  		if os.IsNotExist(err) {
   792  			// create "empty" migration
   793  			migr, err = NewMigration(nil, "", version, targetVersion)
   794  			if err != nil {
   795  				return nil, err
   796  			}
   797  
   798  		} else if err != nil {
   799  			return nil, err
   800  
   801  		} else {
   802  			// create migration from up source
   803  			migr, err = NewMigration(r, identifier, version, targetVersion)
   804  			if err != nil {
   805  				return nil, err
   806  			}
   807  		}
   808  
   809  	} else {
   810  		r, identifier, err := m.sourceDrv.ReadDown(version)
   811  		if os.IsNotExist(err) {
   812  			// create "empty" migration
   813  			migr, err = NewMigration(nil, "", version, targetVersion)
   814  			if err != nil {
   815  				return nil, err
   816  			}
   817  
   818  		} else if err != nil {
   819  			return nil, err
   820  
   821  		} else {
   822  			// create migration from down source
   823  			migr, err = NewMigration(r, identifier, version, targetVersion)
   824  			if err != nil {
   825  				return nil, err
   826  			}
   827  		}
   828  	}
   829  
   830  	if m.PrefetchMigrations > 0 && migr.Body != nil {
   831  		m.logVerbosePrintf("Start buffering %v\n", migr.LogString())
   832  	} else {
   833  		m.logVerbosePrintf("Scheduled %v\n", migr.LogString())
   834  	}
   835  
   836  	return migr, nil
   837  }
   838  
   839  // lock is a thread safe helper function to lock the database.
   840  // It should be called as late as possible when running migrations.
   841  func (m *Migrate) lock() error {
   842  	m.isLockedMu.Lock()
   843  	defer m.isLockedMu.Unlock()
   844  
   845  	if m.isLocked {
   846  		return ErrLocked
   847  	}
   848  
   849  	// create done channel, used in the timeout goroutine
   850  	done := make(chan bool, 1)
   851  	defer func() {
   852  		done <- true
   853  	}()
   854  
   855  	// use errchan to signal error back to this context
   856  	errchan := make(chan error, 2)
   857  
   858  	// start timeout goroutine
   859  	timeout := time.After(m.LockTimeout)
   860  	go func() {
   861  		for {
   862  			select {
   863  			case <-done:
   864  				return
   865  			case <-timeout:
   866  				errchan <- ErrLockTimeout
   867  				return
   868  			}
   869  		}
   870  	}()
   871  
   872  	// now try to acquire the lock
   873  	go func() {
   874  		if err := m.databaseDrv.Lock(); err != nil {
   875  			errchan <- err
   876  		} else {
   877  			errchan <- nil
   878  		}
   879  		return
   880  	}()
   881  
   882  	// wait until we either recieve ErrLockTimeout or error from Lock operation
   883  	err := <-errchan
   884  	if err == nil {
   885  		m.isLocked = true
   886  	}
   887  	return err
   888  }
   889  
   890  // unlock is a thread safe helper function to unlock the database.
   891  // It should be called as early as possible when no more migrations are
   892  // expected to be executed.
   893  func (m *Migrate) unlock() error {
   894  	m.isLockedMu.Lock()
   895  	defer m.isLockedMu.Unlock()
   896  
   897  	if err := m.databaseDrv.Unlock(); err != nil {
   898  		// BUG: Can potentially create a deadlock. Add a timeout.
   899  		return err
   900  	}
   901  
   902  	m.isLocked = false
   903  	return nil
   904  }
   905  
   906  // unlockErr calls unlock and returns a combined error
   907  // if a prevErr is not nil.
   908  func (m *Migrate) unlockErr(prevErr error) error {
   909  	if err := m.unlock(); err != nil {
   910  		return NewMultiError(prevErr, err)
   911  	}
   912  	return prevErr
   913  }
   914  
   915  // logPrintf writes to m.Log if not nil
   916  func (m *Migrate) logPrintf(format string, v ...interface{}) {
   917  	if m.Log != nil {
   918  		m.Log.Printf(format, v...)
   919  	}
   920  }
   921  
   922  // logVerbosePrintf writes to m.Log if not nil. Use for verbose logging output.
   923  func (m *Migrate) logVerbosePrintf(format string, v ...interface{}) {
   924  	if m.Log != nil && m.Log.Verbose() {
   925  		m.Log.Printf(format, v...)
   926  	}
   927  }