// launchTask instantiates an invocation controller and calls its LaunchTask
// method, saving the invocation state when its done.
//
// It returns a transient error if the launch attempt should be retried.
322449
func (e *engineImpl) launchTask(c context.Context, inv *Invocation) error {
	assertNotInTransaction(c)

	// Grab the corresponding TaskManager to launch the task through it.
	ctl, err := controllerForInvocation(c, e, inv)
	if err != nil {
		// Note: controllerForInvocation returns both ctl and err on errors, with
		// ctl not fully initialized (but good enough for what's done below).
		ctl.DebugLog("Failed to initialize task controller - %s", err)
		ctl.State().Status = task.StatusFailed
		return ctl.Save(c)
	}

	// Ask the manager to start the task. If it returns no errors, it should also
	// move the invocation out of an initial state (a failure to do so is a fatal
	// error). If it returns an error, the invocation is forcefully moved to
	// StatusRetrying or StatusFailed state (depending on whether the error is
	// transient or not and how many retries are left). In either case, invocation
	// never ends up in StatusStarting state.
	err = ctl.manager.LaunchTask(c, ctl)
	if err != nil {
		logging.WithError(err).Errorf(c, "Failed to LaunchTask")
	}
	if status := ctl.State().Status; status.Initial() && err == nil {
		err = fmt.Errorf("LaunchTask didn't move invocation out of initial %s state", status)
	}
	if transient.Tag.In(err) && inv.RetryCount+1 >= invocationRetryLimit {
		err = fmt.Errorf("Too many retries, giving up (original error - %s)", err)
	}

	// The task must always end up in a non-initial state. Do it on behalf of the
	// controller if necessary.
	if ctl.State().Status.Initial() {
		if transient.Tag.In(err) {
			// This invocation object will be reused for a retry later.
			ctl.State().Status = task.StatusRetrying
		} else {
			// The invocation has crashed with the fatal error.
			ctl.State().Status = task.StatusFailed
		}
	}

	// Add a notice into the invocation log that we'll attempt to retry.
	isRetrying := ctl.State().Status == task.StatusRetrying
	if isRetrying {
		ctl.DebugLog("The invocation will be retried")
	}

	// We MUST commit the state of the invocation. A failure to save the state
	// may cause the job state machine to get stuck. If we can't save it, we need
	// to retry the whole launch attempt from scratch (redoing all the work,
	// a properly implemented LaunchTask should be idempotent).
	if err := ctl.Save(c); err != nil {
		logging.WithError(err).Errorf(c, "Failed to save invocation state")
		return err
	}

	// Task retries happen via the task queue, need to explicitly trigger a retry
	// by returning a transient error.
	if isRetrying {
		return errRetryingLaunch
	}

	return nil
}
532067
func FlattenBatchPoolStartTask(startTask *batch.StartTask) []interface{} {
	results := make([]interface{}, 0)

	if startTask == nil {
		log.Printf("[DEBUG] startTask is nil")
		return results
	}

	result := make(map[string]interface{})
	if startTask.CommandLine != nil {
		result["command_line"] = *startTask.CommandLine
	}
	if startTask.WaitForSuccess != nil {
		result["wait_for_success"] = *startTask.WaitForSuccess
	}
	if startTask.MaxTaskRetryCount != nil {
		result["max_task_retry_count"] = *startTask.MaxTaskRetryCount
	}

	if startTask.UserIdentity != nil {
		userIdentity := make(map[string]interface{})
		if startTask.UserIdentity.AutoUser != nil {
			autoUser := make(map[string]interface{})

			elevationLevel := string(startTask.UserIdentity.AutoUser.ElevationLevel)
			scope := string(startTask.UserIdentity.AutoUser.Scope)

			autoUser["elevation_level"] = elevationLevel
			autoUser["scope"] = scope

			userIdentity["auto_user"] = []interface{}{autoUser}
		} else {
			userIdentity["user_name"] = *startTask.UserIdentity.UserName
		}

		result["user_identity"] = []interface{}{userIdentity}
	}

	resourceFiles := make([]interface{}, 0)
	if startTask.ResourceFiles != nil {
		for _, armResourceFile := range *startTask.ResourceFiles {
			resourceFile := make(map[string]interface{})
			if armResourceFile.AutoStorageContainerName != nil {
				resourceFile["auto_storage_container_name"] = *armResourceFile.AutoStorageContainerName
			}
			if armResourceFile.StorageContainerURL != nil {
				resourceFile["storage_container_url"] = *armResourceFile.StorageContainerURL
			}
			if armResourceFile.HTTPURL != nil {
				resourceFile["http_url"] = *armResourceFile.HTTPURL
			}
			if armResourceFile.BlobPrefix != nil {
				resourceFile["blob_prefix"] = *armResourceFile.BlobPrefix
			}
			if armResourceFile.FilePath != nil {
				resourceFile["file_path"] = *armResourceFile.FilePath
			}
			if armResourceFile.FileMode != nil {
				resourceFile["file_mode"] = *armResourceFile.FileMode
			}
			resourceFiles = append(resourceFiles, resourceFile)
		}
	}

	if startTask.EnvironmentSettings != nil {
		environment := make(map[string]interface{})
		for _, envSetting := range *startTask.EnvironmentSettings {
			environment[*envSetting.Name] = *envSetting.Value
		}

		result["environment"] = environment
	}
	result["resource_file"] = resourceFiles

	return append(results, result)
}
655082
func (l *DefaultLifecycle) addTask(t *Task) {
	l.rmu.Lock()
	defer l.rmu.Unlock()

	l.registry = append([]*Task{t}, l.registry...)
	l.wg.Add(1)
}
1206084
func (m TaskManager) AbortTask(c context.Context, ctl task.Controller) error {
	// This can happen if the invocation is aborted before it has even started.
	// We don't have buildbucket build ID yet to cancel.
	//
	// There's a high chance that LaunchTask is executing concurrently somewhere.
	// We let it finish peacefully, by not touching the invocation state at all
	// and failing with a transient error instead. This avoids a collision on
	// State modification. When such collision happens, results of LaunchTask
	// (including a fresh build ID) are discarded (as the engine is unable to
	// "merge" conflicting mutations from two different state transitions). This
	// is really bad, since this process produces orphaned Buildbucket builds.
	//
	// So we pick a lesser evil and make AbortTask fail transiently while
	// invocation is starting.
	if status := ctl.State().Status; status.Initial() {
		return errors.Reason("can't abort Buildbucket invocation in state %q", status).Tag(transient.Tag).Err()
	}

	// Grab build ID from the blob generated in LaunchTask.
	taskData, err := readTaskData(ctl)
	if err != nil {
		ctl.State().Status = task.StatusFailed
		return err
	}

	// Ask Buildbucket to kill this build.
	return utils.WrapAPIError(m.withBuildbucket(c, ctl, func(c context.Context, bb *bbv1.Service) error {
		_, err := bb.Cancel(taskData.BuildID, &bbv1.ApiCancelRequestBodyMessage{}).Context(c).Do()
		return err
	}))
}
713860
func (a *Client) CreateTask(params *CreateTaskParams, authInfo runtime.ClientAuthInfoWriter) (*CreateTaskCreated, error) {
	// TODO: Validate the params before sending
	if params == nil {
		params = NewCreateTaskParams()
	}

	result, err := a.transport.Submit(&runtime.ClientOperation{
		ID:                 "createTask",
		Method:             "POST",
		PathPattern:        "/tasks",
		ProducesMediaTypes: []string{"application/vnd.goswagger.examples.task-tracker.v1+json"},
		ConsumesMediaTypes: []string{"application/vnd.goswagger.examples.task-tracker.v1+json"},
		Schemes:            []string{"http", "https"},
		Params:             params,
		Reader:             &CreateTaskReader{formats: a.formats},
		AuthInfo:           authInfo,
		Context:            params.Context,
		Client:             params.HTTPClient,
	})
	if err != nil {
		return nil, err
	}
	return result.(*CreateTaskCreated), nil

}
1172550
func (s *scheduler) GetTask(id string) (core.Task, error) {
	t, err := s.getTask(id)
	if err != nil {
		schedulerLogger.WithFields(log.Fields{
			"_block":  "get-task",
			"_error":  ErrTaskNotFound,
			"task-id": id,
		}).Error("error getting task")
		return nil, err // We do this to send back an explicit nil on the interface
	}
	return t, nil
}
552508
func (s *scheduler) CreateTask(sch schedule.Schedule, wfMap *wmap.WorkflowMap, startOnCreate bool, opts ...core.TaskOption) (core.Task, core.TaskErrors) {
	return s.createTask(sch, wfMap, startOnCreate, "user", opts...)
}
1043990
func (c *Client) StartTask(id string) *StartTasksResult {
	resp, err := c.do("PUT", fmt.Sprintf("/tasks/%v/start", id), ContentTypeJSON)

	if err != nil {
		return &StartTasksResult{Err: err}
	}

	switch resp.Meta.Type {
	case rbody.ScheduledTaskStartedType:
		// Success
		return &StartTasksResult{resp.Body.(*rbody.ScheduledTaskStarted), nil}
	case rbody.ErrorType:
		return &StartTasksResult{Err: resp.Body.(*rbody.Error)}
	default:
		return &StartTasksResult{Err: ErrAPIResponseMetaType}
	}
}
745186
func ApiTaskToStructsTask(apiTask *api.Task, structsTask *structs.Task) {
	structsTask.Name = apiTask.Name
	structsTask.Driver = apiTask.Driver
	structsTask.User = apiTask.User
	structsTask.Leader = apiTask.Leader
	structsTask.Config = apiTask.Config
	structsTask.Env = apiTask.Env
	structsTask.Meta = apiTask.Meta
	structsTask.KillTimeout = *apiTask.KillTimeout
	structsTask.ShutdownDelay = apiTask.ShutdownDelay
	structsTask.KillSignal = apiTask.KillSignal
	structsTask.Constraints = ApiConstraintsToStructs(apiTask.Constraints)
	structsTask.Affinities = ApiAffinitiesToStructs(apiTask.Affinities)

	if l := len(apiTask.Services); l != 0 {
		structsTask.Services = make([]*structs.Service, l)
		for i, service := range apiTask.Services {
			structsTask.Services[i] = &structs.Service{
				Name:        service.Name,
				PortLabel:   service.PortLabel,
				Tags:        service.Tags,
				CanaryTags:  service.CanaryTags,
				AddressMode: service.AddressMode,
			}

			if l := len(service.Checks); l != 0 {
				structsTask.Services[i].Checks = make([]*structs.ServiceCheck, l)
				for j, check := range service.Checks {
					structsTask.Services[i].Checks[j] = &structs.ServiceCheck{
						Name:          check.Name,
						Type:          check.Type,
						Command:       check.Command,
						Args:          check.Args,
						Path:          check.Path,
						Protocol:      check.Protocol,
						PortLabel:     check.PortLabel,
						AddressMode:   check.AddressMode,
						Interval:      check.Interval,
						Timeout:       check.Timeout,
						InitialStatus: check.InitialStatus,
						TLSSkipVerify: check.TLSSkipVerify,
						Header:        check.Header,
						Method:        check.Method,
						GRPCService:   check.GRPCService,
						GRPCUseTLS:    check.GRPCUseTLS,
					}
					if check.CheckRestart != nil {
						structsTask.Services[i].Checks[j].CheckRestart = &structs.CheckRestart{
							Limit:          check.CheckRestart.Limit,
							Grace:          *check.CheckRestart.Grace,
							IgnoreWarnings: check.CheckRestart.IgnoreWarnings,
						}
					}
				}
			}
		}
	}

	structsTask.Resources = ApiResourcesToStructs(apiTask.Resources)

	structsTask.LogConfig = &structs.LogConfig{
		MaxFiles:      *apiTask.LogConfig.MaxFiles,
		MaxFileSizeMB: *apiTask.LogConfig.MaxFileSizeMB,
	}

	if l := len(apiTask.Artifacts); l != 0 {
		structsTask.Artifacts = make([]*structs.TaskArtifact, l)
		for k, ta := range apiTask.Artifacts {
			structsTask.Artifacts[k] = &structs.TaskArtifact{
				GetterSource:  *ta.GetterSource,
				GetterOptions: ta.GetterOptions,
				GetterMode:    *ta.GetterMode,
				RelativeDest:  *ta.RelativeDest,
			}
		}
	}

	if apiTask.Vault != nil {
		structsTask.Vault = &structs.Vault{
			Policies:     apiTask.Vault.Policies,
			Env:          *apiTask.Vault.Env,
			ChangeMode:   *apiTask.Vault.ChangeMode,
			ChangeSignal: *apiTask.Vault.ChangeSignal,
		}
	}

	if l := len(apiTask.Templates); l != 0 {
		structsTask.Templates = make([]*structs.Template, l)
		for i, template := range apiTask.Templates {
			structsTask.Templates[i] = &structs.Template{
				SourcePath:   *template.SourcePath,
				DestPath:     *template.DestPath,
				EmbeddedTmpl: *template.EmbeddedTmpl,
				ChangeMode:   *template.ChangeMode,
				ChangeSignal: *template.ChangeSignal,
				Splay:        *template.Splay,
				Perms:        *template.Perms,
				LeftDelim:    *template.LeftDelim,
				RightDelim:   *template.RightDelim,
				Envvars:      *template.Envvars,
				VaultGrace:   *template.VaultGrace,
			}
		}
	}

	if apiTask.DispatchPayload != nil {
		structsTask.DispatchPayload = &structs.DispatchPayloadConfig{
			File: apiTask.DispatchPayload.File,
		}
	}
}
694431
func (e *engineImpl) execLaunchInvocationTask(c context.Context, tqTask proto.Message) error {
	msg := tqTask.(*internal.LaunchInvocationTask)

	c = logging.SetField(c, "JobID", msg.JobId)
	c = logging.SetField(c, "InvID", msg.InvId)

	hdrs, err := tq.RequestHeaders(c)
	if err != nil {
		return err
	}
	retryCount := hdrs.TaskExecutionCount // 0 for the first attempt
	if retryCount != 0 {
		logging.Warningf(c, "This is a retry (attempt %d)!", retryCount+1)
	}

	// Fetch up-to-date state of the invocation, verify we still need to start it.
	// Log that we are about to do it. We MUST write something to the datastore
	// before attempting the launch to make sure that if the datastore is in read
	// only mode (that happens), we don't spam LaunchTask retries when failing to
	// Save() the state in the end (better to fail now, before LaunchTask call).
	var skipLaunch bool
	var lastInvState Invocation
	logging.Infof(c, "Opening the invocation transaction")
	err = runTxn(c, func(c context.Context) error {
		skipLaunch = false // reset in case the transaction is retried

		// Grab up-to-date invocation state.
		inv := Invocation{ID: msg.InvId}
		switch err := ds.Get(c, &inv); {
		case err == ds.ErrNoSuchEntity:
			// This generally should not happen.
			logging.Warningf(c, "The invocation is unexpectedly gone")
			skipLaunch = true
			return nil
		case err != nil:
			return transient.Tag.Apply(err)
		case !inv.Status.Initial():
			logging.Warningf(c, "The invocation is already running or finished: %s", inv.Status)
			skipLaunch = true
			return nil
		}

		// The invocation is still starting or being retried now. Update its state
		// to indicate we are about to work with it. 'lastInvState' is later passed
		// to the task controller.
		lastInvState = inv
		lastInvState.RetryCount = retryCount
		lastInvState.MutationsCount++
		if retryCount >= invocationRetryLimit {
			logging.Errorf(c, "Too many attempts, giving up")
			lastInvState.debugLog(c, "Too many attempts, giving up")
			lastInvState.Status = task.StatusFailed
			lastInvState.Finished = clock.Now(c).UTC()
			skipLaunch = true
		} else {
			lastInvState.debugLog(c, "Starting the invocation (attempt %d)", retryCount+1)
		}

		// Make sure to trigger all necessary side effects, particularly important
		// if the invocation was moved to Failed state above.
		if err := e.invChanging(c, &inv, &lastInvState, nil, nil); err != nil {
			return err
		}

		// Store the updated invocation.
		lastInvState.trimDebugLog()
		return transient.Tag.Apply(ds.Put(c, &lastInvState))
	})

	switch {
	case err != nil:
		logging.WithError(err).Errorf(c, "Failed to update the invocation")
		return err
	case skipLaunch:
		logging.Warningf(c, "No need to start the invocation anymore")
		return nil
	}

	logging.Infof(c, "Actually launching the task")
	return e.launchTask(c, &lastInvState)
}
1051949
func (s *scheduler) EnableTask(id string) (core.Task, error) {
	t, e := s.getTask(id)
	if e != nil {
		schedulerLogger.WithFields(log.Fields{
			"_block":  "enable-task",
			"_error":  ErrTaskNotFound,
			"task-id": id,
		}).Error("error enabling task")
		return nil, e
	}

	err := t.Enable()
	if err != nil {
		schedulerLogger.WithFields(log.Fields{
			"_block":  "enable-task",
			"_error":  err.Error(),
			"task-id": id,
		}).Error("error enabling task")
		return nil, err
	}
	schedulerLogger.WithFields(log.Fields{
		"_block":     "enable-task",
		"task-id":    t.ID(),
		"task-state": t.State(),
	}).Info("task enabled")
	return t, nil
}
107799
func dbRspProcessingTask(c *asyncConnHdl, ctl workerCtl) (sig *interrupt_code, te *taskStatus) {

	var req asyncReqPtr
	select {
	case sig := <-ctl:
		// interrupted
		return &sig, &ok_status
	case req = <-c.pendingResps:
		// continue to process
	}

	// process response to asyncRequest
	reader := c.super.reader
	cmd := req.cmd

	resp, e3 := GetResponse(reader, cmd) // REVU - protocol modified to handle VIRTUALS
	if e3 != nil {
		// system error
		log.Println("<TEMP DEBUG> Request sent to faults chan on error in GetResponse: ", e3)
		req.stat = rcverr
		req.error = newSystemErrorWithCause("GetResponse os.Error", e3)
		c.faults <- req
		return nil, &taskStatus{rcverr, e3}
	}

	// if responsed processed was for cmd QUIT then signal the rest of the crew
	// REVU - ok, a bit hacky but it works.
	if cmd == &QUIT {
		c.feedback <- workerStatus{0, quit_processed, nil, nil}
		fakesig := pause
		c.isShutdown = true
		SetFutureResult(req.future, cmd, resp)
		return &fakesig, &ok_status
	}

	SetFutureResult(req.future, cmd, resp)
	return nil, &ok_status
}
1372082
func launchService(s *server.Server, done chan struct{}) error {

	if !runServiceFlag {
		return nil
	}

	h := &handler{
		fromsvc: make(chan error),
		s:       s,
		done:    done,
	}

	interactive, err := svc.IsAnInteractiveSession()
	if err != nil {
		return err
	}

	service = h
	go func() {
		if interactive {
			err = debug.Run(serviceNameFlag, h)
		} else {
			err = svc.Run(serviceNameFlag, h)
		}
		h.fromsvc <- err
	}()

	// Wait for the first signal from the service handler.
	err = <-h.fromsvc
	if err != nil {
		return err
	}
	return nil
}
1109878
func (g *TaskGroup) AddTask(t *Task) *TaskGroup {
	g.Tasks = append(g.Tasks, t)
	return g
}
922696
func successTask(id string, cacheable Cacheable) task {
	return func(c *cache) error {
		// Check for discarded Cacheable first.
		if c.buckets[id] == nil {
			return nil
		}
		// Set bucket values.
		b := c.buckets[id]
		b.cacheable = cacheable
		b.status = statusLoaded
		b.loaded = time.Now()
		b.lastUsed = b.loaded
		// Notify all waiters.
		for _, waiter := range c.buckets[id].waiters {
			waiter <- func() (Cacheable, error) {
				return cacheable, nil
			}
		}
		b.waiters = nil
		return nil
	}
}
593610
func (s *Server) GetTask(ctx context.Context, request *api.GetTaskRequest) (*api.GetTaskResponse, error) {
	if request.TaskID == "" {
		return nil, status.Errorf(codes.InvalidArgument, errInvalidArgument.Error())
	}

	var task *api.Task
	s.store.View(func(tx store.ReadTx) {
		task = store.GetTask(tx, request.TaskID)
	})
	if task == nil {
		return nil, status.Errorf(codes.NotFound, "task %s not found", request.TaskID)
	}
	return &api.GetTaskResponse{
		Task: task,
	}, nil
}
855644
func (sm *schedulerMetrics) ClaimTask(succeeded bool) {
	status := statusString(succeeded)

	sm.claimsComplete.WithLabelValues(status).Inc()
	if succeeded {
		sm.claimsActive.Inc()
	}
}