<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/docker/docker/pkg/namesgenerator"

	"github.com/ovh/cds/engine/api/hatchery"
	"github.com/ovh/cds/engine/log"
	"github.com/ovh/cds/sdk"
)

// HatcheryLocal implements HatcheryMode interface for local usage
type HatcheryLocal struct {
	sync.Mutex
	hatch         *hatchery.Hatchery
	basedir       string
	workers       map[string]*exec.Cmd
	workerModelID int64
}

// SetWorkerModelID set the workerModelIDon each heartbeat
func (h *HatcheryLocal) SetWorkerModelID(id int64) {
	h.workerModelID = id
}

// Mode must returns hatchery mode
func (h *HatcheryLocal) Mode() string {
	if h == nil {
		return ""
	}
	return LocalMode
}

// ID must returns hatchery id
func (h *HatcheryLocal) ID() int64 {
	if h.hatch == nil {
		return 0
	}
	return h.hatch.ID
}

//Hatchery returns hatchery instance
func (h *HatcheryLocal) Hatchery() *hatchery.Hatchery {
	return h.hatch
}

// CanSpawn return wether or not hatchery can spawn model.
// requirements are not supported
func (h *HatcheryLocal) CanSpawn(model *sdk.Model, req []sdk.Requirement) bool {
	if model.ID != h.workerModelID {
		return false
	}
	if len(req) > 0 {
		return false
	}
	return true
}

// KillWorker kill a local process
func (h *HatcheryLocal) KillWorker(worker sdk.Worker) error {
	for name, cmd := range h.workers {
		if worker.Name == name {
			log.Notice("KillLocalWorker> Killing %s\n", worker.Name)
			return cmd.Process.Kill()
		}
	}

	return fmt.Errorf("Worker not found")
}

// SpawnWorker starts a new worker process
func (h *HatcheryLocal) SpawnWorker(wm *sdk.Model, req []sdk.Requirement) error {
	var err error

	if len(h.workers) >= maxWorker {
		return fmt.Errorf("Max capacity reached (%d)\n", maxWorker)
	}

	wName := fmt.Sprintf("%s-%s", h.hatch.Name, namesgenerator.GetRandomName(0))

	var args []string
	args = append(args, fmt.Sprintf("--api=%s", sdk.Host))
	args = append(args, fmt.Sprintf("--key=%s", uk))
	args = append(args, fmt.Sprintf("--basedir=%s", h.basedir))
	args = append(args, fmt.Sprintf("--model=%d", h.workerModelID))
	args = append(args, fmt.Sprintf("--name=%s", wName))
	args = append(args, fmt.Sprintf("--hatchery=%d", h.hatch.ID))
	args = append(args, "--single-use")

	cmd := exec.Command("worker", args...)

	// Clearenv
	cmd.Env = []string{}
	env := os.Environ()
	for _, e := range env {
		if !strings.HasPrefix(e, "CDS") && !strings.HasPrefix(e, "HATCHERY") {
			cmd.Env = append(cmd.Env, e)
		}
	}

	if err = cmd.Start(); err != nil {
		return err
	}
	h.Lock()
	h.workers[wName] = cmd
	h.Unlock()

	// Wait in a goroutine so that when process exits, Wait() update cmd.ProcessState
	go func() {
		cmd.Wait()
	}()
	return nil
}

// WorkerStarted returns the number of instances of given model started but
// not necessarily register on CDS yet
func (h *HatcheryLocal) WorkerStarted(model *sdk.Model) int {
	h.localWorkerIndexCleanup()
	var x int
	for name := range h.workers {
		if strings.Contains(name, model.Name) {
			x++
		}
	}

	return x
}

// ParseConfig for local mode
func (h *HatcheryLocal) ParseConfig() {
	h.basedir = os.Getenv("BASEDIR")
	if h.basedir == "" {
		sdk.Exit("basedir not provided, aborting\n")
	}
}

// Init register local hatchery with its worker model
func (h *HatcheryLocal) Init() error {
	h.workers = make(map[string]*exec.Cmd)

	name, err := os.Hostname()
	if err != nil {
		log.Warning("Cannot retrieve hostname: %s\n", err)
	}

	req, err := sdk.GetRequirements()
	if err != nil {
		log.Warning("Cannot fetch requirements: %s\n", err)
	}

	capa, err := checkCapabilities(req)
	if err != nil {
		log.Warning("Cannot check local capabilities: %s\n", err)
	}

	h.hatch = &hatchery.Hatchery{
		Name: name,
		UID:  uk,
		Model: sdk.Model{
			Name:         name,
			Image:        name,
			Capabilities: capa,
		},
	}

	h.workerModelID = h.hatch.Model.ID

	go h.startKillAwolWorkerRoutine()
	return nil<commit_msg>fix (hatchery): register local hatchery<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/docker/docker/pkg/namesgenerator"

	"github.com/ovh/cds/engine/api/hatchery"
	"github.com/ovh/cds/engine/log"
	"github.com/ovh/cds/sdk"
)

