Skip to content

Commit 9c41e44

Browse files
author
Guillaume Lefranc
committed
Log switchover messages to termbox instead of stdout
1 parent 78a7e30 commit 9c41e44

File tree

1 file changed

+84
-73
lines changed

1 file changed

+84
-73
lines changed

mariadb-repmgr/repmgr.go

Lines changed: 84 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func main() {
134134
log.Printf("DEBUG: Creating new server: %v", servers[k].URL)
135135
}
136136
if err != nil {
137-
log.Printf("INFO: Server %s is dead.", servers[k].URL)
137+
log.Printf("INFO : Server %s is dead.", servers[k].URL)
138138
servers[k].State = STATE_FAILED
139139
continue
140140
}
@@ -255,8 +255,14 @@ func main() {
255255
switch event.Type {
256256
case termbox.EventKey:
257257
if event.Key == termbox.KeyCtrlS {
258-
command = "switchover"
259-
exit = true
258+
nmUrl, nsKey := master.switchover()
259+
if nmUrl != "" && nsKey >= 0 {
260+
if *verbose {
261+
logprintf("DEBUG: Reinstancing new master: %s and new slave: %s [%d]", nmUrl, slaves[nsKey].URL, nsKey)
262+
}
263+
master, err = newServerMonitor(nmUrl)
264+
slaves[nsKey], err = newServerMonitor(slaves[nsKey].URL)
265+
}
260266
}
261267
if event.Key == termbox.KeyCtrlF {
262268
command = "failover"
@@ -276,22 +282,9 @@ func main() {
276282
exit = true
277283
}
278284
}
279-
termbox.Close()
280285
switch command {
281-
case "switchover":
282-
nmUrl, nsKey := master.switchover()
283-
if nmUrl != "" && nsKey >= 0 {
284-
if *verbose {
285-
log.Printf("DEBUG: Reinstancing new master: %s and new slave: %s [%d]", nmUrl, slaves[nsKey].URL, nsKey)
286-
}
287-
master, err = newServerMonitor(nmUrl)
288-
slaves[nsKey], err = newServerMonitor(slaves[nsKey].URL)
289-
}
290-
log.Println("###### Restarting monitor console in 5 seconds. Press Ctrl-C to exit")
291-
time.Sleep(5 * time.Second)
292-
exit = false
293-
goto MainLoop
294286
case "failover":
287+
termbox.Close()
295288
nmUrl, nmKey := master.failover()
296289
if nmUrl != "" {
297290
if *verbose {
@@ -306,6 +299,7 @@ func main() {
306299
exit = false
307300
goto MainLoop
308301
}
302+
termbox.Close()
309303
}
310304
}
311305

@@ -379,138 +373,138 @@ func (sm *ServerMonitor) healthCheck() string {
379373

380374
/* Triggers a master switchover. Returns the new master's URL */
381375
func (master *ServerMonitor) switchover() (string, int) {
382-
log.Println("INFO : Starting switchover")
376+
logprint("INFO : Starting switchover")
383377
// Phase 1: Cleanup and election
384-
log.Printf("INFO : Flushing tables on %s (master)", master.URL)
378+
logprintf("INFO : Flushing tables on %s (master)", master.URL)
385379
err := dbhelper.FlushTablesNoLog(master.Conn)
386380
if err != nil {
387-
log.Printf("WARN : Could not flush tables on master", err)
381+
logprintf("WARN : Could not flush tables on master", err)
388382
}
389-
log.Println("INFO : Checking long running updates on master")
383+
logprint("INFO : Checking long running updates on master")
390384
if dbhelper.CheckLongRunningWrites(master.Conn, 10) > 0 {
391-
log.Println("ERROR: Long updates running on master. Cannot switchover")
385+
logprint("ERROR: Long updates running on master. Cannot switchover")
392386
return "", -1
393387
}
394-
log.Println("INFO : Electing a new master")
388+
logprint("INFO : Electing a new master")
395389
var nmUrl string
396390
key := master.electCandidate(slaves)
397391
if key == -1 {
398392
return "", -1
399393
}
400394
nmUrl = slaves[key].URL
401-
log.Printf("INFO : Slave %s has been elected as a new master", nmUrl)
395+
logprintf("INFO : Slave %s has been elected as a new master", nmUrl)
402396
newMaster, err := newServerMonitor(nmUrl)
403397
if *preScript != "" {
404-
log.Printf("INFO : Calling pre-failover script")
398+
logprintf("INFO : Calling pre-failover script")
405399
out, err := exec.Command(*preScript, master.Host, newMaster.Host).CombinedOutput()
406400
if err != nil {
407-
log.Println("ERROR:", err)
401+
logprint("ERROR:", err)
408402
}
409-
log.Println("INFO : Pre-failover script complete:", string(out))
403+
logprint("INFO : Pre-failover script complete:", string(out))
410404
}
411405
// Phase 2: Reject updates and sync slaves
412406
master.freeze()
413-
log.Printf("INFO : Rejecting updates on %s (old master)", master.URL)
407+
logprintf("INFO : Rejecting updates on %s (old master)", master.URL)
414408
err = dbhelper.FlushTablesWithReadLock(master.Conn)
415409
if err != nil {
416-
log.Printf("WARN : Could not lock tables on %s (old master) %s", master.URL, err)
410+
logprintf("WARN : Could not lock tables on %s (old master) %s", master.URL, err)
417411
}
418-
log.Println("INFO : Switching master")
419-
log.Println("INFO : Waiting for candidate master to synchronize")
412+
logprint("INFO : Switching master")
413+
logprint("INFO : Waiting for candidate master to synchronize")
420414
masterGtid := dbhelper.GetVariableByName(master.Conn, "GTID_BINLOG_POS")
421415
if *verbose {
422-
log.Printf("DEBUG: Syncing on master GTID Current Pos [%s]", masterGtid)
416+
logprintf("DEBUG: Syncing on master GTID Current Pos [%s]", masterGtid)
423417
master.log()
424418
}
425419
dbhelper.MasterPosWait(newMaster.Conn, masterGtid)
426420
if *verbose {
427-
log.Println("DEBUG: MASTER_POS_WAIT executed.")
421+
logprint("DEBUG: MASTER_POS_WAIT executed.")
428422
newMaster.log()
429423
}
430424
// Phase 3: Prepare new master
431-
log.Println("INFO: Stopping slave thread on new master")
425+
logprint("INFO : Stopping slave thread on new master")
432426
err = dbhelper.StopSlave(newMaster.Conn)
433427
if err != nil {
434-
log.Println("WARN : Stopping slave failed on new master")
428+
logprint("WARN : Stopping slave failed on new master")
435429
}
436430
// Call post-failover script before unlocking the old master.
437431
if *postScript != "" {
438-
log.Printf("INFO : Calling post-failover script")
432+
logprintf("INFO : Calling post-failover script")
439433
out, err := exec.Command(*postScript, master.Host, newMaster.Host).CombinedOutput()
440434
if err != nil {
441-
log.Println("ERROR:", err)
435+
logprint("ERROR:", err)
442436
}
443-
log.Println("INFO : Post-failover script complete", string(out))
437+
logprint("INFO : Post-failover script complete", string(out))
444438
}
445-
log.Println("INFO : Resetting slave on new master and set read/write mode on")
439+
logprint("INFO : Resetting slave on new master and set read/write mode on")
446440
err = dbhelper.ResetSlave(newMaster.Conn, true)
447441
if err != nil {
448-
log.Println("WARN : Reset slave failed on new master")
442+
logprint("WARN : Reset slave failed on new master")
449443
}
450444
// Phase 4: Demote old master to slave
451445
err = dbhelper.SetReadOnly(newMaster.Conn, false)
452446
if err != nil {
453-
log.Println("ERROR: Could not set new master as read-write")
447+
logprint("ERROR: Could not set new master as read-write")
454448
}
455449
cm := "CHANGE MASTER TO master_host='" + newMaster.IP + "', master_port=" + newMaster.Port + ", master_user='" + rplUser + "', master_password='" + rplPass + "'"
456-
log.Println("INFO : Switching old master as a slave")
450+
logprint("INFO : Switching old master as a slave")
457451
err = dbhelper.UnlockTables(master.Conn)
458452
if err != nil {
459-
log.Println("WARN : Could not unlock tables on old master", err)
453+
logprint("WARN : Could not unlock tables on old master", err)
460454
}
461455
dbhelper.StopSlave(master.Conn) // This is helpful because in some cases the old master can have an old configuration running
462456
_, err = master.Conn.Exec(cm + ", master_use_gtid=current_pos")
463457
if err != nil {
464-
log.Println("WARN : Change master failed on old master", err)
458+
logprint("WARN : Change master failed on old master", err)
465459
}
466460
err = dbhelper.StartSlave(master.Conn)
467461
if err != nil {
468-
log.Println("WARN : Start slave failed on old master", err)
462+
logprint("WARN : Start slave failed on old master", err)
469463
}
470464
if *readonly {
471465
err = dbhelper.SetReadOnly(master.Conn, true)
472466
if err != nil {
473-
log.Printf("ERROR: Could not set old master as read-only, %s", err)
467+
logprintf("ERROR: Could not set old master as read-only, %s", err)
474468
}
475469
}
476470
// Phase 5: Switch slaves to new master
477-
log.Println("INFO : Switching other slaves to the new master")
471+
logprint("INFO : Switching other slaves to the new master")
478472
var oldMasterKey int
479473
for k, sl := range slaves {
480474
if sl.URL == newMaster.URL {
481475
slaves[k].URL = master.URL
482476
oldMasterKey = k
483477
if *verbose {
484-
log.Printf("DEBUG: New master %s found in slave slice at key %d, reinstancing URL to %s", sl.URL, k, master.URL)
478+
logprintf("DEBUG: New master %s found in slave slice at key %d, reinstancing URL to %s", sl.URL, k, master.URL)
485479
}
486480
continue
487481
}
488-
log.Printf("INFO : Waiting for slave %s to sync", sl.URL)
482+
logprintf("INFO : Waiting for slave %s to sync", sl.URL)
489483
dbhelper.MasterPosWait(sl.Conn, masterGtid)
490484
if *verbose {
491485
sl.log()
492486
}
493-
log.Printf("INFO : Change master on slave %s", sl.URL)
487+
logprintf("INFO : Change master on slave %s", sl.URL)
494488
err := dbhelper.StopSlave(sl.Conn)
495489
if err != nil {
496-
log.Printf("WARN : Could not stop slave on server %s, %s", sl.URL, err)
490+
logprintf("WARN : Could not stop slave on server %s, %s", sl.URL, err)
497491
}
498492
_, err = sl.Conn.Exec(cm)
499493
if err != nil {
500-
log.Printf("ERROR: Change master failed on slave %s, %s", sl.URL, err)
494+
logprintf("ERROR: Change master failed on slave %s, %s", sl.URL, err)
501495
}
502496
err = dbhelper.StartSlave(sl.Conn)
503497
if err != nil {
504-
log.Printf("ERROR: could not start slave on server %s, %s", sl.URL, err)
498+
logprintf("ERROR: could not start slave on server %s, %s", sl.URL, err)
505499
}
506500
if *readonly {
507501
err = dbhelper.SetReadOnly(sl.Conn, true)
508502
if err != nil {
509-
log.Printf("ERROR: Could not set slave %s as read-only, %s", sl.URL, err)
503+
logprintf("ERROR: Could not set slave %s as read-only, %s", sl.URL, err)
510504
}
511505
}
512506
}
513-
log.Println("INFO : Switchover complete")
507+
logprint("INFO : Switchover complete")
514508
return newMaster.URL, oldMasterKey
515509
}
516510

@@ -587,18 +581,18 @@ func (master *ServerMonitor) failover() (string, int) {
587581
func (server *ServerMonitor) freeze() bool {
588582
err := dbhelper.SetReadOnly(server.Conn, true)
589583
if err != nil {
590-
log.Printf("WARN : Could not set %s as read-only: %s", server.URL, err)
584+
logprintf("WARN : Could not set %s as read-only: %s", server.URL, err)
591585
return false
592586
}
593587
for i := *waitKill; i > 0; i -= 500 {
594588
threads := dbhelper.CheckLongRunningWrites(server.Conn, 0)
595589
if threads == 0 {
596590
break
597591
}
598-
log.Printf("INFO : Waiting for %d write threads to complete on %s", threads, server.URL)
592+
logprintf("INFO : Waiting for %d write threads to complete on %s", threads, server.URL)
599593
time.Sleep(500 * time.Millisecond)
600594
}
601-
log.Printf("INFO: Terminating all threads on %s", server.URL)
595+
logprintf("INFO : Terminating all threads on %s", server.URL)
602596
dbhelper.KillThreads(server.Conn)
603597
return true
604598
}
@@ -644,45 +638,45 @@ func validateHostPort(h string, p string) bool {
644638
func (master *ServerMonitor) electCandidate(l []*ServerMonitor) int {
645639
ll := len(l)
646640
if *verbose {
647-
log.Printf("DEBUG: Processing %d candidates", ll)
641+
logprintf("DEBUG: Processing %d candidates", ll)
648642
}
649643
seqList := make([]uint64, ll)
650644
i := 0
651645
hiseq := 0
652646
for _, sl := range l {
653647
if *failover == "" {
654648
if *verbose {
655-
log.Printf("DEBUG: Checking eligibility of slave server %s", sl.URL)
649+
logprintf("DEBUG: Checking eligibility of slave server %s", sl.URL)
656650
}
657651
if dbhelper.CheckSlavePrerequisites(sl.Conn, sl.Host) == false {
658652
continue
659653
}
660654
if dbhelper.CheckBinlogFilters(master.Conn, sl.Conn) == false {
661-
log.Printf("WARN : Binlog filters differ on master and slave %s. Skipping", sl.URL)
655+
logprintf("WARN : Binlog filters differ on master and slave %s. Skipping", sl.URL)
662656
continue
663657
}
664658
if dbhelper.CheckReplicationFilters(master.Conn, sl.Conn) == false {
665-
log.Printf("WARN : Replication filters differ on master and slave %s. Skipping", sl.URL)
659+
logprintf("WARN : Replication filters differ on master and slave %s. Skipping", sl.URL)
666660
continue
667661
}
668662
ss, _ := dbhelper.GetSlaveStatus(sl.Conn)
669663
if ss.Seconds_Behind_Master.Valid == false {
670-
log.Printf("WARN : Slave %s is stopped. Skipping", sl.URL)
664+
logprintf("WARN : Slave %s is stopped. Skipping", sl.URL)
671665
continue
672666
}
673667
if ss.Seconds_Behind_Master.Int64 > *maxDelay {
674-
log.Printf("WARN : Slave %s has more than %d seconds of replication delay (%d). Skipping", sl.URL, *maxDelay, ss.Seconds_Behind_Master.Int64)
668+
logprintf("WARN : Slave %s has more than %d seconds of replication delay (%d). Skipping", sl.URL, *maxDelay, ss.Seconds_Behind_Master.Int64)
675669
continue
676670
}
677671
if *gtidCheck && dbhelper.CheckSlaveSync(sl.Conn, master.Conn) == false {
678-
log.Printf("WARN : Slave %s not in sync. Skipping", sl.URL)
672+
logprintf("WARN : Slave %s not in sync. Skipping", sl.URL)
679673
continue
680674
}
681675
}
682676
/* Rig the election if the examined slave is preferred candidate master */
683677
if sl.URL == *prefMaster {
684678
if *verbose {
685-
log.Printf("DEBUG: Election rig: %s elected as preferred master", sl.URL)
679+
logprintf("DEBUG: Election rig: %s elected as preferred master", sl.URL)
686680
}
687681
return i
688682
}
@@ -707,7 +701,7 @@ func (master *ServerMonitor) electCandidate(l []*ServerMonitor) int {
707701

708702
func (server *ServerMonitor) log() {
709703
server.refresh()
710-
log.Printf("DEBUG: Server:%s Current GTID:%s Slave GTID:%s Binlog Pos:%s\n", server.URL, server.CurrentGtid, server.SlaveGtid, server.BinlogPos)
704+
logprintf("DEBUG: Server:%s Current GTID:%s Slave GTID:%s Binlog Pos:%s\n", server.URL, server.CurrentGtid, server.SlaveGtid, server.BinlogPos)
711705
return
712706
}
713707

@@ -777,7 +771,7 @@ func display() {
777771
printTb(0, vy, termbox.ColorWhite, termbox.ColorBlack, " Ctrl-Q to quit, Ctrl-F to failover")
778772
}
779773
vy = vy + 3
780-
tlog.Print(&vy)
774+
tlog.Print()
781775
termbox.Flush()
782776
}
783777

@@ -801,11 +795,10 @@ func (tl *TermLog) Add(s string) {
801795
*tl = shift(*tl, s)
802796
}
803797

804-
func (tl TermLog) Print(vy *int) {
805-
//log.Println(tl)
798+
func (tl TermLog) Print() {
806799
for _, line := range tl {
807-
printTb(0, *vy, termbox.ColorWhite, termbox.ColorBlack, line)
808-
*vy++
800+
printTb(0, vy, termbox.ColorWhite, termbox.ColorBlack, line)
801+
vy++
809802
}
810803
}
811804

@@ -821,6 +814,24 @@ func printfTb(x, y int, fg, bg termbox.Attribute, format string, args ...interfa
821814
printTb(x, y, fg, bg, s)
822815
}
823816

817+
func logprint(msg ...interface{}) {
818+
if *interactive == true || *failover == "monitor" {
819+
tlog.Add(fmt.Sprintln(msg...))
820+
display()
821+
} else {
822+
log.Println(msg...)
823+
}
824+
}
825+
826+
func logprintf(format string, args ...interface{}) {
827+
if *interactive == true || *failover == "monitor" {
828+
tlog.Add(fmt.Sprintf(format, args...))
829+
display()
830+
} else {
831+
log.Printf(format, args...)
832+
}
833+
}
834+
824835
func new_tb_chan() chan termbox.Event {
825836
termboxChan := make(chan termbox.Event)
826837
go func() {
@@ -834,7 +845,7 @@ func new_tb_chan() chan termbox.Event {
834845
func shift(s []string, e string) []string {
835846
ns := make([]string, 1)
836847
ns[0] = e
837-
ns = append(ns, s[0:9]...)
848+
ns = append(ns, s[0:20]...)
838849
return ns
839850
}
840851

0 commit comments

Comments
 (0)