コード例 #1
0
ファイル: directoryLayer.go プロジェクト: ptomasroos/fdb-go
func (dl directoryLayer) createOrOpen(rtr fdb.ReadTransaction, tr *fdb.Transaction, path []string, layer []byte, prefix []byte, allowCreate, allowOpen bool) (DirectorySubspace, error) {
	if e := dl.checkVersion(rtr, nil); e != nil {
		return nil, e
	}

	if prefix != nil && !dl.allowManualPrefixes {
		if len(dl.path) == 0 {
			return nil, errors.New("cannot specify a prefix unless manual prefixes are enabled")
		} else {
			return nil, errors.New("cannot specify a prefix in a partition")
		}
	}

	if len(path) == 0 {
		return nil, errors.New("the root directory cannot be opened")
	}

	existingNode := dl.find(rtr, path).prefetchMetadata(rtr)
	if existingNode.exists() {
		if existingNode.isInPartition(nil, false) {
			subpath := existingNode.getPartitionSubpath()
			enc, e := existingNode.getContents(dl, nil)
			if e != nil {
				return nil, e
			}
			return enc.(directoryPartition).createOrOpen(rtr, tr, subpath, layer, prefix, allowCreate, allowOpen)
		}

		if !allowOpen {
			return nil, errors.New("the directory already exists")
		}

		if layer != nil && bytes.Compare(existingNode._layer.MustGet(), layer) != 0 {
			return nil, errors.New("the directory was created with an incompatible layer")
		}

		return existingNode.getContents(dl, nil)
	}

	if !allowCreate {
		return nil, errors.New("the directory does not exist")
	}

	if e := dl.checkVersion(rtr, tr); e != nil {
		return nil, e
	}

	if prefix == nil {
		newss, e := dl.allocator.allocate(*tr, dl.contentSS)
		if e != nil {
			return nil, fmt.Errorf("unable to allocate new directory prefix (%s)", e.Error())
		}

		if !isRangeEmpty(rtr, newss) {
			return nil, fmt.Errorf("the database has keys stored at the prefix chosen by the automatic prefix allocator: %v", prefix)
		}

		prefix = newss.Bytes()

		pf, e := dl.isPrefixFree(rtr.Snapshot(), prefix)
		if e != nil {
			return nil, e
		}
		if !pf {
			return nil, errors.New("the directory layer has manually allocated prefixes that conflict with the automatic prefix allocator")
		}
	} else {
		pf, e := dl.isPrefixFree(rtr, prefix)
		if e != nil {
			return nil, e
		}
		if !pf {
			return nil, errors.New("the given prefix is already in use")
		}
	}

	var parentNode subspace.Subspace

	if len(path) > 1 {
		pd, e := dl.createOrOpen(rtr, tr, path[:len(path)-1], nil, nil, true, true)
		if e != nil {
			return nil, e
		}
		parentNode = dl.nodeWithPrefix(pd.Bytes())
	} else {
		parentNode = dl.rootNode
	}

	if parentNode == nil {
		return nil, errors.New("the parent directory does not exist")
	}

	node := dl.nodeWithPrefix(prefix)
	tr.Set(parentNode.Sub(_SUBDIRS, path[len(path)-1]), prefix)

	if layer == nil {
		layer = []byte{}
	}

	tr.Set(node.Sub([]byte("layer")), layer)

	return dl.contentsOfNode(node, path, layer)
}