func GenerateJobsCycle() { hostname, err := os.Hostname() if err != nil { log.Fatalf("Could not get hostname: %s", err.Error()) } log.Print("Initial select from RunQueue and starting launcher goroutines") if err := selectRQAndNotify(); err != nil { log.Fatalf("Could not do initial select run queue: %s", err.Error()) } log.Print("Initial select from Timetable") ttRows, err := selectTimetable() if err != nil { log.Fatalf("Could not do initial select timetable: %s", err.Error()) } log.Print("Starting jobgen goroutines") if err := notifyForFullTTSelect(ttRows, false); err != nil { log.Fatalf("Could notify about timetable: %s", err.Error()) } for { res, err := db.LockCycle(getLockName(), hostname) if err != nil || !res { if err == nil { log.Println("Could not get lock, another host holds it? Retrying in 10 seconds") } else { log.Warningf("Could not get lock, got DB error: ", err.Error()) } time.Sleep(time.Second * 10) continue } // timer := pinba.TimerStart(map[string]string{"group": "jobgenerator"}) startTs := time.Now().UnixNano() db.LogCycleStart(CYCLE_CLASS_NAME, hostname, 0) log.Debug("Cycle started") success := doCycle() log.Debug("Cycle finished") successInt := 1 if !success { successInt = 0 } db.LogCycleStop(CYCLE_CLASS_NAME, hostname, 0, successInt) passedMs := int64((time.Now().UnixNano() - startTs) / 1e6) if passedMs < cycleMs { time.Sleep(time.Duration(cycleMs-passedMs) * time.Millisecond) } } }
func NewProcess(id uint64, bin string, cmd string, args []string, stdout_file, stderr_file string) (*Vproc, error) { p := new(Vproc) p.Id = id p.Cmd = exec.Command(bin, cmd) var a = []string{bin, cmd} a = append(a, args...) p.Cmd.Args = a p.Cmd.Env = os.Environ() log.Debug("%v\n", a) stdout, err := os.OpenFile(stdout_file, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666) if err != nil { return nil, err } p.Cmd.Stdout = stdout stderr, err := os.OpenFile(stderr_file, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666) if err != nil { return nil, err } p.Cmd.Stderr = stderr return p, nil }
func main() { service.Initialize("conf/phproxyd.conf", &config) q, w, e := syscall.Syscall(syscall.SYS_GETPRIORITY, 1, 0, 0) log.Debug("GetPriority: %v %v %v", q, w, e) sh = newShardedCache(32) service.EventLoop(ports) }
func FinalizeRestartWithSuccess() { log.Debug("restarted successfuly") currentRestart.Pidfile.CloseAndRemove() currentRestart = nil }
// Call this when you want to start your servers and stuff func EventLoop(ports []Port) { defer log.Debug("exiting") initPhaseDuration = time.Since(startupTime) daemonConfig := config.GetDaemonConfig() // service-stats ports ports = append(ports, GpbPort("service-stats-gpb", stats_ctx, badoo_service.Gpbrpc)) ports = append(ports, JsonPort("service-stats-gpb/json", stats_ctx, badoo_service.Gpbrpc)) // build map of ports and do some sanity checks ph := make(map[string]*Port) for i := 0; i < len(ports); i++ { p := &ports[i] ph[p.Name] = p // json and gpb ports should have the same context // so try and warn user about passing plain values in (as it makes a copy) if reflect.ValueOf(p.Handler).Kind() != reflect.Ptr { log.Infof("port[%d].Handler should be a pointer (you want gpbs and json to use the same context, right?) (now: %T)", i, p.Handler) } } getRestartSocket := func(rcd *RestartChildData, portName, portAddr string) (*RestartSocket, *os.File) { if rcd == nil { return nil, nil } restartSocket, exists := rcd.GpbrpcSockets[portName] if exists == false { return nil, nil } restartFile := os.NewFile(restartSocket.Fd, "") if restartSocket.Address != portAddr { return nil, restartFile } return &restartSocket, restartFile } // start 'em all for _, lcf := range daemonConfig.GetListen() { portName, portAddr := lcf.GetProto(), lcf.GetAddress() port := ph[portName] if nil == port { log.Warnf("ignoring unknown port: %s at %s", portName, portAddr) continue } if port.IsStarted { log.Warnf("ignoring double startup for port: %s at %s", portName, portAddr) } listener, err := func() (listener net.Listener, err error) { // it's important that this should be a function, see defer inside restartSocket, restartFile := getRestartSocket(restartData, portName, portAddr) // this whole fd/file affair is very inconvenient to // since when getRestartSocket() returns fd - it can't close it yet, as it can be used by FileListener defer restartFile.Close() if restartSocket == nil { listener, err = net.Listen("tcp", portAddr) if err != nil { log.Errorf("listen failed for server %s at %s: %s", portName, portAddr, err) return } log.Infof("port %s bound to address %s", portName, listener.Addr()) } else { listener, err = net.FileListener(restartFile) // this dup()-s if err != nil { log.Errorf("failed to grab parent fd %d for %s at %s: %s", restartSocket.Fd, portName, portAddr, err) return } log.Infof("port %s bound to address %s (parent fd: %d)", portName, listener.Addr(), restartSocket.Fd) } return }() if err != nil { os.Exit(1) } // enable pinba only for ports that explicitly request it ps := func() gpbrpc.PinbaSender { if !lcf.GetPinbaEnabled() { return nil // explicit nil here } if pinbaSender == nil { log.Warnf("pinba is not configured, but pinba_enabled IS set for port %s: %s", portName, portAddr) return nil // explicit nil here } log.Infof("pinba configured for port %s:%s -> %s", portName, portAddr, pinbaSender.Address) return pinbaSender }() // slow request log time slowRequestTime := time.Duration(daemonConfig.GetSlowRequestMs()) * time.Millisecond srv := &Server{ Name: lcf.GetProto(), Address: lcf.GetAddress(), Server: gpbrpc.NewServer(listener, port.Proto, port.Codec, port.Handler, ps, slowRequestTime), } go srv.Server.Serve() port.IsStarted = true StartedServers[port.Name] = srv // save it for laterz } // kill parent if this is a child of graceful restart if restartData != nil { syscall.Kill(restartData.PPid, syscall.SIGQUIT) } log.Infof("entering event loop") exitMethod := wait_for_signals() if exitMethod == EXIT_GRACEFULLY { // wait for established connections to close and then die // FIXME: should stop servers from accepting new connections here! const ATTEMPTS_PER_SEC = 2 maxAttempts := daemonConfig.GetParentWaitTimeout() * ATTEMPTS_PER_SEC for i := uint32(0); i < maxAttempts; i++ { for _, srv := range StartedServers { currConn := atomic.LoadUint64(&srv.Server.Stats.ConnCur) if currConn > 0 { log.Debugf("%s still has %d connections", srv.Name, currConn) time.Sleep(time.Second / ATTEMPTS_PER_SEC) } } } } else { // do nothing for EXIT_IMMEDIATELY } // doing cleanups here // XXX: can this be moved to defer at the start of this function? if pidfile != nil { pidfile.CloseAndRemove() } }