diff --git a/build.sh b/build.sh index df91567..ef26c15 100644 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/bash # # -RELEASE_VERSION="0.9.3" +RELEASE_VERSION="0.9.4" buildpath=/tmp/gh-ost target=gh-ost diff --git a/go/base/context.go b/go/base/context.go index f220973..f8ac7d4 100644 --- a/go/base/context.go +++ b/go/base/context.go @@ -70,6 +70,7 @@ type MigrationContext struct { maxLoadMutex *sync.Mutex PostponeCutOverFlagFile string SwapTablesTimeoutSeconds int64 + PanicFlagFile string ServeSocketFile string ServeTCPPort int64 diff --git a/go/cmd/gh-ost/main.go b/go/cmd/gh-ost/main.go index 09fa908..484bad8 100644 --- a/go/cmd/gh-ost/main.go +++ b/go/cmd/gh-ost/main.go @@ -76,6 +76,7 @@ func main() { flag.StringVar(&migrationContext.ThrottleFlagFile, "throttle-flag-file", "", "operation pauses when this file exists; hint: use a file that is specific to the table being altered") flag.StringVar(&migrationContext.ThrottleAdditionalFlagFile, "throttle-additional-flag-file", "/tmp/gh-ost.throttle", "operation pauses when this file exists; hint: keep default, use for throttling multiple gh-ost operations") flag.StringVar(&migrationContext.PostponeCutOverFlagFile, "postpone-cut-over-flag-file", "", "while this file exists, migration will postpone the final stage of swapping tables, and will keep on syncing the ghost table. Cut-over/swapping would be ready to perform the moment the file is deleted.") + flag.StringVar(&migrationContext.PanicFlagFile, "panic-flag-file", "", "when this file is created, gh-ost will immediately terminate, without cleanup") flag.StringVar(&migrationContext.ServeSocketFile, "serve-socket-file", "", "Unix socket file to serve on. Default: auto-determined and advertised upon startup") flag.Int64Var(&migrationContext.ServeTCPPort, "serve-tcp-port", 0, "TCP port to serve on. Default: disabled") diff --git a/go/logic/migrator.go b/go/logic/migrator.go index ddd885b..e2c3fc5 100644 --- a/go/logic/migrator.go +++ b/go/logic/migrator.go @@ -99,6 +99,15 @@ func (this *Migrator) acceptSignals() { } func (this *Migrator) shouldThrottle() (result bool, reason string) { + + // Regardless of throttle, we take opportunity to check for panic-abort + if this.migrationContext.PanicFlagFile != "" { + if base.FileExists(this.migrationContext.PanicFlagFile) { + this.panicAbort <- fmt.Errorf("Found panic-file %s. Aborting without cleanup", this.migrationContext.PanicFlagFile) + } + } + // Back to throttle considerations + // User-based throttle if atomic.LoadInt64(&this.migrationContext.ThrottleCommandedByUser) > 0 { return true, "commanded by user" @@ -295,6 +304,7 @@ func (this *Migrator) listenOnPanicAbort() { err := <-this.panicAbort log.Fatale(err) } + func (this *Migrator) validateStatement() (err error) { if this.parser.HasNonTrivialRenames() && !this.migrationContext.SkipRenamedColumns { this.migrationContext.ColumnRenameMap = this.parser.GetNonTrivialRenames() @@ -606,12 +616,14 @@ func (this *Migrator) onServerCommand(command string, writer *bufio.Writer) (err if len(tokens) > 1 { arg = strings.TrimSpace(tokens[1]) } + switch command { case "help": { fmt.Fprintln(writer, `available commands: status # Print a status message chunk-size= # Set a new chunk-size + max-load= # Set a new set of max-load thresholds throttle # Force throttling no-throttle # End forced throttling (other throttling may still apply) help # This message @@ -740,6 +752,16 @@ func (this *Migrator) printMigrationStatusHint(writers ...io.Writer) { this.migrationContext.ThrottleAdditionalFlagFile, )) } + if this.migrationContext.PostponeCutOverFlagFile != "" { + fmt.Fprintln(w, fmt.Sprintf("# Postpone cut-over flag file: %+v", + this.migrationContext.PostponeCutOverFlagFile, + )) + } + if this.migrationContext.PanicFlagFile != "" { + fmt.Fprintln(w, fmt.Sprintf("# Panic flag file: %+v", + this.migrationContext.PanicFlagFile, + )) + } fmt.Fprintln(w, fmt.Sprintf("# Serving on unix socket: %+v", this.migrationContext.ServeSocketFile, ))