org.dcache.chimera.namespace.ExtendedInode.java Source code

Java tutorial

Introduction

Here is the source code for org.dcache.chimera.namespace.ExtendedInode.java

Source

/* dCache - http://www.dcache.org/
 *
 * Copyright (C) 2014 - 2015 Deutsches Elektronen-Synchrotron
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.dcache.chimera.namespace;

import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteSource;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import diskCacheV111.util.FsPath;
import diskCacheV111.util.PnfsId;

import org.dcache.acl.ACE;
import org.dcache.acl.ACL;
import org.dcache.acl.enums.RsType;
import org.dcache.chimera.ChimeraFsException;
import org.dcache.chimera.FileSystemProvider;
import org.dcache.chimera.FsInode;
import org.dcache.chimera.FsInodeType;
import org.dcache.chimera.StorageLocatable;
import org.dcache.chimera.UnixPermission;
import org.dcache.chimera.store.InodeStorageInformation;
import org.dcache.namespace.FileType;
import org.dcache.util.Checksum;

/**
 * A Chimera inode extension that provides easy access to and caching of data
 * associated with an inode.
 *
 * In the Chimera schema, the extended data isn't stored in the inode table
 * and thus isn't accessible through the base class.
 */
public class ExtendedInode extends FsInode {
    private ImmutableMap<String, byte[]> tags;
    private ImmutableList<Checksum> checksums;
    private ImmutableList<StorageLocatable> locations;
    private ImmutableMap<String, String> flags;
    private ACL acl;
    private HashMap<Integer, ExtendedInode> levels;
    private InodeStorageInformation storageInfo;
    private Optional<ExtendedInode> parent;

    private ExtendedInode(ExtendedInode parent, FsInode inode) {
        this(parent.getFs(), inode);
        this.parent = Optional.of(parent);
    }

    public ExtendedInode(FileSystemProvider fs, PnfsId id, FileSystemProvider.StatCacheOption option)
            throws ChimeraFsException {
        this(fs, fs.id2inode(id.toString(), option));
    }

    public ExtendedInode(FileSystemProvider fs, FsInode inode) {
        super(fs, inode);
    }

    public ExtendedInode(FileSystemProvider fs, long id, FsInodeType type) {
        super(fs, id, type);
    }

    public ExtendedInode(FileSystemProvider fs, long id) {
        super(fs, id);
    }

    public ExtendedInode(FileSystemProvider fs, long id, int level) {
        super(fs, id, level);
    }

    public ExtendedInode(FileSystemProvider fs, long id, FsInodeType type, int level) {
        super(fs, id, type, level);
    }

    @Override
    public ExtendedInode mkdir(String newDir) throws ChimeraFsException {
        return new ExtendedInode(this, super.mkdir(newDir));
    }

    @Override
    public ExtendedInode mkdir(String name, int owner, int group, int mode) throws ChimeraFsException {
        return new ExtendedInode(this, super.mkdir(name, owner, group, mode));
    }

    @Override
    public ExtendedInode mkdir(String name, int owner, int group, int mode, List<ACE> acl, Map<String, byte[]> tags)
            throws ChimeraFsException {
        return new ExtendedInode(this, super.mkdir(name, owner, group, mode, acl, tags));
    }

    @Override
    public ExtendedInode create(String name, int uid, int gid, int mode) throws ChimeraFsException {
        return new ExtendedInode(this, super.create(name, uid, gid, mode));
    }

    @Override
    public ExtendedInode inodeOf(String name, FileSystemProvider.StatCacheOption stat) throws ChimeraFsException {
        return new ExtendedInode(this, super.inodeOf(name, stat));
    }

    @Override
    public ExtendedInode getParent() {
        if (parent == null) {
            parent = Optional.ofNullable(super.getParent()).map(p -> new ExtendedInode(getFs(), p));
        }
        return parent.orElse(null);
    }

    public PnfsId getPnfsId() throws ChimeraFsException {
        return new PnfsId(getId());
    }

    public ImmutableMap<String, byte[]> getTags() throws ChimeraFsException {
        if (tags == null) {
            tags = ImmutableMap.copyOf(_fs.getAllTags(this));
        }
        return tags;
    }

    public ImmutableList<String> getTag(String tag) {
        try {
            byte[] data = getTags().get(tag);
            if (data == null || data.length == 0) {
                return ImmutableList.of();
            }
            return ByteSource.wrap(data).asCharSource(Charsets.UTF_8).readLines();
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }

    public ImmutableCollection<Checksum> getChecksums() throws ChimeraFsException {
        if (checksums == null) {
            checksums = ImmutableList.copyOf(_fs.getInodeChecksums(this));
        }
        return checksums;
    }

    public ImmutableList<String> getLocations(int type) throws ChimeraFsException {
        return ImmutableList.copyOf(
                getLocations().stream().filter(l -> l.type() == type).map(StorageLocatable::location).iterator());
    }

    public ImmutableList<StorageLocatable> getLocations() throws ChimeraFsException {
        if (locations == null) {
            locations = ImmutableList.copyOf(_fs.getInodeLocations(this));
        }
        return locations;
    }

    public ImmutableMap<String, String> getFlags() throws ChimeraFsException {
        if (flags == null) {
            ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
            ExtendedInode level2 = getLevel(2);
            try {
                ChimeraCacheInfo info = new ChimeraCacheInfo(level2);
                for (Map.Entry<String, String> e : info.getFlags().entrySet()) {
                    builder.put(e.getKey(), e.getValue());
                }
            } catch (IOException e) {
                throw new ChimeraFsException(e.getMessage(), e);
            }
            flags = builder.build();
        }
        return flags;
    }

    public ACL getAcl() throws ChimeraFsException {
        if (acl == null) {
            RsType rsType = isDirectory() ? RsType.DIR : RsType.FILE;
            acl = new ACL(rsType, _fs.getACL(this));
        }
        return acl;
    }

    public ExtendedInode getLevel(int level) {
        if (levels == null) {
            levels = new HashMap<>();
        }
        ExtendedInode inode = levels.get(level);
        if (inode == null) {
            inode = new ExtendedInode(_fs, ino(), level);
            levels.put(level, inode);
        }
        return inode;
    }

    public InodeStorageInformation getStorageInfo() throws ChimeraFsException {
        if (storageInfo == null) {
            storageInfo = _fs.getStorageInfo(this);
        }
        return storageInfo;
    }

    public FsPath getPath() throws ChimeraFsException {
        return FsPath.create(_fs.inode2path(this));
    }

    public FileType getFileType() throws ChimeraFsException {
        switch (UnixPermission.getType(statCache().getMode())) {
        case UnixPermission.S_IFREG:
            return FileType.REGULAR;
        case UnixPermission.S_IFDIR:
            return FileType.DIR;
        case UnixPermission.S_IFLNK:
            return FileType.LINK;
        default:
            return FileType.SPECIAL;
        }
    }
}