// flock acquires an advisory lock on a file descriptor.
514462
func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
	var t time.Time
	for {
		// If we're beyond our timeout then return an error.
		// This can only occur after we've attempted a flock once.
		if t.IsZero() {
			t = time.Now()
		} else if timeout > 0 && time.Since(t) > timeout {
			return ErrTimeout
		}
		flag := syscall.LOCK_SH
		if exclusive {
			flag = syscall.LOCK_EX
		}

		// Otherwise attempt to obtain an exclusive lock.
		err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB)
		if err == nil {
			return nil
		} else if err != syscall.EWOULDBLOCK {
			return err
		}

		// Wait for a bit and try again.
		time.Sleep(50 * time.Millisecond)
	}
}
1124968
func (cli *Client) SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error {
	serverResp, err := cli.post(ctx, "/swarm/unlock", nil, req, nil)
	ensureReaderClosed(serverResp)
	return err
}
1325215
func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
	for i, desc := range file.MessageType {
		sl = wrapThisDescriptor(sl, desc, nil, file, i)
	}
	return sl
}
895367
func (d *Daemon) doSync(logger log.Logger, lastKnownSyncTagRev *string, warnedAboutSyncTagChange *bool) (retErr error) {
	started := time.Now().UTC()
	defer func() {
		syncDuration.With(
			fluxmetrics.LabelSuccess, fmt.Sprint(retErr == nil),
		).Observe(time.Since(started).Seconds())
	}()

	syncSetName := makeGitConfigHash(d.Repo.Origin(), d.GitConfig)

	// We don't care how long this takes overall, only about not
	// getting bogged down in certain operations, so use an
	// undeadlined context in general.
	ctx := context.Background()

	// checkout a working clone so we can mess around with tags later
	var working *git.Checkout
	{
		var err error
		ctx, cancel := context.WithTimeout(ctx, d.GitOpTimeout)
		defer cancel()
		working, err = d.Repo.Clone(ctx, d.GitConfig)
		if err != nil {
			return err
		}
		defer working.Clean()
	}

	// For comparison later.
	oldTagRev, err := working.SyncRevision(ctx)
	if err != nil && !isUnknownRevision(err) {
		return err
	}
	// Check if something other than the current instance of fluxd changed the sync tag.
	// This is likely to be caused by another fluxd instance using the same tag.
	// Having multiple instances fighting for the same tag can lead to fluxd missing manifest changes.
	if *lastKnownSyncTagRev != "" && oldTagRev != *lastKnownSyncTagRev && !*warnedAboutSyncTagChange {
		logger.Log("warning",
			"detected external change in git sync tag; the sync tag should not be shared by fluxd instances")
		*warnedAboutSyncTagChange = true
	}

	newTagRev, err := working.HeadRevision(ctx)
	if err != nil {
		return err
	}

	// Get a map of all resources defined in the repo
	allResources, err := d.Manifests.LoadManifests(working.Dir(), working.ManifestDirs())
	if err != nil {
		return errors.Wrap(err, "loading resources from repo")
	}

	var resourceErrors []event.ResourceError
	if err := fluxsync.Sync(syncSetName, allResources, d.Cluster); err != nil {
		switch syncerr := err.(type) {
		case cluster.SyncError:
			logger.Log("err", err)
			for _, e := range syncerr {
				resourceErrors = append(resourceErrors, event.ResourceError{
					ID:    e.ResourceID,
					Path:  e.Source,
					Error: e.Error.Error(),
				})
			}
		default:
			return err
		}
	}

	// update notes and emit events for applied commits

	var initialSync bool
	var commits []git.Commit
	{
		var err error
		ctx, cancel := context.WithTimeout(ctx, d.GitOpTimeout)
		if oldTagRev != "" {
			commits, err = d.Repo.CommitsBetween(ctx, oldTagRev, newTagRev, d.GitConfig.Paths...)
		} else {
			initialSync = true
			commits, err = d.Repo.CommitsBefore(ctx, newTagRev, d.GitConfig.Paths...)
		}
		cancel()
		if err != nil {
			return err
		}
	}

	// Figure out which workload IDs changed in this release
	changedResources := map[string]resource.Resource{}

	if initialSync {
		// no synctag, We are syncing everything from scratch
		changedResources = allResources
	} else {
		ctx, cancel := context.WithTimeout(ctx, d.GitOpTimeout)
		changedFiles, err := working.ChangedFiles(ctx, oldTagRev)
		if err == nil && len(changedFiles) > 0 {
			// We had some changed files, we're syncing a diff
			// FIXME(michael): this won't be accurate when a file can have more than one resource
			changedResources, err = d.Manifests.LoadManifests(working.Dir(), changedFiles)
		}
		cancel()
		if err != nil {
			return errors.Wrap(err, "loading resources from repo")
		}
	}

	workloadIDs := flux.ResourceIDSet{}
	for _, r := range changedResources {
		workloadIDs.Add([]flux.ResourceID{r.ResourceID()})
	}

	var notes map[string]struct{}
	{
		ctx, cancel := context.WithTimeout(ctx, d.GitOpTimeout)
		notes, err = working.NoteRevList(ctx)
		cancel()
		if err != nil {
			return errors.Wrap(err, "loading notes from repo")
		}
	}

	// Collect any events that come from notes attached to the commits
	// we just synced. While we're doing this, keep track of what
	// other things this sync includes e.g., releases and
	// autoreleases, that we're already posting as events, so upstream
	// can skip the sync event if it wants to.
	includes := make(map[string]bool)
	if len(commits) > 0 {
		var noteEvents []event.Event

		// Find notes in revisions.
		for i := len(commits) - 1; i >= 0; i-- {
			if _, ok := notes[commits[i].Revision]; !ok {
				includes[event.NoneOfTheAbove] = true
				continue
			}
			ctx, cancel := context.WithTimeout(ctx, d.GitOpTimeout)
			var n note
			ok, err := working.GetNote(ctx, commits[i].Revision, &n)
			cancel()
			if err != nil {
				return errors.Wrap(err, "loading notes from repo")
			}
			if !ok {
				includes[event.NoneOfTheAbove] = true
				continue
			}

			// If this is the first sync, we should expect no notes,
			// since this is supposedly the first time we're seeing
			// the repo. But there are circumstances in which we can
			// nonetheless see notes -- if the tag was deleted from
			// the upstream repo, or if this accidentally has the same
			// notes ref as another daemon using the same repo (but a
			// different tag). Either way, we don't want to report any
			// notes on an initial sync, since they (most likely)
			// don't belong to us.
			if initialSync {
				logger.Log("warning", "no notes expected on initial sync; this repo may be in use by another fluxd")
				break
			}

			// Interpret some notes as events to send to the upstream
			switch n.Spec.Type {
			case update.Containers:
				spec := n.Spec.Spec.(update.ReleaseContainersSpec)
				noteEvents = append(noteEvents, event.Event{
					ServiceIDs: n.Result.AffectedResources(),
					Type:       event.EventRelease,
					StartedAt:  started,
					EndedAt:    time.Now().UTC(),
					LogLevel:   event.LogLevelInfo,
					Metadata: &event.ReleaseEventMetadata{
						ReleaseEventCommon: event.ReleaseEventCommon{
							Revision: commits[i].Revision,
							Result:   n.Result,
							Error:    n.Result.Error(),
						},
						Spec: event.ReleaseSpec{
							Type:                  event.ReleaseContainersSpecType,
							ReleaseContainersSpec: &spec,
						},
						Cause: n.Spec.Cause,
					},
				})
				includes[event.EventRelease] = true
			case update.Images:
				spec := n.Spec.Spec.(update.ReleaseImageSpec)
				noteEvents = append(noteEvents, event.Event{
					ServiceIDs: n.Result.AffectedResources(),
					Type:       event.EventRelease,
					StartedAt:  started,
					EndedAt:    time.Now().UTC(),
					LogLevel:   event.LogLevelInfo,
					Metadata: &event.ReleaseEventMetadata{
						ReleaseEventCommon: event.ReleaseEventCommon{
							Revision: commits[i].Revision,
							Result:   n.Result,
							Error:    n.Result.Error(),
						},
						Spec: event.ReleaseSpec{
							Type:             event.ReleaseImageSpecType,
							ReleaseImageSpec: &spec,
						},
						Cause: n.Spec.Cause,
					},
				})
				includes[event.EventRelease] = true
			case update.Auto:
				spec := n.Spec.Spec.(update.Automated)
				noteEvents = append(noteEvents, event.Event{
					ServiceIDs: n.Result.AffectedResources(),
					Type:       event.EventAutoRelease,
					StartedAt:  started,
					EndedAt:    time.Now().UTC(),
					LogLevel:   event.LogLevelInfo,
					Metadata: &event.AutoReleaseEventMetadata{
						ReleaseEventCommon: event.ReleaseEventCommon{
							Revision: commits[i].Revision,
							Result:   n.Result,
							Error:    n.Result.Error(),
						},
						Spec: spec,
					},
				})
				includes[event.EventAutoRelease] = true
			case update.Policy:
				// Use this to mean any change to policy
				includes[event.EventUpdatePolicy] = true
			default:
				// Presume it's not something we're otherwise sending
				// as an event
				includes[event.NoneOfTheAbove] = true
			}
		}

		cs := make([]event.Commit, len(commits))
		for i, c := range commits {
			cs[i].Revision = c.Revision
			cs[i].Message = c.Message
		}
		if err = d.LogEvent(event.Event{
			ServiceIDs: workloadIDs.ToSlice(),
			Type:       event.EventSync,
			StartedAt:  started,
			EndedAt:    started,
			LogLevel:   event.LogLevelInfo,
			Metadata: &event.SyncEventMetadata{
				Commits:     cs,
				InitialSync: initialSync,
				Includes:    includes,
				Errors:      resourceErrors,
			},
		}); err != nil {
			logger.Log("err", err)
			// Abort early to ensure at least once delivery of events
			return err
		}

		for _, event := range noteEvents {
			if err = d.LogEvent(event); err != nil {
				logger.Log("err", err)
				// Abort early to ensure at least once delivery of events
				return err
			}
		}
	}

	// Move the tag and push it so we know how far we've gotten.
	if oldTagRev != newTagRev {
		{
			ctx, cancel := context.WithTimeout(ctx, d.GitOpTimeout)
			tagAction := git.TagAction{
				Revision: newTagRev,
				Message:  "Sync pointer",
			}
			err := working.MoveSyncTagAndPush(ctx, tagAction)
			cancel()
			if err != nil {
				return err
			}
			*lastKnownSyncTagRev = newTagRev
		}
		logger.Log("tag", d.GitConfig.SyncTag, "old", oldTagRev, "new", newTagRev)
		{
			ctx, cancel := context.WithTimeout(ctx, d.GitOpTimeout)
			err := d.Repo.Refresh(ctx)
			cancel()
			return err
		}
	}
	return nil
}
1207100
func (s *Swarm) Notify(n Notifiee) {
	s.notifieeLock.Lock()
	s.notifiees[n] = struct{}{}
	s.notifieeLock.Unlock()
}
1186329
func (f *Flock) TryLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
	return tryCtx(ctx, f.TryLock, retryDelay)
}
1021540
func CreateLockFile(file string) (LockFile, error) {
	f, err := os.Create(file)
	if err != nil {
		// Consider those fatal, others may be considered transient
		// (for instance FD limit reached, etc...)
		if os.IsNotExist(err) || os.IsPermission(err) {
			return nil, err
		}
		return nil, ErrUnableToLockNow
	}
	spec := &syscall.Flock_t{
		Type:   syscall.F_WRLCK,
		Whence: int16(io.SeekStart),
		Start:  0,
		Len:    0, // 0 means to lock the entire file.
	}
	if err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, spec); err != nil {
		// Try to gather all errors that we deem transient and return
		// ErrUnableToLockNow in this case to indicate the caller that
		// the lock could not be acquired at this time but it could
		// try later.
		// Basing this from possible ERRORS from this page:
		// http://pubs.opengroup.org/onlinepubs/009695399/functions/fcntl.html
		if err == syscall.EAGAIN || err == syscall.EACCES ||
			err == syscall.EINTR || err == syscall.ENOLCK {
			err = ErrUnableToLockNow
		}
		// TODO: If error is not ErrUnableToLockNow, it may mean that
		// the call is not supported on that platform, etc...
		// We should have another level of verification, for instance
		// check content of the lockfile is not being updated by the
		// owner of the file, etc...
		f.Close()
		return nil, err
	}
	return &lockFile{f: f}, nil
}
931608
func (s *SimpleFSHandler) SimpleFSWait(ctx context.Context, arg keybase1.OpID) error {
	cli, err := s.client()
	if err != nil {
		return err
	}
	return cli.SimpleFSWait(ctx, arg)
}
297804
func (l *FileLock) SharedLock() error {
	return syscall.Flock(l.fd, syscall.LOCK_SH)
}
559883
func (fbo *folderBranchOps) notifyBatchLocked(
	ctx context.Context, lState *kbfssync.LockState,
	md ImmutableRootMetadata) error {
	fbo.headLock.AssertLocked(lState)

	for _, op := range md.data.Changes.Ops {
		err := fbo.notifyOneOpLocked(ctx, lState, op, md.ReadOnly(), false)
		if err != nil {
			return err
		}
	}
	return nil
}
300582
func (s *Server) Lock(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) {
	// We list the directory first to make sure it exists.
	if _, err := s.ListDir(ctx, dirPath, false /*full*/); err != nil {
		// We need to return the right error codes, like
		// topo.ErrNoNode and topo.ErrInterrupted, and the
		// easiest way to do this is to return convertError(err).
		// It may lose some of the context, if this is an issue,
		// maybe logging the error would work here.
		return nil, convertError(err, dirPath)
	}

	lockPath := path.Join(s.root, dirPath, locksFilename)

	// Build the lock structure.
	l, err := s.client.LockOpts(&api.LockOptions{
		Key:   lockPath,
		Value: []byte(contents),
	})
	if err != nil {
		return nil, err
	}

	// Wait until we are the only ones in this client trying to
	// lock that path.
	s.mu.Lock()
	li, ok := s.locks[lockPath]
	for ok {
		// Unlock, wait for something to change.
		s.mu.Unlock()
		select {
		case <-ctx.Done():
			return nil, convertError(ctx.Err(), dirPath)
		case <-li.done:
		}

		// The original locker is gone, try to get it again
		s.mu.Lock()
		li, ok = s.locks[lockPath]
	}
	li = &lockInstance{
		lock: l,
		done: make(chan struct{}),
	}
	s.locks[lockPath] = li
	s.mu.Unlock()

	// We are the only ones trying to lock now.
	lost, err := l.Lock(ctx.Done())
	if err != nil {
		// Failed to lock, give up our slot in locks map.
		// Close the channel to unblock anyone else.
		s.mu.Lock()
		delete(s.locks, lockPath)
		s.mu.Unlock()
		close(li.done)

		return nil, err
	}

	// We got the lock, we're good.
	return &consulLockDescriptor{
		s:        s,
		lockPath: lockPath,
		lost:     lost,
	}, nil
}
172166
func (w *writer) Commit(ctx context.Context, descriptor distribution.Descriptor) (distribution.Descriptor, error) {
	desc := descriptor
	switch {
	case w.closed:
		return desc, fmt.Errorf("already closed")
	case w.committed:
		return desc, fmt.Errorf("already committed")
	case w.cancelled:
		return desc, fmt.Errorf("already cancelled")
	}
	w.committed = true
	return desc, nil
}
1012789
func (l *lockTracker) Lock(id string) {
	l.seenMu.RLock()
	if _, seen := l.seen[id]; !seen {
		l.seenMu.RUnlock()
		l.seenMu.Lock()
		l.seen[id] = struct{}{}
		l.seenMu.Unlock()
	} else {
		l.seenMu.RUnlock()
	}

	l.Locker.Lock(id)
}
59172
func lock() error {
	var err error
	var lock lockfile.Lockfile

	daemonMutex.Lock()
	lock, err = getLockfile()
	if err != nil {
		daemonMutex.Unlock()
		return fmt.Errorf("[lock] cannot init lockfile: %v", err)
	}

	// Try to acquire the lock and in case of a temporary error, sleep for
	// two seconds until the next retry (at most 10 times).  Return fatal
	// errors immediately, as we can't recover.
	for i := 0; i < 10; i++ {
		if err = lock.TryLock(); err != nil {
			switch err.(type) {
			case lockfile.TemporaryError:
				logrus.Debugf("[lock] busy: next retry in two seconds")
				time.Sleep(2 * time.Second)
			default:
				daemonMutex.Unlock()
				return fmt.Errorf("[lock] error acquiring lock: %s", err)
			}
		}
	}
	if err != nil {
		daemonMutex.Unlock()
		return fmt.Errorf("[lock] error acquiring lock: too many tries")
	}

	logrus.Debugf("[lock] lock acquired")
	return nil
}
1284220
func ByUserIndexKeys(obj interface{}) ([]string, error) {
	group, ok := obj.(*userapi.Group)
	if !ok {
		return nil, fmt.Errorf("unexpected type: %v", obj)
	}

	return group.Users, nil
}
97904
func FSUnlock(f *os.File) error {
	if err := syscall.Flock(int(f.Fd()), syscall.LOCK_UN); err != nil {
		return trace.ConvertSystemError(err)
	}
	return nil
}
270026
func (c *remoteClient) lockInfo() (*state.LockInfo, error) {
	r, err := c.lockFile().NewReader(c.storageContext)
	if err != nil {
		return nil, err
	}
	defer r.Close()

	rawData, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}

	info := &state.LockInfo{}
	if err := json.Unmarshal(rawData, info); err != nil {
		return nil, err
	}

	// We use the Generation as the ID, so overwrite the ID in the json.
	// This can't be written into the Info, since the generation isn't known
	// until it's written.
	attrs, err := c.lockFile().Attrs(c.storageContext)
	if err != nil {
		return nil, err
	}
	info.ID = strconv.FormatInt(attrs.Generation, 10)

	return info, nil
}