// ネットワークをリランする。 // // return : エラー情報。 func (n *Network) Rerun() error { current := n.Start if current == nil { return fmt.Errorf("Start element of network is nil.") } err := n.resume() if err != nil { console.Display("CTM019E", err) return err } prePID := n.Result.JobnetResult.PID if util.IsProcessExists(prePID) { return fmt.Errorf("JOBNETWORK [%d] still running.", n.ID) } console.Display("CTM012I", n.Name, n.ID) n.setIsRerunJob() for { next, err := current.Execute() if err != nil { return n.end(err) } if current == n.End { return n.end(nil) } else if next == nil { err := fmt.Errorf("Element[id = %s] cannot terminate network because it is not a endEvent.", current.ID()) return n.end(err) } current = next } panic("Not reached.") }
// ネットワークを実行する。 // // return : エラー情報。 func (n *Network) Run() error { current := n.Start if current == nil { return fmt.Errorf("Start element of network is nil.") } err := n.start() if err != nil { console.Display("CTM019E", err) return err } console.Display("CTM012I", n.Name, n.ID) for { next, err := current.Execute() if err != nil { return n.end(err) } if current == n.End { return n.end(nil) } else if next == nil { err := fmt.Errorf("Element[id = %s] cannot terminate network because it is not a endEvent.", current.ID()) return n.end(err) } current = next } panic("Not reached.") }
// ジョブの実行要求を受け付けて実行する。 // // param : req マスタからの要求メッセージ。 // // param : conf サーバントの設定情報。 // // param : stCh スタート時刻送信用チャンネル // // return : マスタへ返信するメッセージ。 func DoJobRequest(req *message.Request, conf *config.ServantConfig, stCh chan<- string) *message.Response { job := newJobInstance(req, conf) cmd := job.createShell() err := job.run(cmd, stCh) if err != nil { console.DisplayError("CTS019E", err) job.stat = db.ABNORMAL job.detail = err.Error() } else { rcSt, rcMsg := job.judgeRC() ptnSt, ptnMsg, err := job.writeFileAndJodgeJoblog() if err != nil { console.DisplayError("CTS019E", err) job.stat = db.ABNORMAL job.detail = err.Error() } else { // RCからの結果と、出力MSGの結果を比較し、大きい方(異常の方)を採用する if rcSt > ptnSt { job.stat = rcSt job.detail = rcMsg } else { job.stat = ptnSt job.detail = ptnMsg } } console.Display("CTS011I", job.path, job.nID, job.jID, job.stat, job.rc) job.setVariableValue() } return job.createResponse() }
func receiveLoopProcess(listener net.Listener, sq chan<- *Session) error { conn, err := listener.Accept() if err != nil { log.Error(err) return err } console.Display("CTS014I") go receiveMessage(conn, sq) return nil }
func realMain(args *arguments) int { if args.v { showVersion() return rc_OK } message.ServantVersion = Version // システム変数のセット message.AddSysValue("ROOT", "", util.GetRootPath()) config.ReadConfig(args.configPath) if err := config.Servant.DetectError(); err != nil { console.Display("CTS005E", err) return rc_error } // ログ出力開始 if err := log.Init(config.Servant.Dir.LogDir, "servant", strconv.Itoa(config.Servant.Sys.BindPort), config.Servant.Log.OutputLevel, config.Servant.Log.MaxSizeKB, config.Servant.Log.MaxGeneration, config.Servant.Log.TimeoutSec); err != nil { console.Display("CTS023E", err) return rc_error } defer log.Term() console.Display("CTS001I", os.Getpid(), Version) // メイン処理開始 exitCode, err := Run() if err != nil { log.Error(err) exitCode = rc_error } console.Display("CTS002I", exitCode) return exitCode }
// 引数で指定したbind用のアドレスとポート番号portを指定してメッセージの受信待ちを開始する。 // 受信したメッセージは戻り値のchan stringに順番に挿入されていく。 // 引数で指定した多重度でチャネルを作成する。 // // 引数:bindAddr バインドアドレス // // 引数:port Listenポート番号 // // 引数:multi メッセージ受信の多重度 // // 戻り値:メッセージ受信を通知する、受信チャネル // // 戻り値:エラー情報 func StartReceive(bindAddr string, port int, multi int) (<-chan *Session, error) { addr := fmt.Sprintf("%s:%d", bindAddr, port) listener, err := net.Listen(protocol, addr) if err != nil { return nil, err } console.Display("CTS007I", bindAddr, port) sq := make(chan *Session, multi) go receiveLoop(listener, sq) return sq, nil }
// 設定ファイルを読み込む // 読み込みに失敗する場合はDefaultServantConfig関数でデフォルト値を設定する。 // // 戻り値: 設定値を格納したServantConfig構造体オブジェクト func ReadConfig(configPath string) *ServantConfig { var err error if len(configPath) > 0 { FilePath = configPath } Servant, err = loadFile(FilePath) if err != nil { console.Display("CTS004W", FilePath) Servant = DefaultServantConfig() } Servant.convertFullpath() return Servant }
// ネットワーク名nameを元にネットワーク定義ファイルをロードし、Network構造体のオブジェクトを返す。 // // param : name ジョブネットワーク名。 // // return : ジョブネットワーク構造体。 func LoadNetwork(name string) *Network { nwk, err := NewNetwork(name) if err != nil { console.Display("CTM019E", err) return nil } file, err := os.Open(nwk.MasterPath) if err != nil { console.Display("CTM010E", nwk.MasterPath) log.Error(err) return nil } defer file.Close() err = nwk.LoadElements(file) if err != nil { console.Display("CTM011E", nwk.MasterPath, err) return nil } return nwk }
func (s *Session) doRequest(req *message.Request, conf *config.ServantConfig) (string, error) { err := req.ExpandServantVars() if err != nil { console.Display("CTS015E", err.Error()) res := s.createErrorResponse(req, err) return res.GenerateJSON() } stCh := make(chan string, 1) go s.waitAndSendStartTime(stCh) defer close(stCh) res := s.doJobRequest(req, conf, stCh) return res.GenerateJSON() }
// セッションに対応した処理を実行する。 // 引数:conf 設定情報 // 戻り値:なし func (s *Session) Do(conf *config.ServantConfig) error { defer s.Conn.Close() defer s.endHeartbeat() var msg string req := new(message.Request) if err := req.ParseJSON(s.Body); err != nil { chk := new(message.JobCheck) if err := chk.ParseJSON(s.Body); err != nil { console.Display("CTS015E", err.Error()) return err } resultMsg, err := s.doJobCheck(chk, conf) if err != nil { log.Error(err) return err } msg = resultMsg } else { resMsg, err := s.doRequest(req, conf) if err != nil { log.Error(err) return err } msg = resMsg } if _, err := s.Conn.Write([]byte(msg + MsgEnd)); err != nil { log.Error(err) return err } return nil }
func realMain(args *arguments) int { if args.versionFlag == flag_ON { showVersion() return rc_OK } if args.networkName == "" && args.rerunInstance == 0 { showUsage() return rc_ERROR } if args.networkName != "" && args.rerunInstance != 0 { console.Display("CTM019E", "Cannot use both -n and -r option.") return rc_ERROR } if args.configPath == "" { args.configPath = defaultConfig } message.MasterVersion = Version if err := config.Load(args.configPath); err != nil { console.Display("CTM004E", args.configPath) return rc_ERROR } if err := config.DetectError(); err != nil { console.Display("CTM005E", err) return rc_ERROR } if err := log.Init(config.Dir.LogDir, "master", "", config.Log.OutputLevel, config.Log.MaxSizeKB, config.Log.MaxGeneration, config.Log.TimeoutSec); err != nil { console.Display("CTM021E", err) return rc_ERROR } defer log.Term() console.Display("CTM001I", os.Getpid(), Version) // master終了時のコンソール出力 var rc int defer func() { console.Display("CTM002I", rc) }() if args.rerunInstance != 0 { nwkResult, err := getNetworkResult(args.rerunInstance) if err != nil { console.Display("CTM019E", err) return rc_ERROR } if nwkResult.Status == db.NORMAL || nwkResult.Status == db.WARN { console.Display("CTM029I", args.rerunInstance) return rc_OK } args.networkName = nwkResult.JobnetWork args.startFlag = flag_ON } nwk := jobnet.LoadNetwork(args.networkName) if nwk == nil { rc = rc_ERROR return rc } defer nwk.Terminate() err := nwk.DetectFlowError() if err != nil { console.Display("CTM011E", nwk.MasterPath, err) rc = rc_ERROR return rc } if args.startFlag == flag_OFF { console.Display("CTM020I", nwk.MasterPath) rc = rc_OK return rc } err = nwk.LoadJobEx() if err != nil { console.Display("CTM004E", nwk.JobExPath) log.Error(err) rc = rc_ERROR return rc } if args.rerunInstance == 0 { err = nwk.Run() } else { nwk.ID = args.rerunInstance err = nwk.Rerun() } if err != nil { console.Display("CTM013I", nwk.Name, nwk.ID, "ABNORMAL") // ジョブ自体の異常終了では、エラーメッセージが空で返るので、出力しない if len(err.Error()) != 0 { log.Error(err) } rc = rc_ERROR return rc } console.Display("CTM013I", nwk.Name, nwk.ID, "NORMAL") rc = rc_OK return rc }
// オンラインヘルプを表示する。 func showUsage() { console.Display("CTM003E") fmt.Print(console.USAGE) }