@Override
  public void setMetadata(FileMetadata metadata, byte type, AtomicDBUpdate update)
      throws DatabaseException {

    assert (metadata instanceof BufferBackedFileMetadata);
    BufferBackedFileMetadata md = (BufferBackedFileMetadata) metadata;

    int index = md.getIndexId();
    if (type == -1)
      for (byte i = 0; i < BufferBackedFileMetadata.NUM_BUFFERS; i++) {
        byte[] valBuf = md.getValueBuffer(i);
        assert (valBuf != null);
        update.addUpdate(
            index,
            index == FILE_ID_INDEX
                ? BabuDBStorageHelper.createFileIdIndexKey(metadata.getId(), i)
                : md.getKeyBuffer(i),
            valBuf);
      }
    else {
      byte[] valBuf = md.getValueBuffer(type);
      assert (valBuf != null);
      update.addUpdate(
          index,
          index == FILE_ID_INDEX
              ? BabuDBStorageHelper.createFileIdIndexKey(metadata.getId(), type)
              : md.getKeyBuffer(type),
          valBuf);
    }
  }
  @Override
  public FileMetadata createSymLink(
      long fileId,
      long parentId,
      String fileName,
      int atime,
      int ctime,
      int mtime,
      String userId,
      String groupId,
      String ref,
      AtomicDBUpdate update) {

    // create metadata
    BufferBackedFileMetadata fileMetadata =
        new BufferBackedFileMetadata(
            parentId,
            fileName,
            userId,
            groupId,
            fileId,
            atime,
            ctime,
            mtime,
            ref.length(),
            0777,
            0,
            (short) 1,
            0,
            0,
            false);

    // create link target (XAttr)
    BufferBackedXAttr lt =
        new BufferBackedXAttr(fileId, SYSTEM_UID, LINK_TARGET_ATTR_NAME, ref.getBytes(), (short) 0);
    update.addUpdate(XATTRS_INDEX, lt.getKeyBuf(), lt.getValBuf());

    // update main metadata in the file index
    update.addUpdate(
        FILE_INDEX, fileMetadata.getFCMetadataKey(), fileMetadata.getFCMetadataValue());
    update.addUpdate(
        FILE_INDEX, fileMetadata.getRCMetadata().getKey(), fileMetadata.getRCMetadata().getValue());

    // add an entry to the file ID index
    update.addUpdate(
        FILE_ID_INDEX,
        BabuDBStorageHelper.createFileIdIndexKey(fileId, (byte) 3),
        BabuDBStorageHelper.createFileIdIndexValue(parentId, fileName));

    return fileMetadata;
  }
  @Override
  public FileMetadata getMetadata(long fileId) throws DatabaseException {

    try {

      // create the key for the file ID index lookup
      byte[] key = BabuDBStorageHelper.createFileIdIndexKey(fileId, (byte) -1);
      ByteBuffer.wrap(key).putLong(fileId);

      byte[][] valBufs = new byte[BufferBackedFileMetadata.NUM_BUFFERS][];

      // retrieve the metadata from the link index
      ResultSet<byte[], byte[]> it =
          database.prefixLookup(BabuDBStorageManager.FILE_ID_INDEX, key, null).get();

      while (it.hasNext()) {

        Entry<byte[], byte[]> curr = it.next();

        int type = BabuDBStorageHelper.getType(curr.getKey(), BabuDBStorageManager.FILE_ID_INDEX);

        // if the value is a back link, resolve it
        if (type == 3) {

          long parentId = ByteBuffer.wrap(curr.getValue()).getLong();
          String fileName = new String(curr.getValue(), 8, curr.getValue().length - 8);

          return getMetadata(parentId, fileName);
        }

        valBufs[type] = curr.getValue();
      }

      it.free();

      // if not metadata was found for the file ID, return null
      if (valBufs[FileMetadata.RC_METADATA] == null) return null;

      byte[][] keyBufs =
          new byte[][] {null, BabuDBStorageHelper.createFileKey(0, "", FileMetadata.RC_METADATA)};

      // otherwise, a hard link target is contained in the index; create a
      // new metadata object in this case
      return new BufferBackedFileMetadata(keyBufs, valBufs, BabuDBStorageManager.FILE_ID_INDEX);

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
  @Override
  public byte[] getXAttr(long fileId, String uid, String key) throws DatabaseException {

    ResultSet<byte[], byte[]> it = null;
    try {

      // peform a prefix lookup
      byte[] prefix = BabuDBStorageHelper.createXAttrPrefixKey(fileId, uid, key);
      it = database.prefixLookup(XATTRS_INDEX, prefix, null).get();

      // check whether the entry is the correct one
      while (it.hasNext()) {

        Entry<byte[], byte[]> curr = it.next();
        BufferBackedXAttr xattr = new BufferBackedXAttr(curr.getKey(), curr.getValue());
        if (uid.equals(xattr.getOwner()) && key.equals(xattr.getKey())) return xattr.getValue();
      }

      return null;

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    } finally {
      if (it != null) it.free();
    }
  }
  protected long getNumDirs() throws DatabaseException {
    try {
      byte[] sizeBytes = BabuDBStorageHelper.getVolumeMetadata(database, NUM_DIRS_KEY);
      return ByteBuffer.wrap(sizeBytes).getLong(0);

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
  @Override
  public FileMetadata getMetadata(final long parentId, final String fileName)
      throws DatabaseException {

    try {
      return BabuDBStorageHelper.getMetadata(database, parentId, fileName);
    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
  @Override
  public DatabaseResultSet<FileMetadata> getChildren(long parentId, int seen, int num)
      throws DatabaseException {

    try {
      return BabuDBStorageHelper.getChildren(database, parentId, seen, num);
    } catch (Exception exc) {
      throw new DatabaseException(exc);
    }
  }
  @Override
  public FileMetadata createFile(
      long fileId,
      long parentId,
      String fileName,
      int atime,
      int ctime,
      int mtime,
      String userId,
      String groupId,
      int perms,
      long w32Attrs,
      long size,
      boolean readOnly,
      int epoch,
      int issEpoch,
      AtomicDBUpdate update)
      throws DatabaseException {

    // create metadata
    BufferBackedFileMetadata fileMetadata =
        new BufferBackedFileMetadata(
            parentId, fileName, userId, groupId, fileId, atime, ctime, mtime, size, perms, w32Attrs,
            (short) 1, epoch, issEpoch, readOnly);

    // update main metadata in the file index
    update.addUpdate(
        FILE_INDEX, fileMetadata.getFCMetadataKey(), fileMetadata.getFCMetadataValue());
    update.addUpdate(
        FILE_INDEX, fileMetadata.getRCMetadata().getKey(), fileMetadata.getRCMetadata().getValue());

    // add an entry to the file ID index
    update.addUpdate(
        FILE_ID_INDEX,
        BabuDBStorageHelper.createFileIdIndexKey(fileId, (byte) 3),
        BabuDBStorageHelper.createFileIdIndexValue(parentId, fileName));

    volume.updateVolumeSize(size, update);
    updateCount(NUM_FILES_KEY, true, update);

    return fileMetadata;
  }
  private void updateCount(byte[] key, boolean increment, AtomicDBUpdate update)
      throws DatabaseException {

    try {
      byte[] countBytes = BabuDBStorageHelper.getVolumeMetadata(database, key);
      ByteBuffer countBuf = ByteBuffer.wrap(countBytes);
      countBuf.putLong(0, countBuf.getLong() + (increment ? 1 : -1));

      update.addUpdate(VOLUME_INDEX, key, countBytes);
    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #10
0
  @Override
  public short unlink(final long parentId, final String fileName, final AtomicDBUpdate update)
      throws DatabaseException {

    try {

      // retrieve the file metadata
      BufferBackedFileMetadata file = BabuDBStorageHelper.getMetadata(database, parentId, fileName);

      // determine and set the new link count
      short newLinkCount = (short) (file.getLinkCount() - 1);
      file.setLinkCount(newLinkCount);

      // if there will be links remaining after the deletion, update the
      // link count; it must be in the FILE_ID_INDEX, because there have
      // been at least two links
      if (newLinkCount > 0)
        update.addUpdate(
            FILE_ID_INDEX,
            BabuDBStorageHelper.createFileIdIndexKey(file.getId(), FileMetadata.RC_METADATA),
            file.getRCMetadata().getValue());

      // remove all entries from the file index
      update.addUpdate(
          FILE_INDEX,
          BabuDBStorageHelper.createFileKey(parentId, fileName, FileMetadata.FC_METADATA),
          null);
      update.addUpdate(
          FILE_INDEX,
          BabuDBStorageHelper.createFileKey(parentId, fileName, FileMetadata.RC_METADATA),
          null);

      return newLinkCount;

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #11
0
  public FileMetadata createDir(
      long fileId,
      long parentId,
      String fileName,
      int atime,
      int ctime,
      int mtime,
      String userId,
      String groupId,
      int perms,
      long w32Attrs,
      boolean initCount,
      AtomicDBUpdate update)
      throws DatabaseException {

    // create metadata
    BufferBackedFileMetadata fileMetadata =
        new BufferBackedFileMetadata(
            parentId, fileName, userId, groupId, fileId, atime, ctime, mtime, perms, w32Attrs,
            (short) 1);

    // update main metadata in the file index
    update.addUpdate(
        FILE_INDEX, fileMetadata.getFCMetadataKey(), fileMetadata.getFCMetadataValue());
    update.addUpdate(
        FILE_INDEX, fileMetadata.getRCMetadata().getKey(), fileMetadata.getRCMetadata().getValue());

    // add an entry to the file ID index
    update.addUpdate(
        FILE_ID_INDEX,
        BabuDBStorageHelper.createFileIdIndexKey(fileId, (byte) 3),
        BabuDBStorageHelper.createFileIdIndexValue(parentId, fileName));

    if (initCount) initCount(NUM_DIRS_KEY, update);
    else updateCount(NUM_DIRS_KEY, true, update);

    return fileMetadata;
  }
Пример #12
0
  @Override
  public DatabaseResultSet<ACLEntry> getACL(long fileId) throws DatabaseException {

    try {

      byte[] prefix = BabuDBStorageHelper.createACLPrefixKey(fileId, null);
      ResultSet<byte[], byte[]> it = database.prefixLookup(ACL_INDEX, prefix, null).get();

      return new ACLIterator(it);

    } catch (Exception exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #13
0
  @Override
  public ACLEntry getACLEntry(long fileId, String entity) throws DatabaseException {

    try {

      byte[] key = BabuDBStorageHelper.createACLPrefixKey(fileId, entity);
      byte[] value = database.lookup(ACL_INDEX, key, null).get();

      return value == null ? null : new BufferBackedACLEntry(key, value);

    } catch (Exception exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #14
0
  @Override
  public DatabaseResultSet<XAttr> getXAttrs(long fileId, String uid) throws DatabaseException {

    try {

      // peform a prefix lookup
      byte[] prefix = BabuDBStorageHelper.createXAttrPrefixKey(fileId, uid, null);
      ResultSet<byte[], byte[]> it = database.prefixLookup(XATTRS_INDEX, prefix, null).get();

      return new XAttrIterator(it, uid);

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #15
0
  @Override
  public long getNextFileId() throws DatabaseException {

    try {
      // get the file ID assigned to the last created file or
      // directory
      byte[] idBytes = BabuDBStorageHelper.getLastAssignedFileId(database);

      // calculate the new file ID
      ByteBuffer tmp = ByteBuffer.wrap(idBytes);
      long id = tmp.getLong(0) + 1;

      return id;
    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #16
0
  public void setXAttr(
      long fileId, String uid, String key, byte[] value, boolean init, AtomicDBUpdate update)
      throws DatabaseException {

    try {
      short collNumber =
          init ? -1 : BabuDBStorageHelper.findXAttrCollisionNumber(database, fileId, uid, key);

      BufferBackedXAttr xattr = new BufferBackedXAttr(fileId, uid, key, value, collNumber);
      update.addUpdate(XATTRS_INDEX, xattr.getKeyBuf(), value == null ? null : xattr.getValBuf());

      if (key.startsWith(SYS_ATTR_KEY_PREFIX + MRCHelper.POLICY_ATTR_PREFIX))
        notifyAttributeSet(volume.getId(), key, value == null ? null : new String(value));

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #17
0
  @Override
  public void link(
      final FileMetadata metadata,
      final long newParentId,
      final String newFileName,
      final AtomicDBUpdate update) {

    // get the link source
    BufferBackedFileMetadata md = (BufferBackedFileMetadata) metadata;

    // increment the link count
    short links = metadata.getLinkCount();
    md.setLinkCount((short) (links + 1));

    // insert the whole metadata of the original file in the file ID
    // index
    update.addUpdate(
        FILE_ID_INDEX,
        BabuDBStorageHelper.createFileIdIndexKey(metadata.getId(), FileMetadata.FC_METADATA),
        md.getFCMetadataValue());
    update.addUpdate(
        FILE_ID_INDEX,
        BabuDBStorageHelper.createFileIdIndexKey(metadata.getId(), FileMetadata.RC_METADATA),
        md.getRCMetadata().getValue());

    // remove the back link
    update.addUpdate(
        FILE_ID_INDEX, BabuDBStorageHelper.createFileIdIndexKey(metadata.getId(), (byte) 3), null);

    // if the metadata was retrieved from the FILE_INDEX and hasn't
    // been deleted before (i.e. links == 0), ensure that the original
    // file in the file index now points to the file ID index, and
    // remove the FC and XLoc metadata entries
    if (links != 0 && md.getIndexId() == FILE_INDEX) {

      update.addUpdate(
          FILE_INDEX,
          md.getRCMetadata().getKey(),
          BabuDBStorageHelper.createLinkTarget(metadata.getId()));
      update.addUpdate(FILE_INDEX, md.getFCMetadataKey(), null);
    }

    // create an entry for the new link to the metadata in the file
    // index
    update.addUpdate(
        FILE_INDEX,
        BabuDBStorageHelper.createFileKey(newParentId, newFileName, FileMetadata.RC_METADATA),
        BabuDBStorageHelper.createLinkTarget(metadata.getId()));
  }
Пример #18
0
  @Override
  public FileMetadata[] resolvePath(final Path path) throws DatabaseException {

    try {
      FileMetadata[] md = new FileMetadata[path.getCompCount()];

      long parentId = 0;
      for (int i = 0; i < md.length; i++) {
        md[i] = BabuDBStorageHelper.getMetadata(database, parentId, path.getComp(i));
        if (md[i] == null || i < md.length - 1 && !md[i].isDirectory()) {
          md[i] = null;
          return md;
        }
        parentId = md[i].getId();
      }

      return md;

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #19
0
  @Override
  public void createSnapshot(String snapName, long parentId, String dirName, boolean recursive)
      throws DatabaseException {

    try {

      // determine the prefixes for the snapshot
      byte[][][] prefixes = null;

      FileMetadata snapDir = getMetadata(parentId, dirName);

      // for a full volume snapshot, simply use a 'null' prefix (full:
      // dirID == 1 && recursive)
      if (snapDir.getId() != 1 || !recursive) {

        // get the IDs of all files and directories contained in the
        // given directory; if recursive == true, include subdirectories
        List<FileMetadata> nestedFiles = new LinkedList<FileMetadata>();
        BabuDBStorageHelper.getNestedFiles(nestedFiles, database, snapDir.getId(), recursive);

        List<byte[]> dirEntryPrefixes = new ArrayList<byte[]>(nestedFiles.size());
        List<byte[]> filePrefixes = new ArrayList<byte[]>(nestedFiles.size());

        // include the extended attributes of the volume's root
        // directory if it's not the snapshot directory - they are
        // needed to access volume-wide parameters in the snapshot, such
        // as the access control policy
        if (snapDir.getId() != 1) filePrefixes.add(ByteBuffer.wrap(new byte[8]).putLong(1).array());

        // include all metadata of the snapshot (i.e. top level) dir
        byte[] idxKey = BabuDBStorageHelper.createFileKey(parentId, dirName, (byte) -1);
        byte[] fileKey = BabuDBStorageHelper.createFilePrefixKey(snapDir.getId());
        dirEntryPrefixes.add(idxKey);
        filePrefixes.add(fileKey);

        // include the snapshot directory content
        idxKey = BabuDBStorageHelper.createFilePrefixKey(snapDir.getId());
        dirEntryPrefixes.add(idxKey);

        // determine the key prefixes of all nested files to include and
        // exclude
        for (FileMetadata file : nestedFiles) {

          // create a prefix key for the nested file
          byte[] key = BabuDBStorageHelper.createFilePrefixKey(file.getId());

          // if the nested file is a directory, ...
          if (file.isDirectory()) {

            // include the directory in the file prefixes
            // and the directory prefix in the dir entry prefixes
            filePrefixes.add(key);
            dirEntryPrefixes.add(key);
          }

          // if the nested file is a file, ...
          else filePrefixes.add(key);
        }

        byte[][] dirEntryPrefixesA = dirEntryPrefixes.toArray(new byte[dirEntryPrefixes.size()][]);
        byte[][] filePrefixesA = filePrefixes.toArray(new byte[filePrefixes.size()][]);

        Arrays.sort(dirEntryPrefixesA, DefaultByteRangeComparator.getInstance());
        Arrays.sort(filePrefixesA, DefaultByteRangeComparator.getInstance());

        // FILE_INDEX, XATTRS_INDEX, ACL_INDEX, FILE_ID_INDEX,
        // VOLUME_INDEX
        prefixes =
            new byte[][][] {dirEntryPrefixesA, filePrefixesA, filePrefixesA, filePrefixesA, null};
      }

      // create the snapshot
      SnapshotConfig snap = new DefaultSnapshotConfig(snapName, ALL_INDICES, prefixes, null);
      snapMan.createPersistentSnapshot(database.getName(), snap);

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }
Пример #20
0
  @Override
  public short delete(final long parentId, final String fileName, final AtomicDBUpdate update)
      throws DatabaseException {

    try {

      // retrieve the file metadata
      BufferBackedFileMetadata file = BabuDBStorageHelper.getMetadata(database, parentId, fileName);

      // check whether there is only one link remaining
      short newLinkCount = (short) (file.getLinkCount() - 1);
      assert (newLinkCount >= 0);

      // decrement the link count
      file.setLinkCount(newLinkCount);

      // if there will be links remaining after the deletion, update the
      // link count
      if (newLinkCount > 0)
        update.addUpdate(
            FILE_ID_INDEX,
            BabuDBStorageHelper.createFileIdIndexKey(file.getId(), FileMetadata.RC_METADATA),
            file.getRCMetadata().getValue());

      // delete all keys ...

      // remove all content from the file index
      update.addUpdate(
          BabuDBStorageManager.FILE_INDEX,
          BabuDBStorageHelper.createFileKey(parentId, fileName, FileMetadata.FC_METADATA),
          null);
      update.addUpdate(
          BabuDBStorageManager.FILE_INDEX,
          BabuDBStorageHelper.createFileKey(parentId, fileName, FileMetadata.RC_METADATA),
          null);

      // if the last link to the file is supposed to be deleted, remove
      // the remaining metadata, including ACLs and XAttrs
      if (newLinkCount == 0) {

        // remove the back link from the file ID index
        update.addUpdate(
            BabuDBStorageManager.FILE_ID_INDEX,
            BabuDBStorageHelper.createFileIdIndexKey(file.getId(), (byte) 3),
            null);

        // remove potentially existing metadata from the file ID index
        update.addUpdate(
            BabuDBStorageManager.FILE_ID_INDEX,
            BabuDBStorageHelper.createFileIdIndexKey(file.getId(), FileMetadata.FC_METADATA),
            null);
        update.addUpdate(
            BabuDBStorageManager.FILE_ID_INDEX,
            BabuDBStorageHelper.createFileIdIndexKey(file.getId(), FileMetadata.RC_METADATA),
            null);

        byte[] idBytes = new byte[8];
        ByteBuffer.wrap(idBytes).putLong(file.getId());

        // remove all ACLs
        ResultSet<byte[], byte[]> it =
            database.prefixLookup(BabuDBStorageManager.ACL_INDEX, idBytes, null).get();
        while (it.hasNext())
          update.addUpdate(BabuDBStorageManager.ACL_INDEX, it.next().getKey(), null);
        it.free();

        // remove all extended attributes
        it = database.prefixLookup(BabuDBStorageManager.XATTRS_INDEX, idBytes, null).get();
        while (it.hasNext())
          update.addUpdate(BabuDBStorageManager.XATTRS_INDEX, it.next().getKey(), null);
        it.free();

        // if a file is deleted, update file count and volume size
        if (file.isDirectory()) {
          updateCount(NUM_DIRS_KEY, false, update);
        } else if (file.getXLocList() != null) {
          volume.updateVolumeSize(-file.getSize(), update);
          updateCount(NUM_FILES_KEY, false, update);
        }
      }

      return file.getLinkCount();

    } catch (BabuDBException exc) {
      throw new DatabaseException(exc);
    }
  }