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  }