// HatcheryLocal implements HatcheryMode interface for local usage
type HatcheryLocal struct {
	sync.Mutex
	hatch         *hatchery.Hatchery
	basedir       string
	workers       map[string]*exec.Cmd
	workerModelID int64
}

// SetWorkerModelID set the workerModelIDon each heartbeat
func (h *HatcheryLocal) SetWorkerModelID(id int64) {
	h.workerModelID = id
}

// Mode must returns hatchery mode
func (h *HatcheryLocal) Mode() string {
	if h == nil {
		return ""
	}
	return LocalMode
}

// ID must returns hatchery id
func (h *HatcheryLocal) ID() int64 {
	if h.hatch == nil {
		return 0
	}
	return h.hatch.ID
}

//Hatchery returns hatchery instance
func (h *HatcheryLocal) Hatchery() *hatchery.Hatchery {
	return h.hatch
}

// CanSpawn return wether or not hatchery can spawn model.
// requirements are not supported
func (h *HatcheryLocal) CanSpawn(model *sdk.Model, req []sdk.Requirement) bool {
	if model.ID != h.workerModelID {
		return false
	}
	if len(req) > 0 {
		return false
	}
	return true
}

// KillWorker kill a local process
func (h *HatcheryLocal) KillWorker(worker sdk.Worker) error {
	for name, cmd := range h.workers {
		if worker.Name == name {
			log.Notice("KillLocalWorker> Killing %s\n", worker.Name)
			return cmd.Process.Kill()
		}
	}

	return fmt.Errorf("Worker not found")
}

// SpawnWorker starts a new worker process
func (h *HatcheryLocal) SpawnWorker(wm *sdk.Model, req []sdk.Requirement) error {
	var err error

	if len(h.workers) >= maxWorker {
		return fmt.Errorf("Max capacity reached (%d)\n", maxWorker)
	}

	wName := fmt.Sprintf("%s-%s", h.hatch.Name, namesgenerator.GetRandomName(0))

	var args []string
	args = append(args, fmt.Sprintf("--api=%s", sdk.Host))
	args = append(args, fmt.Sprintf("--key=%s", uk))
	args = append(args, fmt.Sprintf("--basedir=%s", h.basedir))
	args = append(args, fmt.Sprintf("--model=%d", h.workerModelID))
	args = append(args, fmt.Sprintf("--name=%s", wName))
	args = append(args, fmt.Sprintf("--hatchery=%d", h.hatch.ID))
	args = append(args, "--single-use")

	cmd := exec.Command("worker", args...)

	// Clearenv
	cmd.Env = []string{}
	env := os.Environ()
	for _, e := range env {
		if !strings.HasPrefix(e, "CDS") && !strings.HasPrefix(e, "HATCHERY") {
			cmd.Env = append(cmd.Env, e)
		}
	}

	if err = cmd.Start(); err != nil {
		return err
	}
	h.Lock()
	h.workers[wName] = cmd
	h.Unlock()

	// Wait in a goroutine so that when process exits, Wait() update cmd.ProcessState
	go func() {
		cmd.Wait()
	}()
	return nil
}

// WorkerStarted returns the number of instances of given model started but
// not necessarily register on CDS yet
func (h *HatcheryLocal) WorkerStarted(model *sdk.Model) int {
	h.localWorkerIndexCleanup()
	var x int
	for name := range h.workers {
		if strings.Contains(name, model.Name) {
			x++
		}
	}

	return x
}

// ParseConfig for local mode
func (h *HatcheryLocal) ParseConfig() {
	h.basedir = os.Getenv("BASEDIR")
	if h.basedir == "" {
		sdk.Exit("basedir not provided, aborting\n")
	}
}

// Init register local hatchery with its worker model
func (h *HatcheryLocal) Init() error {
	h.workers = make(map[string]*exec.Cmd)

	name, err := os.Hostname()
	if err != nil {
		log.Warning("Cannot retrieve hostname: %s\n", err)
	}

	req, err := sdk.GetRequirements()
	if err != nil {
		log.Warning("Cannot fetch requirements: %s\n", err)
	}

	capa, err := checkCapabilities(req)
	if err != nil {
		log.Warning("Cannot check local capabilities: %s\n", err)
	}

	h.hatch = &hatchery.Hatchery{
		Name: name,
		UID:  uk,
		Model: sdk.Model{
			Name:         name,
			Image:        name,
			Capabilities: capa,
		},
	}

	h.workerModelID = h.hatch.Model.ID

	if err := register(h.hatch); err != nil {
		log.Warning("Cannot register hatchery: %s\n", err)
		return err
	}

	go h.startKillAwolWorkerRoutine()
	return nil
{'fraction_non_alphanumeric': 0.14654205607476636, 'fraction_numerical': 0.0022429906542056075, 'mean_word_length': 3.6047045324153757, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '628093', 'n_tokens_mistral': 3076, 'n_tokens_neox': 2974, 'n_words': 777}