func (self *Metadata) restartQueuedLocal() error {
	if self.exists(QueuedLocally) {
		if err := self.uncheckedReset(); err == nil {
			util.PrintInfo("runtime", "(reset-running)   %s", self.fqname)
			return nil
		} else {
			return err
		}
	}
	return nil
}
Resets the metadata if the state was queued, but the job manager had not yet
started the job locally or queued it remotely.
package core
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"syscall"
	"time"
	"github.com/martian-lang/martian/martian/util"
)
const heartbeatTimeout = 60  
type MetadataFileName string
const AnyFile MetadataFileName = "*"
const (
	AlarmFile      MetadataFileName = "alarm"
	ArgsFile       MetadataFileName = "args"
	Assert         MetadataFileName = "assert"
	ChunkDefsFile  MetadataFileName = "chunk_defs"
	ChunkOutsFile  MetadataFileName = "chunk_outs"
	CompleteFile   MetadataFileName = "complete"
	Errors         MetadataFileName = "errors"
	FinalState     MetadataFileName = "finalstate"
	Heartbeat      MetadataFileName = "heartbeat"
	InvocationFile MetadataFileName = "invocation"
	JobId          MetadataFileName = "jobid"
	JobInfoFile    MetadataFileName = "jobinfo"
	JobModeFile    MetadataFileName = "jobmode"
	Lock           MetadataFileName = "lock"
	LogFile        MetadataFileName = "log"
	MetadataZip    MetadataFileName = "metadata.zip"
	MroSourceFile  MetadataFileName = "mrosource"
	OutsFile       MetadataFileName = "outs"
	Perf           MetadataFileName = "perf"
	PerfData       MetadataFileName = "perf.data"
	ProfileOut     MetadataFileName = "profile.out"
	ProgressFile   MetadataFileName = "progress"
	QueuedLocally  MetadataFileName = "queued_locally"
	Stackvars      MetadataFileName = "stackvars"
	StageDefsFile  MetadataFileName = "stage_defs"
	StdErr         MetadataFileName = "stderr"
	StdOut         MetadataFileName = "stdout"
	TagsFile       MetadataFileName = "tags"
	TimestampFile  MetadataFileName = "timestamp"
	UiPort         MetadataFileName = "uiport"
	UuidFile       MetadataFileName = "uuid"
	VdrKill        MetadataFileName = "vdrkill"
	PartialVdr     MetadataFileName = "vdrkill.partial"
	VersionsFile   MetadataFileName = "versions"
	DisabledFile   MetadataFileName = "disabled"
)
const MetadataFilePrefix string = "_"
func (self MetadataFileName) FileName() string {
	return MetadataFilePrefix + string(self)
}
func (self MetadataFileName) MimeType() string {
	switch self {
	case ArgsFile, OutsFile,
		JobInfoFile,
		StageDefsFile, ChunkDefsFile, ChunkOutsFile,
		VdrKill, PartialVdr, FinalState,
		TagsFile, VersionsFile, Perf:
		return "application/json"
	case LogFile, StdErr, StdOut,
		InvocationFile, MroSourceFile,
		Assert, AlarmFile, Errors, Stackvars,
		ProgressFile:
		return "text/plain;charset=UTF-8"
	case MetadataZip:
		return "application/zip"
	case CompleteFile, Heartbeat, TimestampFile,
		JobId, QueuedLocally,
		JobModeFile, Lock, UiPort, UuidFile,
		DisabledFile:
		return "text/plain"
	case PerfData:
		return "application/octet-stream"
	default:
		return ""
	}
}
func metadataFileNameFromPath(p string) MetadataFileName {
	return MetadataFileName(path.Base(p)[len(MetadataFilePrefix):])
}
type MetadataState string
const (
	Complete      MetadataState = "complete"
	Failed        MetadataState = "failed"
	DisabledState MetadataState = "disabled"
	Running       MetadataState = "running"
	Queued        MetadataState = "queued"
	Ready         MetadataState = "ready"
	Waiting       MetadataState = ""
	ForkWaiting   MetadataState = "waiting"
)
const (
	ChunksPrefix  = "chunks_"
	SplitPrefix   = "split_"
	JoinPrefix    = "join_"
	CleanupPrefix = "cleanup_"
	RetryPrefix   = "retry_"
)
func (self MetadataState) Prefixed(prefix string) MetadataState {
	return MetadataState(prefix + string(self))
}
func (self MetadataState) HasPrefix(prefix string) bool {
	return strings.HasPrefix(string(self), prefix)
}
func (self MetadataState) IsRunning() bool {
	return strings.HasSuffix(string(self), string(Running))
}
func (self MetadataState) IsQueued() bool {
	return strings.HasSuffix(string(self), string(Queued))
}
func (self MetadataState) IsFailed() bool {
	return strings.HasSuffix(string(self), string(Failed))
}
func makeUniquifier() string {
	trimmedTime := uint32(time.Now().Unix()) & ((^uint32(0)) >> 8)
	return fmt.Sprintf("%04x%06x", uint16(os.Getpid()), trimmedTime)
}
type Metadata struct {
	fqname        string
	path          string
	finalPath     string
	contents      map[MetadataFileName]struct{}
	readCache     map[MetadataFileName]LazyArgumentMap
	curFilesPath  string
	finalFilePath string
	journalPath   string
	lastRefresh   time.Time
	lastHeartbeat time.Time
	mutex         sync.Mutex
	uniquifier    string
	journalPrefix string
	notRunningSince time.Time
}
type MetadataInfo struct {
	Path string `json:"path"`
	Names []string `json:"names"`
}
func NewMetadata(fqname string, p string) *Metadata {
	return &Metadata{
		fqname:        fqname,
		path:          p,
		finalPath:     p,
		contents:      make(map[MetadataFileName]struct{}),
		readCache:     make(map[MetadataFileName]LazyArgumentMap),
		curFilesPath:  path.Join(p, "files"),
		finalFilePath: path.Join(p, "files"),
	}
}
func NewMetadataRunWithJournalPath(fqname, p, filesPath, journalPath, runType string) *Metadata {
	self := NewMetadata(fqname, p)
	self.journalPath = path.Join(journalPath, fqname)
	self.curFilesPath = filesPath
	self.finalFilePath = filesPath
	if runType != "main" {
		self.journalPrefix = runType + "_"
	}
	return self
}
func newMetadataWithJournalPath(fqname, journalName, p, journalPath string) *Metadata {
	self := NewMetadata(fqname, p)
	self.journalPath = path.Join(journalPath, journalName)
	return self
}
func (self *Metadata) glob() ([]string, error) {
	paths, err := util.Readdirnames(self.path)
	if err != nil {
		return nil, err
	}
	matches := make([]string, 0, len(paths))
	for _, p := range paths {
		if strings.HasPrefix(p, MetadataFilePrefix) {
			matches = append(matches, path.Join(self.path, p))
		}
	}
	return matches, nil
}
func (self *Metadata) symlinks() []string {
	var symlinks []string
	if self.path != self.finalPath {
		if info, err := os.Lstat(self.finalPath); err == nil && info.Mode()&os.ModeSymlink != 0 {
			symlinks = []string{self.finalPath}
		}
		if self.finalFilePath != path.Join(self.finalPath, "files") {
			if info, err := os.Lstat(self.finalFilePath); err == nil && info.Mode()&os.ModeSymlink != 0 {
				symlinks = append(symlinks, self.finalFilePath)
			}
		}
	}
	return symlinks
}
func (self *Metadata) enumerateFiles() ([]string, error) {
	paths, err := util.Readdirnames(self.curFilesPath)
	for i, p := range paths {
		paths[i] = path.Join(self.curFilesPath, p)
	}
	return paths, err
}
func (self *Metadata) enumerateTemp() ([]string, error) {
	if td := self.TempDir(); td == "" {
		return nil, nil
	} else {
		paths, err := util.Readdirnames(td)
		for i, p := range paths {
			paths[i] = path.Join(td, p)
		}
		return paths, err
	}
}
func (self *Metadata) FilesPath() string {
	return self.curFilesPath
}
func (self *Metadata) TempDir() string {
	if p := self.path; p != "" {
		return path.Join(p, "tmp")
	} else {
		return ""
	}
}
func (self *Metadata) writeError(msg string, src error) {
	msg = msg + " (" + self.fqname + ")"
	util.LogError(src, "runtime", "%s", msg)
	if err := self.WriteRaw(Errors, msg+": "+src.Error()); err != nil {
		util.PrintError(err, "runtime", "Could not write error message")
	}
}
func (self *Metadata) writeErrorNoLock(msg string, src error) {
	msg = msg + self.fqname
	util.LogError(src, "runtime", "%s", msg)
	if err := self._writeRawNoLock(Errors, msg+": "+src.Error()); err != nil {
		util.PrintError(err, "runtime", "Could not write error message")
	}
}
func (self *Metadata) mkdirs() error {
	if err := util.Mkdir(self.path); err != nil {
		self.writeError("Could not create directories for ", err)
		return err
	}
	if err := util.Mkdir(self.curFilesPath); err != nil {
		self.writeError("Could not create directories for ", err)
		return err
	}
	return nil
}
func (self *Metadata) mkForkDirs() error {
	if err := util.MkdirAll(self.path); err != nil {
		self.writeError("Could not create directories for ", err)
		return err
	}
	if err := util.Mkdir(self.curFilesPath); err != nil {
		self.writeError("Could not create directories for ", err)
		return err
	}
	return nil
}
func (self *Metadata) uniquify() error {
	self.mutex.Lock()
	defer self.mutex.Unlock()
	if self.uniquifier == "" {
		self.uniquifier = makeUniquifier()
	}
	p := self.finalPath + "-u" + self.uniquifier
	if err := util.Mkdir(p); err != nil {
		self.writeErrorNoLock("Could not create directories for ", err)
		return err
	}
	self.path = p
	filesPath := path.Join(p, "files")
	if err := util.Mkdir(filesPath); err != nil {
		self.writeErrorNoLock("Could not create file directory for ", err)
		os.Remove(p)
		return err
	}
	self.curFilesPath = filesPath
	if err := util.Mkdir(self.TempDir()); err != nil {
		self.writeErrorNoLock("Could not create temp directory for ", err)
		os.Remove(filesPath)
		os.Remove(p)
		return err
	}
	if self.discoverUniquifier() != self.uniquifier {
		if relPath, err := filepath.Rel(filepath.Dir(self.finalPath), p); err != nil {
			msg := fmt.Sprintf(
				"Could not compute relative path for %s to %s for stage ",
				self.finalPath, p)
			self.writeErrorNoLock(msg, err)
			os.RemoveAll(p)
			return err
		} else {
			if err := os.Symlink(relPath, self.finalPath); err != nil {
				self.writeErrorNoLock("Could not create symlink for ", err)
				os.RemoveAll(p)
				return err
			}
		}
		if self.finalFilePath != path.Join(self.finalPath, "files") {
			if err := os.Remove(self.finalFilePath); err != nil && !os.IsNotExist(err) {
				self.writeErrorNoLock("Could not remove existing directory for ", err)
				os.RemoveAll(p)
				return err
			}
			if relPath, err := filepath.Rel(filepath.Dir(self.finalFilePath), filesPath); err != nil {
				msg := fmt.Sprintf(
					"Could not compute relative path for %s to %s for stage ",
					self.finalFilePath, filesPath)
				self.writeErrorNoLock(msg, err)
				os.RemoveAll(p)
				return err
			} else {
				if err := os.Symlink(relPath, self.finalFilePath); err != nil {
					self.writeErrorNoLock("Could not create files symlink for ", err)
					os.RemoveAll(p)
					return err
				}
			}
		}
	}
	return nil
}
func (self *Metadata) removeAll() error {
	self.mutex.Lock()
	defer self.mutex.Unlock()
	if len(self.contents) > 0 {
		self.contents = make(map[MetadataFileName]struct{})
	}
	if len(self.readCache) > 0 {
		self.readCache = make(map[MetadataFileName]LazyArgumentMap)
	}
	self.notRunningSince = time.Time{}
	self.lastRefresh = time.Time{}
	if err := os.RemoveAll(self.curFilesPath); err != nil {
		return err
	}
	if err := os.RemoveAll(self.path); err != nil {
		return err
	}
	if self.finalFilePath != self.curFilesPath {
		os.Remove(self.finalFilePath)
	}
	if self.finalPath != self.path {
		os.Remove(self.finalPath)
	}
	return nil
}
func (self *Metadata) _getStateNoLock() (MetadataState, bool) {
	if self._existsNoLock(Errors) {
		return Failed, true
	}
	if self._existsNoLock(Assert) {
		return Failed, true
	}
	if self._existsNoLock(CompleteFile) {
		if self._existsNoLock(JobId) {
			if err := self._removeNoLock(JobId); err != nil {
				util.LogError(err, "runtime", "Could not remove file.")
			}
		}
		return Complete, true
	}
	if self._existsNoLock(DisabledFile) {
		return DisabledState, true
	}
	if self._existsNoLock(LogFile) {
		return Running, true
	}
	if self._existsNoLock(JobInfoFile) {
		return Queued, true
	}
	return Waiting, false
}
func (self *Metadata) getState() (MetadataState, bool) {
	self.mutex.Lock()
	state, ok := self._getStateNoLock()
	self.mutex.Unlock()
	return state, ok
}
func (self *Metadata) _cacheNoLock(name MetadataFileName) {
	self.contents[name] = struct{}{}
	delete(self.readCache, name)
}
func (self *Metadata) cache(name MetadataFileName, uniquifier string) {
	self.mutex.Lock()
	if self.uniquifier == uniquifier {
		self._cacheNoLock(name)
	} else if self.uniquifier != "" {
		util.LogInfo("runtime",
			"There appears to be more than one instance of %s running "+
				"(Saw ID '%s', expected '%s').",
			self.fqname, uniquifier, self.uniquifier)
	}
	self.mutex.Unlock()
}
func (self *Metadata) _uncacheNoLock(name MetadataFileName) {
	delete(self.contents, name)
	delete(self.readCache, name)
}
func (self *Metadata) uncache(name MetadataFileName) {
	self.mutex.Lock()
	self._uncacheNoLock(name)
	self.mutex.Unlock()
}
func (self *Metadata) discoverUniquify() {
	self.uniquifier = self.discoverUniquifier()
	if self.uniquifier != "" {
		self.path = self.finalPath + "-u" + self.uniquifier
		self.curFilesPath = path.Join(self.path, "files")
	}
}
func (self *Metadata) discoverUniquifier() string {
	if rel, err := os.Readlink(self.finalPath); err == nil {
		dest := path.Join(path.Dir(self.finalPath), rel)
		if strings.HasPrefix(dest, self.finalPath+"-u") {
			return dest[len(self.finalPath)+2:]
		}
	}
	return ""
}
func (self *Metadata) loadCache() {
	self.discoverUniquify()
	paths, err := self.glob()
	if err != nil {
		return
	}
	self.mutex.Lock()
	if len(self.contents) > 0 {
		self.contents = make(map[MetadataFileName]struct{}, len(paths))
	}
	if len(self.readCache) > 0 {
		self.readCache = make(map[MetadataFileName]LazyArgumentMap)
	}
	for _, p := range paths {
		self.contents[metadataFileNameFromPath(p)] = struct{}{}
	}
	self.notRunningSince = time.Time{}
	self.lastRefresh = time.Time{}
	self.mutex.Unlock()
}
func (self *Metadata) poll() {
	paths, _ := self.glob()
	if len(paths) == 0 {
		return
	}
	self.mutex.Lock()
	for _, p := range paths {
		self.contents[metadataFileNameFromPath(p)] = struct{}{}
	}
	self.mutex.Unlock()
}
func (self *Metadata) FilePath(name string) string {
	return path.Join(self.curFilesPath, name)
}
func (self *Metadata) MetadataFilePath(name MetadataFileName) string {
	return path.Join(self.path, name.FileName())
}
func (self *Metadata) _existsNoLock(name MetadataFileName) bool {
	_, ok := self.contents[name]
	return ok
}
func (self *Metadata) exists(name MetadataFileName) bool {
	self.mutex.Lock()
	ok := self._existsNoLock(name)
	self.mutex.Unlock()
	return ok
}
func (self *Metadata) readRawBytes(name MetadataFileName) ([]byte, error) {
	return ioutil.ReadFile(self.MetadataFilePath(name))
}
func (self *Metadata) readRawSafe(name MetadataFileName) (string, error) {
	bytes, err := self.readRawBytes(name)
	return string(bytes), err
}
func (self *Metadata) readRaw(name MetadataFileName) string {
	s, _ := self.readRawSafe(name)
	return s
}
func (self *Metadata) readFromCache(name MetadataFileName) (LazyArgumentMap, bool) {
	self.mutex.Lock()
	i, ok := self.readCache[name]
	self.mutex.Unlock()
	return i, ok
}
func (self *Metadata) saveToCache(name MetadataFileName, value LazyArgumentMap) {
	self.mutex.Lock()
	self.readCache[name] = value
	self.mutex.Unlock()
}
func (self *Metadata) openFile(name MetadataFileName) (*os.File, error) {
	return os.Open(self.MetadataFilePath(name))
}
func (self *Metadata) read(name MetadataFileName, limit int64) (LazyArgumentMap, error) {
	v, ok := self.readFromCache(name)
	if ok {
		return v, nil
	}
	p := self.MetadataFilePath(name)
	if f, err := os.Open(p); err != nil {
		if !os.IsNotExist(err) {
			util.LogError(err, "runtime",
				"Could not open %s",
				p)
		}
		return nil, err
	} else {
		if err := func(p string, f *os.File, limit int64, v *LazyArgumentMap) error {
			defer f.Close()
			if limit > 0 {
				if info, err := f.Stat(); err != nil {
					return err
				} else if info.Size() > limit {
					return fmt.Errorf(
						"Insufficient memory to read %s\n"+
							"File is %d bytes, read size limited to %d bytes.",
						p, info.Size(), limit)
				}
			}
			dec := json.NewDecoder(f)
			return dec.Decode(v)
		}(p, f, limit, &v); err == nil {
			self.saveToCache(name, v)
			return v, nil
		} else {
			return nil, err
		}
	}
}
func (self *Metadata) ReadInto(name MetadataFileName, target interface{}) error {
	if b, err := self.readRawBytes(name); err != nil {
		return err
	} else {
		return json.Unmarshal(b, target)
	}
}
func (self *Metadata) _writeRawNoLock(name MetadataFileName, text string) error {
	err := ioutil.WriteFile(self.MetadataFilePath(name), []byte(text), 0644)
	self._cacheNoLock(name)
	if err != nil {
		msg := fmt.Sprintf("Could not write %s for %s: %s", name, self.fqname, err.Error())
		util.LogError(err, "runtime", msg)
		if name != Errors {
			_ = self._writeRawNoLock(Errors, msg)
		}
	}
	return err
}
func (self *Metadata) WriteRaw(name MetadataFileName, text string) error {
	return self.WriteRawBytes(name, []byte(text))
}
func (self *Metadata) WriteRawBytes(name MetadataFileName, text []byte) error {
	err := ioutil.WriteFile(self.MetadataFilePath(name), text, 0644)
	self.cache(name, self.uniquifier)
	if err != nil {
		msg := fmt.Sprintf("Could not write %s for %s: %s", name, self.fqname, err.Error())
		util.LogError(err, "runtime", "%s", msg)
		if name != Errors {
			self.WriteErrorString(msg)
		}
	}
	return err
}
func (self *Metadata) WriteErrorString(msg string) {
	if err := self.WriteRaw(Errors, msg); err != nil {
		util.LogError(err, "runtime", "Could not write errors file.")
	}
}
func (self *Metadata) appendRaw(name MetadataFileName, text string) error {
	self.cache(name, self.uniquifier)
	if f, err := os.OpenFile(self.MetadataFilePath(name),
		os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644); err != nil {
		return err
	} else if _, err := f.Write([]byte(text)); err != nil {
		f.Close()
		return err
	} else {
		return f.Close()
	}
}
func (self *Metadata) AppendAlarm(text string) error {
	if err := self.appendRaw(AlarmFile, text); err != nil {
		msg := fmt.Sprintf("Could not write alarm for %s: %s",
			self.fqname, err.Error())
		util.LogError(err, "runtime", "%s", msg)
		self.WriteErrorString(msg)
		return err
	}
	if self.journalPrefix != "" {
		return self.UpdateJournal(AlarmFile)
	} else {
		return nil
	}
}
func (self *Metadata) Write(name MetadataFileName, object interface{}) error {
	bytes, _ := json.MarshalIndent(object, "", "    ")
	return self.WriteRawBytes(name, bytes)
}
func (self *Metadata) WriteTime(name MetadataFileName) error {
	return self.WriteRaw(name, util.Timestamp())
}
func (self *Metadata) WriteAtomic(name MetadataFileName, object interface{}) error {
	bytes, err := json.MarshalIndent(object, "", "    ")
	if err != nil {
		return err
	}
	fname := self.MetadataFilePath(name)
	tmpName := fname + ".tmp"
	if err := ioutil.WriteFile(tmpName, bytes, 0644); err != nil {
		return err
	}
	if err := os.Rename(tmpName, fname); err == nil || os.IsNotExist(err) {
		return nil
	} else {
		return err
	}
}
func (self *Metadata) UpdateJournal(name MetadataFileName) error {
	fname := self.journalPath + "." + self.journalPrefix + string(name)
	if err := ioutil.WriteFile(fname,
		[]byte(util.Timestamp()), 0644); err != nil && !os.IsExist(err) {
		return err
	}
	return nil
}
func (self *Metadata) remove(name MetadataFileName) error {
	self.uncache(name)
	err := os.Remove(self.MetadataFilePath(name))
	if os.IsNotExist(err) {
		return nil
	}
	return err
}
func (self *Metadata) _removeNoLock(name MetadataFileName) error {
	self._uncacheNoLock(name)
	err := os.Remove(self.MetadataFilePath(name))
	if os.IsNotExist(err) {
		return nil
	}
	return err
}
func (self *Metadata) clearReadCache() {
	self.mutex.Lock()
	if len(self.readCache) > 0 {
		self.readCache = make(map[MetadataFileName]LazyArgumentMap)
	}
	self.mutex.Unlock()
}
func (self *Metadata) resetHeartbeat() {
	self.lastHeartbeat = time.Time{}
}
func (self *Metadata) endRefresh(lastRefresh time.Time) {
	self.mutex.Lock()
	self.lastRefresh = lastRefresh
	if !self.notRunningSince.IsZero() && self.notRunningSince.Before(lastRefresh) {
		notRunningSince := self.notRunningSince
		self.notRunningSince = time.Time{}
		if state, _ := self._getStateNoLock(); state == Running || state == Queued {
			err := self._writeRawNoLock(Errors, fmt.Sprintf(
				"According to the job manager, the job for %s was not queued "+
					"or running, since at least %s.",
				self.fqname, notRunningSince.Format(util.TIMEFMT)))
			if err != nil {
				util.LogError(err, "runtime",
					"Error writing error message about cluster-mode job not running.")
			}
		}
	}
	self.mutex.Unlock()
}
func (self *Metadata) failNotRunning(jobid string) {
	if !self.exists(JobId) {
		return
	}
	if st, _ := self.getState(); st != Running && st != Queued {
		return
	}
	self.poll()
	if st, _ := self.getState(); st != Running && st != Queued {
		return
	}
	self.mutex.Lock()
	defer self.mutex.Unlock()
	if !self.notRunningSince.IsZero() {
		return
	}
	if self.readRaw(JobId) != jobid {
		return
	}
	if !self._existsNoLock(JobId) {
		return
	}
	self.notRunningSince = time.Now()
}
func (self *Metadata) checkedReset() error {
	self.mutex.Lock()
	if state, _ := self._getStateNoLock(); state == Failed {
		if len(self.contents) > 0 {
			self.contents = make(map[MetadataFileName]struct{})
		}
		self.mutex.Unlock()
		if err := self.uncheckedReset(); err == nil {
			util.PrintInfo("runtime", "(reset-partial)   %s", self.fqname)
		} else {
			return err
		}
	} else {
		self.mutex.Unlock()
	}
	return nil
}
func (self *Metadata) journalFile() string {
	if self.uniquifier == "" {
		return self.journalPath
	} else if p := self.journalPath; p == "" {
		return ""
	} else {
		return p + ".u" + self.uniquifier
	}
}
func (self *Metadata) uncheckedReset() error {
	if len(self.journalPath) > 0 {
		dir, base := filepath.Split(self.journalFile())
		paths, _ := util.Readdirnames(dir)
		for _, p := range paths {
			if strings.HasPrefix(p, base) {
				os.Remove(path.Join(dir, p))
			}
		}
	}
	if err := self.removeAll(); err != nil {
		util.PrintInfo("runtime",
			"Cannot reset the stage because some folder contents could not "+
				"be deleted.\n\nPlease resolve this error in order to "+
				"continue running the pipeline:\n\t%v",
			err)
		return err
	}
	if self.uniquifier == "" {
		return self.mkdirs()
	} else {
		self.uniquifier = ""
		return self.uniquify()
	}
}