org.dcache.chimera.H2FsSqlDriver.java Source code

Java tutorial

Introduction

Here is the source code for org.dcache.chimera.H2FsSqlDriver.java

Source

/*
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This library 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 Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program (see the file COPYING.LIB for more
 * details); if not, write to the Free Software Foundation, Inc.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.dcache.chimera;

import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import javax.sql.DataSource;

import java.io.ByteArrayInputStream;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.EnumSet;

import org.dcache.acl.enums.AceFlags;
import org.dcache.acl.enums.RsType;
import org.dcache.chimera.posix.Stat;

/**
 * H2 database specific dialect.
 */
public class H2FsSqlDriver extends FsSqlDriver {

    public H2FsSqlDriver(DataSource dataSource) throws ChimeraFsException {
        super(dataSource);
    }

    @Override
    Stat createInode(String id, int type, int uid, int gid, int mode, int nlink, long size) {
        /* H2 uses weird names for the column with the auto-generated key, so we cannot use the code
         * in the base class.
         */
        Timestamp now = new Timestamp(System.currentTimeMillis());
        KeyHolder keyHolder = new GeneratedKeyHolder();
        _jdbc.update(con -> {
            PreparedStatement ps = con.prepareStatement(
                    "INSERT INTO t_inodes (ipnfsid,itype,imode,inlink,iuid,igid,isize,iio,"
                            + "ictime,iatime,imtime,icrtime,igeneration) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)",
                    Statement.RETURN_GENERATED_KEYS);
            ps.setString(1, id);
            ps.setInt(2, type);
            ps.setInt(3, mode & UnixPermission.S_PERMS);
            ps.setInt(4, nlink);
            ps.setInt(5, uid);
            ps.setInt(6, gid);
            ps.setLong(7, size);
            ps.setInt(8, _ioMode);
            ps.setTimestamp(9, now);
            ps.setTimestamp(10, now);
            ps.setTimestamp(11, now);
            ps.setTimestamp(12, now);
            ps.setLong(13, 0);
            return ps;
        }, keyHolder);

        Stat stat = new Stat();
        stat.setIno((Long) keyHolder.getKey());
        stat.setId(id);
        stat.setCrTime(now.getTime());
        stat.setGeneration(0);
        stat.setSize(size);
        stat.setATime(now.getTime());
        stat.setCTime(now.getTime());
        stat.setMTime(now.getTime());
        stat.setUid(uid);
        stat.setGid(gid);
        stat.setMode(mode & UnixPermission.S_PERMS | type);
        stat.setNlink(nlink);
        stat.setDev(17);
        stat.setRdev(13);

        return stat;
    }

    @Override
    long createTagInode(int uid, int gid, int mode) {
        final String CREATE_TAG_INODE_WITHOUT_VALUE = "INSERT INTO t_tags_inodes (imode, inlink, iuid, igid, isize, "
                + "ictime, iatime, imtime, ivalue) VALUES (?,1,?,?,0,?,?,?,NULL)";

        Timestamp now = new Timestamp(System.currentTimeMillis());
        KeyHolder keyHolder = new GeneratedKeyHolder();
        int rc = _jdbc.update(con -> {
            PreparedStatement ps = con.prepareStatement(CREATE_TAG_INODE_WITHOUT_VALUE,
                    Statement.RETURN_GENERATED_KEYS);
            ps.setInt(1, mode | UnixPermission.S_IFREG);
            ps.setInt(2, uid);
            ps.setInt(3, gid);
            ps.setTimestamp(4, now);
            ps.setTimestamp(5, now);
            ps.setTimestamp(6, now);
            return ps;
        }, keyHolder);
        if (rc != 1) {
            throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(CREATE_TAG_INODE_WITHOUT_VALUE, 1, rc);
        }
        /* H2 uses weird names for the column with the auto-generated key, so we cannot use the code
         * in the base class.
         */
        return (Long) keyHolder.getKey();
    }

    @Override
    long createTagInode(int uid, int gid, int mode, byte[] value) {
        final String CREATE_TAG_INODE_WITH_VALUE = "INSERT INTO t_tags_inodes (imode, inlink, iuid, igid, isize, "
                + "ictime, iatime, imtime, ivalue) VALUES (?,1,?,?,?,?,?,?,?)";

        Timestamp now = new Timestamp(System.currentTimeMillis());
        KeyHolder keyHolder = new GeneratedKeyHolder();
        int rc = _jdbc.update(con -> {
            PreparedStatement ps = con.prepareStatement(CREATE_TAG_INODE_WITH_VALUE,
                    Statement.RETURN_GENERATED_KEYS);
            ps.setInt(1, mode | UnixPermission.S_IFREG);
            ps.setInt(2, uid);
            ps.setInt(3, gid);
            ps.setLong(4, value.length);
            ps.setTimestamp(5, now);
            ps.setTimestamp(6, now);
            ps.setTimestamp(7, now);
            ps.setBinaryStream(8, new ByteArrayInputStream(value), value.length);
            return ps;
        }, keyHolder);
        if (rc != 1) {
            throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(CREATE_TAG_INODE_WITH_VALUE, 1, rc);
        }
        /* H2 uses weird names for the column with the auto-generated key, so we cannot use the code
         * in the base class.
         */
        return (Long) keyHolder.getKey();
    }

    /**
     * copy all directory tags from origin directory to destination. New copy marked as inherited.
     *
     * @param orign
     * @param destination
     */
    @Override
    void copyTags(FsInode orign, FsInode destination) {
        _jdbc.update("INSERT INTO t_tags (inumber,itagid,isorign,itagname) (SELECT " + destination.ino()
                + ",itagid,0,itagname from t_tags WHERE inumber=?)", orign.ino());
    }

    @Override
    void copyAcl(FsInode source, FsInode inode, RsType type, EnumSet<AceFlags> mask, EnumSet<AceFlags> flags) {
        int msk = mask.stream().mapToInt(AceFlags::getValue).reduce(0, (a, b) -> a | b);
        int flgs = flags.stream().mapToInt(AceFlags::getValue).reduce(0, (a, b) -> a | b);
        _jdbc.update("INSERT INTO t_acl (inumber,rs_type,type,flags,access_msk,who,who_id,ace_order) "
                + "SELECT ?, ?, type, BITXOR(BITOR(flags, ?), ?), access_msk, who, who_id, ace_order "
                + "FROM t_acl WHERE inumber = ? AND BITAND(flags, ?) > 0", ps -> {
                    ps.setLong(1, inode.ino());
                    ps.setInt(2, type.getValue());
                    ps.setInt(3, msk);
                    ps.setInt(4, msk);
                    ps.setLong(5, source.ino());
                    ps.setInt(6, flgs);
                });
    }

    @Override
    public boolean isForeignKeyError(SQLException e) {
        return "23506".endsWith(e.getSQLState());
    }
}