github.com/swiftstack/proxyfs@v0.0.0-20201223034610-5434d919416e/halter/api.go (about) 1 package halter 2 3 import ( 4 "fmt" 5 "os" 6 "syscall" 7 8 "github.com/swiftstack/ProxyFS/evtlog" 9 ) 10 11 // Note 1: Following const block and HaltLabelStrings should be kept in sync 12 // Note 2: HaltLabelStrings should be easily parseable as URL components 13 14 const ( 15 apiTestHaltLabel1 = iota 16 apiTestHaltLabel2 17 InodeFlushInodesEntry 18 InodeFlushInodesExit 19 ) 20 21 var ( 22 HaltLabelStrings = []string{ 23 "halter.testHaltLabel1", 24 "halter.testHaltLabel2", 25 "inode.flushInodes_Entry", 26 "inode.flushInodes_Exit", 27 } 28 ) 29 30 // Arm sets up a HALT on the haltAfterCount'd call to Trigger() 31 func Arm(haltLabelString string, haltAfterCount uint32) { 32 globals.Lock() 33 haltLabel, ok := globals.triggerNamesToNumbers[haltLabelString] 34 if !ok { 35 err := fmt.Errorf("halter.Arm(haltLabelString='%v',) - label unknown", haltLabelString) 36 haltWithErr(err) 37 } 38 if 0 == haltAfterCount { 39 err := fmt.Errorf("halter.Arm(haltLabel==%v,) called with haltAfterCount==0", haltLabelString) 40 haltWithErr(err) 41 } 42 globals.armedTriggers[haltLabel] = haltAfterCount 43 globals.Unlock() 44 evtlog.Record(evtlog.FormatHalterArm, haltLabelString, haltAfterCount) 45 } 46 47 // Disarm removes a previously armed trigger via a call to Arm() 48 func Disarm(haltLabelString string) { 49 globals.Lock() 50 haltLabel, ok := globals.triggerNamesToNumbers[haltLabelString] 51 if !ok { 52 err := fmt.Errorf("halter.Disarm(haltLabelString='%v') - label unknown", haltLabelString) 53 haltWithErr(err) 54 } 55 delete(globals.armedTriggers, haltLabel) 56 globals.Unlock() 57 evtlog.Record(evtlog.FormatHalterDisarm, haltLabelString) 58 } 59 60 // Trigger decrements the haltAfterCount if armed and, should it reach 0, HALTs 61 func Trigger(haltLabel uint32) { 62 globals.Lock() 63 numTriggersRemaining, armed := globals.armedTriggers[haltLabel] 64 if !armed { 65 globals.Unlock() 66 return 67 } 68 numTriggersRemaining-- 69 if 0 == numTriggersRemaining { 70 haltLabelString := globals.triggerNumbersToNames[haltLabel] 71 evtlog.Record(evtlog.FormatHalterDisarm, haltLabelString) 72 err := fmt.Errorf("halter.TriggerArm(haltLabelString==%v) triggered HALT", haltLabelString) 73 haltWithErr(err) 74 } 75 globals.armedTriggers[haltLabel] = numTriggersRemaining 76 globals.Unlock() 77 } 78 79 // Dump returns a map of currently armed triggers and their remaining trigger count 80 func Dump() (armedTriggers map[string]uint32) { 81 armedTriggers = make(map[string]uint32) 82 for k, v := range globals.armedTriggers { 83 armedTriggers[globals.triggerNumbersToNames[k]] = v 84 } 85 return 86 } 87 88 // List returns a slice of available triggers 89 func List() (availableTriggers []string) { 90 availableTriggers = make([]string, 0, len(globals.triggerNumbersToNames)) 91 for k := range globals.triggerNamesToNumbers { 92 availableTriggers = append(availableTriggers, k) 93 } 94 return 95 } 96 97 // Stat returns the remaining haltAfterCount for the specified haltLabelString 98 func Stat(haltLabelString string) (haltAfterCount uint32, err error) { 99 globals.Lock() 100 haltLabel, ok := globals.triggerNamesToNumbers[haltLabelString] 101 if !ok { 102 globals.Unlock() 103 err = fmt.Errorf("halter.Stat(haltLabelString='%v') - label unknown", haltLabelString) 104 return 105 } 106 haltAfterCount, ok = globals.armedTriggers[haltLabel] 107 if !ok { 108 haltAfterCount = 0 109 } 110 globals.Unlock() 111 return 112 } 113 114 func haltWithErr(err error) { 115 if nil == globals.testModeHaltCB { 116 fmt.Println(err) 117 os.Exit(int(syscall.SIGKILL)) 118 } else { 119 globals.testModeHaltCB(err) 120 } 121 }