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