Package io.fathom.cloud.storage.api.os.models

Source Code of io.fathom.cloud.storage.api.os.models.CloudObject

package io.fathom.cloud.storage.api.os.models;

import io.fathom.cloud.blobs.BlobData;
import io.fathom.cloud.blobs.BlobStore;
import io.fathom.cloud.protobuf.FileModel.FileData;
import io.fathom.cloud.protobuf.FileModel.FileRange;

import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import com.fathomdb.utils.Hex;
import com.google.common.collect.Lists;
import com.google.common.io.ByteSource;
import com.google.common.io.ByteStreams;
import com.google.protobuf.ByteString;

public class CloudObject {
    protected static final ByteSource EMPTY = ByteStreams.asByteSource(new byte[0]);
    final FileData data;

    public CloudObject(FileData data) {
        this.data = data;
    }

    public InputStream getInputStream(final BlobStore blobStore) throws IOException {
        return getInputStream(blobStore, null, null);
    }

    public InputStream getInputStream(final BlobStore blobStore, final Long from, final Long to) throws IOException {
        // if (data.getRangesCount() == 1) {
        // return getInputStream(keyValueStore, data.getRanges(0)
        // .getContentKey());
        // } else {
        // TODO: This can be made much more efficient

        List<FileRange> ranges = data.getRangesList();
        if (from != null || to != null) {
            List<FileRange> matching = Lists.newArrayList();
            for (FileRange range : ranges) {
                if (from != null) {
                    if (from > range.getEnd()) {
                        continue;
                    }
                }
                if (to != null) {
                    if (to <= range.getStart()) {
                        continue;
                    }
                }

                matching.add(range);
            }
            ranges = matching;
        }

        final Iterator<FileRange> it = data.getRangesList().iterator();

        SequenceInputStream sis = new SequenceInputStream(new Enumeration<InputStream>() {

            @Override
            public boolean hasMoreElements() {
                return it.hasNext();
            }

            @Override
            public InputStream nextElement() {
                ByteSource is;
                try {
                    FileRange range = it.next();
                    is = getBlob(blobStore, range.getContentKey());

                    if (to != null || from != null) {
                        long start = 0;
                        if (from != null) {
                            start = Math.max(0, from - range.getStart());

                            // Enforced by the skipping logic
                            assert start <= is.size();
                        }
                        long end = is.size();
                        if (to != null) {
                            end = Math.min(to - range.getStart(), is.size());

                            // Enforced by the skipping logic
                            assert end >= 0;
                        }

                        long length = end - start;
                        if (length <= 0) {
                            assert length == 0;
                            // Easier than worrying about hasNext
                            is = EMPTY;
                        } else {
                            is = is.slice(start, length);
                        }
                    }

                    // TODO: Open buffered stream??

                    return is.openStream();
                } catch (IOException e) {
                    throw new IllegalStateException("Error reading data", e);
                }
            }
        });

        return sis;
        // }
    }

    BlobData getBlob(BlobStore blobStore, ByteString key) throws IOException {
        final BlobData is = blobStore.find(key);

        if (is == null) {
            throw new IOException("Unable to open storage for range: " + Hex.toHex(key.toByteArray()));
        }

        return is;
    }

    public ByteSource asByteSource(final BlobStore blobStore, final Long from, final Long to) {
        return new ByteSource() {
            @Override
            public InputStream openStream() throws IOException {
                return getInputStream(blobStore, from, to);
            }
        };
    }

}
TOP

Related Classes of io.fathom.cloud.storage.api.os.models.CloudObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.