Пример #1
0
func (p *memp) CopyTo(dst w.Path, opt w.CopyOptions) (bool, error) {
	p.fs.m.Lock()
	defer p.fs.m.Unlock()

	dstp, ok := dst.(*memp)
	if !ok {
		return false, w.ErrorBadHost
	}

	if p.path == dstp.path {
		return false, w.ErrorSameFile
	}

	srcf, err := p.internalLookup()
	if err != nil {
		return false, w.ErrorNotFound
	}

	// Can only move complete directory trees.
	if srcf.IsDirectory() && opt.Move && opt.Depth >= 0 {
		return false, w.ErrorIsDir
	}

	if _, err := dstp.parent().internalLookup(); err != nil {
		return false, w.ErrorMissingParent
	}

	newf := true
	_, err = dstp.internalLookup()
	if err == nil {
		if opt.Overwrite {
			newf = false
			p.removeSubtree(dstp.path)
		} else {
			return false, w.ErrorDestExists
		}
	}

	for orig, v := range p.fs.files {
		nn, ok := wp.Included(orig, p.path, opt.Depth)
		if !ok {
			continue
		}
		nn = path.Join(dstp.path, nn)
		if opt.Move {
			log.Printf("MOVE %s -> %s", orig, nn)
			// Note: As we adjust path here, it is important that
			// this move operation does not depend on anything
			// file-related.
			v.path = nn
			p.fs.files[nn] = v
			delete(p.fs.files, orig)
		} else {
			log.Printf("COPY %s -> %s", orig, nn)
			nv := v.clone(nn)
			p.fs.files[nn] = nv
		}
	}
	return newf, nil
}
Пример #2
0
func (lm *lockmaster) refreshLock(tok string, path Path, duration time.Duration) (*lock, error) {
	lm.m.Lock()
	defer lm.m.Unlock()

	p := path.String()

	// We enforce all locks to be a minimum of ten seconds.
	if duration < minLockDuration {
		duration = minLockDuration
	}
	if duration > maxLockDuration {
		duration = maxLockDuration
	}

	l, ok := lm.locks[tok]
	if !ok {
		return nil, fmt.Errorf("unknown lock: %s", tok)
	}
	if l.expired() {
		delete(lm.locks, l.token)
		return nil, errors.New("expired lock")
	}
	if _, ok := wp.Included(p, l.path, l.depth); !ok {
		return nil, errors.New("path not within lock")
	}
	l.duration = duration
	l.touch()
	return l, nil
}
Пример #3
0
func (lm *lockmaster) createLock(owner string, path Path, depth int, duration time.Duration) (*lock, error) {
	lm.m.Lock()
	defer lm.m.Unlock()

	p := path.String()

	// We enforce all locks to be a minimum of ten seconds.
	if duration < minLockDuration {
		duration = minLockDuration
	}
	if duration > maxLockDuration {
		duration = maxLockDuration
	}

	for _, l := range lm.locks {
		if l.expired() {
			delete(lm.locks, l.token)
			continue
		}

		// Check if the lock covers this path already.
		if _, ok := wp.Included(p, l.path, l.depth); ok {
			return nil, ErrorLocked
		}

		// Check if this crosses another lock.
		if _, ok := wp.Included(l.path, p, depth); ok {
			return nil, ErrorLocked
		}
	}

	l := &lock{
		token:    lm.generateToken(),
		depth:    depth,
		owner:    owner,
		duration: duration,
		modified: time.Now(),
		path:     p,
	}
	lm.locks[l.token] = l
	return l, nil
}
Пример #4
0
func (lm *lockmaster) isLocked(p, t string) bool {
	lm.m.Lock()
	defer lm.m.Unlock()
	l := lm.locks[t]
	if l == nil || l.expired() {
		delete(lm.locks, t)
		return false
	}
	_, ok := wp.Included(p, l.path, l.depth)
	return ok
}
Пример #5
0
func (lm *lockmaster) getLockForPath(p string) *lock {
	lm.m.Lock()
	defer lm.m.Unlock()
	for _, l := range lm.locks {
		if l.expired() {
			delete(lm.locks, l.token)
			continue
		}

		if _, ok := wp.Included(p, l.path, l.depth); !ok {
			continue
		}
		return l
	}
	return nil
}
Пример #6
0
func (p *memp) LookupSubtree(depth int) ([]w.File, error) {
	_, err := p.Lookup()
	if err != nil {
		return nil, err
	}

	p.fs.m.Lock()
	defer p.fs.m.Unlock()

	var files []w.File
	for fn, f := range p.fs.files {
		if _, ok := wp.Included(fn, p.path, depth); ok {
			files = append(files, f)
		}
	}
	return files, nil
}