github.com/mfycheng/glide@v0.11.2-0.20160818232903-be8a502f4bc4/cache/global_lock.go (about) 1 package cache 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "time" 9 10 "github.com/Masterminds/glide/msg" 11 gpath "github.com/Masterminds/glide/path" 12 ) 13 14 var isStarted bool 15 16 // SystemLock starts a system rather than application lock. This way multiple 17 // app instances don't cause race conditions when working in the cache. 18 func SystemLock() error { 19 if isStarted { 20 return nil 21 } 22 err := waitOnLock() 23 if err != nil { 24 return err 25 } 26 err = startLock() 27 isStarted = true 28 return err 29 } 30 31 // SystemUnlock removes the system wide Glide cache lock. 32 func SystemUnlock() { 33 lockdone <- struct{}{} 34 os.Remove(lockFileName) 35 } 36 37 var lockdone = make(chan struct{}, 1) 38 39 type lockdata struct { 40 Comment string `json:"comment"` 41 Pid int `json:"pid"` 42 Time string `json:"time"` 43 } 44 45 var lockFileName = filepath.Join(gpath.Home(), "lock.json") 46 47 // Write a lock for now. 48 func writeLock() error { 49 ld := &lockdata{ 50 Comment: "File managed by Glide (https://glide.sh)", 51 Pid: os.Getpid(), 52 Time: time.Now().Format(time.RFC3339Nano), 53 } 54 55 out, err := json.Marshal(ld) 56 if err != nil { 57 return err 58 } 59 err = ioutil.WriteFile(lockFileName, out, 0755) 60 return err 61 } 62 63 func startLock() error { 64 err := writeLock() 65 if err != nil { 66 return err 67 } 68 69 go func() { 70 for { 71 select { 72 case <-lockdone: 73 return 74 default: 75 time.Sleep(10 * time.Second) 76 err := writeLock() 77 if err != nil { 78 msg.Die("Error using Glide lock: %s", err) 79 } 80 } 81 } 82 }() 83 84 return nil 85 } 86 87 func waitOnLock() error { 88 var announced bool 89 for { 90 fi, err := os.Stat(lockFileName) 91 if err != nil && os.IsNotExist(err) { 92 return nil 93 } else if err != nil { 94 return err 95 } 96 97 diff := time.Now().Sub(fi.ModTime()) 98 if diff.Seconds() > 15 { 99 return nil 100 } 101 102 if !announced { 103 announced = true 104 msg.Info("Waiting on Glide global cache access") 105 } 106 107 // Check on the lock file every 15 seconds. 108 // TODO(mattfarina): should this be a different length? 109 time.Sleep(time.Second) 110 } 111 }