github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/modelcmd/files.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package modelcmd 5 6 import ( 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 "time" 12 13 "github.com/juju/errors" 14 "github.com/juju/utils/fslock" 15 16 "github.com/juju/juju/juju/osenv" 17 ) 18 19 const ( 20 CurrentControllerFilename = "current-controller" 21 22 lockName = "current.lock" 23 ) 24 25 var ( 26 // 5 seconds should be way more than enough to write or read any files 27 // even on heavily loaded controllers. 28 lockTimeout = 5 * time.Second 29 ) 30 31 // NOTE: synchronisation across functions in this file. 32 // 33 // Each of the read and write functions use a fslock to synchronise calls 34 // across both the current executable and across different executables. 35 36 func getCurrentControllerFilePath() string { 37 return filepath.Join(osenv.JujuXDGDataHome(), CurrentControllerFilename) 38 } 39 40 // ReadCurrentController reads the file $JUJU_DATA/current-controller and 41 // return the value stored there. If the file doesn't exist an empty string is 42 // returned and no error. 43 func ReadCurrentController() (string, error) { 44 lock, err := acquireEnvironmentLock("read current-controller") 45 if err != nil { 46 return "", errors.Trace(err) 47 } 48 defer lock.Unlock() 49 50 current, err := ioutil.ReadFile(getCurrentControllerFilePath()) 51 if err != nil { 52 if os.IsNotExist(err) { 53 return "", nil 54 } 55 return "", errors.Trace(err) 56 } 57 return strings.TrimSpace(string(current)), nil 58 } 59 60 // WriteCurrentController writes the controllerName to the file 61 // $JUJU_DATA/current-controller file. 62 func WriteCurrentController(controllerName string) error { 63 lock, err := acquireEnvironmentLock("write current-controller") 64 if err != nil { 65 return errors.Trace(err) 66 } 67 defer lock.Unlock() 68 69 path := getCurrentControllerFilePath() 70 err = ioutil.WriteFile(path, []byte(controllerName+"\n"), 0644) 71 if err != nil { 72 return errors.Errorf("unable to write to the controller file: %q, %s", path, err) 73 } 74 return nil 75 } 76 77 func acquireEnvironmentLock(operation string) (*fslock.Lock, error) { 78 // NOTE: any reading or writing from the directory should be done with a 79 // fslock to make sure we have a consistent read or write. Also worth 80 // noting, we should use a very short timeout. 81 lock, err := fslock.NewLock(osenv.JujuXDGDataHome(), lockName, fslock.Defaults()) 82 if err != nil { 83 return nil, errors.Trace(err) 84 } 85 err = lock.LockWithTimeout(lockTimeout, operation) 86 if err != nil { 87 return nil, errors.Trace(err) 88 } 89 return lock, nil 90 }