示例#1
0
// This custom unmarshaller is needed because the json sent to us as a string
// rather than a fully typed object. We support both formats in the hopes that
// one day everything will be fully typed
// Note: the `json:",string"` tag DOES NOT apply here; it DOES NOT work with
// struct types, only ints/floats/etc. We're basically doing that though
// We also intentionally fail if there are any keys we were unable to unmarshal
// into our struct
func (overrides *ContainerOverrides) UnmarshalJSON(b []byte) error {
	regular := ContainerOverridesCopy{}

	// Try to do it the strongly typed way first
	err := json.Unmarshal(b, &regular)
	if err == nil {
		err = utils.CompleteJsonUnmarshal(b, regular)
		if err == nil {
			*overrides = ContainerOverrides(regular)
			return nil
		}
		err = utils.NewMultiError(errors.New("Error unmarshalling ContainerOverrides"), err)
	}

	// Now the stringly typed way
	var str string
	err2 := json.Unmarshal(b, &str)
	if err2 != nil {
		return utils.NewMultiError(errors.New("Could not unmarshal ContainerOverrides into either an object or string respectively"), err, err2)
	}

	// We have a string, let's try to unmarshal that into a typed object
	err3 := json.Unmarshal([]byte(str), &regular)
	if err3 == nil {
		err3 = utils.CompleteJsonUnmarshal([]byte(str), regular)
		if err3 == nil {
			*overrides = ContainerOverrides(regular)
			return nil
		} else {
			err3 = utils.NewMultiError(errors.New("Error unmarshalling ContainerOverrides"), err3)
		}
	}

	return utils.NewMultiError(errors.New("Could not unmarshal ContainerOverrides in any supported way"), err, err2, err3)
}
// FinalSave should be called immediately before exiting, and only before
// exiting, in order to flush tasks to disk. It waits a short timeout for state
// to settle if necessary. If unable to reach a steady-state and save within
// this short timeout, it returns an error
func FinalSave(saver statemanager.Saver, taskEngine engine.TaskEngine) error {
	engineDisabled := make(chan error)

	disableTimer := time.AfterFunc(engineDisableTimeout, func() {
		engineDisabled <- errors.New("Timed out waiting for TaskEngine to settle")
	})

	go func() {
		log.Debug("Shutting down task engine")
		taskEngine.Disable()
		disableTimer.Stop()
		engineDisabled <- nil
	}()

	disableErr := <-engineDisabled

	stateSaved := make(chan error)
	saveTimer := time.AfterFunc(finalSaveTimeout, func() {
		stateSaved <- errors.New("Timed out trying to save to disk")
	})
	go func() {
		log.Debug("Saving state before shutting down")
		stateSaved <- saver.ForceSave()
		saveTimer.Stop()
	}()

	saveErr := <-stateSaved

	if disableErr != nil || saveErr != nil {
		return utils.NewMultiError(disableErr, saveErr)
	}
	return nil
}