github.com/hy3/cuto@v0.9.8-0.20160830082821-aa6652f877b7/servant/job/jobcheck.go (about) 1 package job 2 3 import ( 4 "bufio" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "regexp" 11 "strconv" 12 "strings" 13 14 "github.com/unirita/cuto/message" 15 "github.com/unirita/cuto/servant/config" 16 "github.com/unirita/cuto/utctime" 17 ) 18 19 func DoJobResultCheck(chk *message.JobCheck, conf *config.ServantConfig) *message.JobResult { 20 result := new(message.JobResult) 21 result.NID = chk.NID 22 result.JID = chk.JID 23 24 logPath := filepath.Join(conf.Dir.LogDir, "servant.log") 25 endRecord, err := searchJobEndRecordFromLog(logPath, result.NID, result.JID) 26 if err != nil || len(endRecord) == 0 { 27 return createUnexecutedResult(chk.NID, chk.JID) 28 } 29 30 status, err := extractStatusFromRecord(endRecord) 31 if err != nil || status == 0 { 32 return createErrorResult(chk.NID, chk.JID) 33 } 34 result.Stat = status 35 36 et, err := extractTimestampFromRecord(endRecord) 37 if err != nil { 38 return createErrorResult(chk.NID, chk.JID) 39 } 40 result.Et = et.Format(utctime.Default) 41 42 rc, err := extractRCFromRecord(endRecord) 43 if err != nil { 44 return createErrorResult(chk.NID, chk.JID) 45 } 46 result.RC = rc 47 48 joblog, err := searchLatestJoblog(conf.Dir.JoblogDir, chk.NID, chk.JID, et) 49 if err != nil { 50 return createErrorResult(chk.NID, chk.JID) 51 } 52 53 st, err := extractTimestampFromJoblog(joblog) 54 if err != nil { 55 return createErrorResult(chk.NID, chk.JID) 56 } 57 result.St = st.Format(utctime.Default) 58 59 variable, err := extractVariableFromJoblog(joblog) 60 if err != nil { 61 return createErrorResult(chk.NID, chk.JID) 62 } 63 result.Var = variable 64 65 return result 66 } 67 68 func searchJobEndRecordFromLog(path string, nid int, jid string) (string, error) { 69 file, err := os.Open(path) 70 if err != nil { 71 return "", err 72 } 73 defer file.Close() 74 75 matchStr := fmt.Sprintf( 76 `^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} \[\d+\] \[INF\] CTS01[01]I.*INSTANCE \[%d\] ID \[%s\]`, 77 nid, jid) 78 matcher := regexp.MustCompile(matchStr) 79 var endRecord string 80 s := bufio.NewScanner(file) 81 for s.Scan() { 82 record := s.Text() 83 if matcher.MatchString(record) { 84 endRecord = record 85 } 86 } 87 88 return endRecord, nil 89 } 90 91 func extractTimestampFromRecord(record string) (utctime.UTCTime, error) { 92 timestampStr := record[:len(utctime.Default)] 93 return utctime.ParseLocaltime(utctime.Default, timestampStr) 94 } 95 96 func extractStatusFromRecord(record string) (int, error) { 97 if strings.Contains(record, "CTS010I") { 98 return 0, nil 99 } 100 101 finder := regexp.MustCompile(`STATUS \[\d+\]`) 102 statusStr := finder.FindString(record) 103 if len(statusStr) < 9 { 104 return 0, errors.New("Could not extract status.") 105 } 106 status, err := strconv.Atoi(statusStr[8 : len(statusStr)-1]) 107 if err != nil { 108 return 0, errors.New("Could not extract status as int.") 109 } 110 111 return status, nil 112 } 113 114 func extractRCFromRecord(record string) (int, error) { 115 finder := regexp.MustCompile(`RC \[\d+\]`) 116 rcStr := finder.FindString(record) 117 if len(rcStr) < 5 { 118 return 0, errors.New("Could not extract RC.") 119 } 120 rc, err := strconv.Atoi(rcStr[4 : len(rcStr)-1]) 121 if err != nil { 122 return 0, errors.New("Could not extract RC as int.") 123 } 124 125 return rc, nil 126 } 127 128 func searchLatestJoblog(joblogDir string, nid int, jid string, et utctime.UTCTime) (string, error) { 129 dirNames := make([]string, 2) 130 dirNames[0] = et.FormatLocaltime(utctime.Date8Num) 131 dirNames[1] = et.AddDays(-1).FormatLocaltime(utctime.Date8Num) 132 133 matchStr := fmt.Sprintf(`^%d\.[^.]+\.%s\.`, nid, jid) 134 matcher := regexp.MustCompile(matchStr) 135 for _, dirName := range dirNames { 136 dir := filepath.Join(joblogDir, dirName) 137 fileInfos, err := ioutil.ReadDir(dir) 138 if err != nil { 139 continue 140 } 141 142 var path string 143 for _, fileInfo := range fileInfos { 144 fileName := fileInfo.Name() 145 if matcher.MatchString(fileName) { 146 path = fileName 147 } 148 } 149 if path != "" { 150 return filepath.Join(dir, path), nil 151 } 152 } 153 154 return "", errors.New("Could not find joblog file.") 155 } 156 157 func extractTimestampFromJoblog(joblog string) (utctime.UTCTime, error) { 158 parts := strings.Split(joblog, ".") 159 timestampStr := strings.Join(parts[len(parts)-3:len(parts)-1], ".") 160 return utctime.ParseLocaltime(utctime.NoDelimiter, timestampStr) 161 } 162 163 func extractVariableFromJoblog(joblog string) (string, error) { 164 file, err := os.Open(joblog) 165 if err != nil { 166 return "", err 167 } 168 defer file.Close() 169 170 var variable string 171 s := bufio.NewScanner(file) 172 for s.Scan() { 173 variable = s.Text() 174 } 175 176 return variable, nil 177 } 178 179 func createUnexecutedResult(nid int, jid string) *message.JobResult { 180 result := new(message.JobResult) 181 result.NID = nid 182 result.JID = jid 183 result.Stat = -1 184 return result 185 } 186 187 func createErrorResult(nid int, jid string) *message.JobResult { 188 result := new(message.JobResult) 189 result.NID = nid 190 result.JID = jid 191 return result 192 }