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