1
0
mirror of https://github.com/minio/mc.git synced 2025-11-12 01:02:26 +03:00

separate mutex for internal and external locking

This commit is contained in:
Anand Babu (AB) Periasamy
2015-09-09 17:36:33 -07:00
committed by Harshavardhana
parent 942a633c67
commit 3a9b2064f6
2 changed files with 155 additions and 139 deletions

View File

@@ -53,7 +53,10 @@ var Theme = map[string]*color.Color{
} }
var ( var (
mutex = &sync.RWMutex{} // Used by the caller to print multiple lines atomically. Exposed by Lock/Unlock methods.
publicMutex = &sync.Mutex{}
// Used internally by console.
privateMutex = &sync.Mutex{}
stderrColoredOutput = ansicolor.NewAnsiColorWriter(os.Stderr) stderrColoredOutput = ansicolor.NewAnsiColorWriter(os.Stderr)
@@ -198,164 +201,162 @@ var (
} }
) )
var ( // wrap around standard fmt functions
// wrap around standard fmt functions // consolePrint prints a message prefixed with message type and program name
// consolePrint prints a message prefixed with message type and program name func consolePrint(tag string, c *color.Color, a ...interface{}) {
consolePrint = func(tag string, c *color.Color, a ...interface{}) { privateMutex.Lock()
mutex.Lock() defer privateMutex.Unlock()
defer mutex.Unlock()
switch tag { switch tag {
case "Debug": case "Debug":
output := color.Output output := color.Output
color.Output = stderrColoredOutput color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) { if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <DEBUG> ") c.Print(ProgramName() + ": <DEBUG> ")
c.Print(a...) c.Print(a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ") fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
fmt.Fprint(color.Output, a...) fmt.Fprint(color.Output, a...)
} }
color.Output = output color.Output = output
case "Fatal": case "Fatal":
fallthrough fallthrough
case "Error": case "Error":
output := color.Output output := color.Output
color.Output = stderrColoredOutput color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) { if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <ERROR> ") c.Print(ProgramName() + ": <ERROR> ")
c.Print(a...) c.Print(a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ") fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
fmt.Fprint(color.Output, a...) fmt.Fprint(color.Output, a...)
} }
color.Output = output color.Output = output
case "Info": case "Info":
if isatty.IsTerminal(os.Stdout.Fd()) { if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ") c.Print(ProgramName() + ": ")
c.Print(a...) c.Print(a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": ") fmt.Fprint(color.Output, ProgramName()+": ")
fmt.Fprint(color.Output, a...) fmt.Fprint(color.Output, a...)
} }
default: default:
if isatty.IsTerminal(os.Stdout.Fd()) { if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(a...) c.Print(a...)
} else { } else {
fmt.Fprint(color.Output, a...) fmt.Fprint(color.Output, a...)
}
} }
} }
}
// consolePrintf - same as print with a new line // consolePrintf - same as print with a new line
consolePrintf = func(tag string, c *color.Color, format string, a ...interface{}) { func consolePrintf(tag string, c *color.Color, format string, a ...interface{}) {
mutex.Lock() privateMutex.Lock()
defer mutex.Unlock() defer privateMutex.Unlock()
switch tag { switch tag {
case "Debug": case "Debug":
output := color.Output output := color.Output
color.Output = stderrColoredOutput color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) { if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <DEBUG> ") c.Print(ProgramName() + ": <DEBUG> ")
c.Printf(format, a...) c.Printf(format, a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ") fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
fmt.Fprintf(color.Output, format, a...) fmt.Fprintf(color.Output, format, a...)
} }
color.Output = output color.Output = output
case "Fatal": case "Fatal":
fallthrough fallthrough
case "Error": case "Error":
output := color.Output output := color.Output
color.Output = stderrColoredOutput color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) { if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <ERROR> ") c.Print(ProgramName() + ": <ERROR> ")
c.Printf(format, a...) c.Printf(format, a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ") fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
fmt.Fprintf(color.Output, format, a...) fmt.Fprintf(color.Output, format, a...)
} }
color.Output = output color.Output = output
case "Info": case "Info":
if isatty.IsTerminal(os.Stdout.Fd()) { if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ") c.Print(ProgramName() + ": ")
c.Printf(format, a...) c.Printf(format, a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": ") fmt.Fprint(color.Output, ProgramName()+": ")
fmt.Fprintf(color.Output, format, a...) fmt.Fprintf(color.Output, format, a...)
} }
default: default:
if isatty.IsTerminal(os.Stdout.Fd()) { if isatty.IsTerminal(os.Stdout.Fd()) {
c.Printf(format, a...) c.Printf(format, a...)
} else { } else {
fmt.Fprintf(color.Output, format, a...) fmt.Fprintf(color.Output, format, a...)
}
} }
} }
}
// consolePrintln - same as print with a new line // consolePrintln - same as print with a new line
consolePrintln = func(tag string, c *color.Color, a ...interface{}) { func consolePrintln(tag string, c *color.Color, a ...interface{}) {
mutex.Lock() privateMutex.Lock()
defer mutex.Unlock() defer privateMutex.Unlock()
switch tag { switch tag {
case "Debug": case "Debug":
output := color.Output output := color.Output
color.Output = stderrColoredOutput color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) { if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <DEBUG> ") c.Print(ProgramName() + ": <DEBUG> ")
c.Println(a...) c.Println(a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ") fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
fmt.Fprintln(color.Output, a...) fmt.Fprintln(color.Output, a...)
} }
color.Output = output color.Output = output
case "Fatal": case "Fatal":
fallthrough fallthrough
case "Error": case "Error":
output := color.Output output := color.Output
color.Output = stderrColoredOutput color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) { if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <ERROR> ") c.Print(ProgramName() + ": <ERROR> ")
c.Println(a...) c.Println(a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ") fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
fmt.Fprintln(color.Output, a...) fmt.Fprintln(color.Output, a...)
} }
color.Output = output color.Output = output
case "Info": case "Info":
if isatty.IsTerminal(os.Stdout.Fd()) { if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ") c.Print(ProgramName() + ": ")
c.Println(a...) c.Println(a...)
} else { } else {
fmt.Fprint(color.Output, ProgramName()+": ") fmt.Fprint(color.Output, ProgramName()+": ")
fmt.Fprintln(color.Output, a...) fmt.Fprintln(color.Output, a...)
} }
default: default:
if isatty.IsTerminal(os.Stdout.Fd()) { if isatty.IsTerminal(os.Stdout.Fd()) {
c.Println(a...) c.Println(a...)
} else { } else {
fmt.Fprintln(color.Output, a...) fmt.Fprintln(color.Output, a...)
}
} }
} }
) }
// Lock console // Lock console
func Lock() { func Lock() {
mutex.Lock() publicMutex.Lock()
} }
// Unlock locked console // Unlock locked console
func Unlock() { func Unlock() {
mutex.Unlock() publicMutex.Unlock()
} }
// SetCustomTheme sets a color theme // SetCustomTheme sets a color theme
func SetCustomTheme(theme map[string]*color.Color) *probe.Error { func SetCustomTheme(theme map[string]*color.Color) *probe.Error {
mutex.Lock() privateMutex.Lock()
defer mutex.Unlock() defer privateMutex.Unlock()
// add new theme // add new theme
for k, v := range theme { for k, v := range theme {
Theme[k] = v Theme[k] = v
@@ -371,7 +372,7 @@ func ProgramName() string {
// SetNoColor disable coloring // SetNoColor disable coloring
func SetNoColor() { func SetNoColor() {
mutex.Lock() privateMutex.Lock()
defer mutex.Unlock() defer privateMutex.Unlock()
color.NoColor = true color.NoColor = true
} }

View File

@@ -35,3 +35,18 @@ func (s *MySuite) TestSetTheme(c *C) {
_, ok := Theme["unknown"] _, ok := Theme["unknown"]
c.Assert(ok, Equals, true) c.Assert(ok, Equals, true)
} }
func (s *MySuite) TestLock(c *C) {
Lock()
Print("") // Test for deadlocks.
Unlock()
}
func (s *MySuite) TestTesting(c *C) {
// Enable testing
IsTesting = true
Fatalln("THIS IS A TEST MESSAGE. PLEASE INGORE.")
c.Assert(IsExited, Equals, true)
// reset back
IsExited = false
}