func doCycle() bool { var ( jiRows map[string]map[string]*JobInfoEntry scripts map[string]*ScriptEntry flags map[string]*FlagEntry scriptsRusage map[string]*ScriptRusageEntry classLocTTRows map[string]map[string][]*TimetableEntry ) unifiedStartTs := time.Now().UnixNano() startTs := time.Now().UnixNano() err := loadFullState( &LoadStateFunc{name: "Scripts", fun: func() (err error) { scripts, err = getGroupedScriptsForPlatform(); return }}, &LoadStateFunc{name: "JobInfo", fun: func() (err error) { jiRows, err = getGroupedJobInfo(); return }}, &LoadStateFunc{name: "Flags", fun: func() (err error) { flags, err = getFlags(); return }}, &LoadStateFunc{name: "ScriptsRusage", fun: func() (err error) { scriptsRusage, err = getScriptRusageStats(); return }}, &LoadStateFunc{name: "ScriptTimetable", fun: func() (err error) { classLocTTRows, err = selectTimetable(); return }}) if err != nil { log.Errorf("Failed to select state in doCycle: %s", err.Error()) return false } log.Debugf("Loaded for %.5f sec", float64(time.Now().UnixNano()-startTs)/1e9) startTs = time.Now().UnixNano() err = loadSettingsFromRows(jiRows, scripts) if err != nil { log.Errorf("Could not load settings from rows: %s", err.Error()) return false } func() { allSettingsMutex.Lock() defer allSettingsMutex.Unlock() for _, row := range scripts { row.settings = allSettings[row.settings_id] } }() scriptsMap.Lock() scriptsMap.v = scripts scriptsMap.Unlock() log.Debugf(" Selected %d rows from flags", len(flags)) log.Debugf(" Selected %d rows from scripts rusage", len(scriptsRusage)) log.Debugf("Load settings for %.5f sec", float64(time.Now().UnixNano()-startTs)/1e9) startTs = time.Now().UnixNano() // We should not try to generate jobs for scripts that are not present in Script table // But we should not forget settings (e.g. last generation_id) for that script for class_name := range jiRows { if _, ok := scripts[class_name]; !ok { delete(jiRows, class_name) } } log.Debugf("Selected all for %.5f sec", float64(time.Now().UnixNano()-unifiedStartTs)/1e9) startTs = time.Now().UnixNano() updateLoadEstimates() log.Debugf("Load estimates updated for %.5f sec", float64(time.Now().UnixNano()-startTs)/1e9) func() { rusageInfo.Lock() defer rusageInfo.Unlock() log.Debugf("Group hosts: %+v", rusageInfo.groupHosts) }() startTs = time.Now().UnixNano() failedLocationsMutex.Lock() failedLocations = make(map[string]bool) failedLocationsMutex.Unlock() success := true if len(scripts) > 0 { throttle.setIntervalCh <- time.Second / time.Duration(len(scripts)) } trigger(throttle.c, "throttle, start of cycle") for className, script := range scripts { <-throttle.c tx := new(db.LazyTrx) err := tx.Begin() if err != nil { log.Errorf("Could not start transaction in job generate: %s", err.Error()) success = false continue } have := make(map[string]bool) locTtRows := classLocTTRows[className] if locTtRows != nil { for rawLoc, v := range locTtRows { loc, err := getLocationIdx(script.settings.location_type, rawLoc) if err != nil { log.Warningf("Broken settings for class %s: %s", className, err.Error()) loc = rawLoc } if len(v) > 0 { have[loc] = true } } } add_to_timetable, err := generateJobs(tx, className, script.settings, jiRows[className], have, flags[className]) if err != nil { log.Errorf("Could generate jobs for class %s: %s", className, err.Error()) tx.Rollback() success = false continue } err = tx.Commit() if err != nil { log.Errorf("Could not commit generate jobs for class %s: %s", className, err.Error()) success = false continue } per_location := make(map[string][]*TimetableEntry) for _, row := range add_to_timetable { allSettingsMutex.Lock() row.settings = allSettings[row.settings_id] allSettingsMutex.Unlock() if row.settings == nil { log.Warningf("Internal inconsistency error: Invalid settings for generated row: %+v", row) continue } key := DEFAULT_LOCATION_IDX if row.settings.location_type == LOCATION_TYPE_EACH { key = row.location } if _, ok := per_location[key]; !ok { per_location[key] = make([]*TimetableEntry, 0) } per_location[key] = append(per_location[key], row) } for location, rows := range per_location { notifyAboutNewTTRows(className, location, rows, true) } } notifyForFullTTSelect(classLocTTRows, true) log.Debugf("Processed %d classes for %.5f sec", len(scripts), float64(time.Now().UnixNano()-startTs)/1e9) log.Debugf("Total %.5f sec", float64(time.Now().UnixNano()-unifiedStartTs)/1e9) return success }