Exemplo n.º 1
0
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)
		}
	}
}
Exemplo n.º 2
0
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
}
Exemplo n.º 3
0
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)
}
Exemplo n.º 4
0
func FinalizeRestartWithSuccess() {
	log.Debug("restarted successfuly")
	currentRestart.Pidfile.CloseAndRemove()
	currentRestart = nil
}
Exemplo n.º 5
0
// 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()
	}
}