2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-11-06 11:40:06 +00:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package kvmetainfo
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"storj.io/storj/pkg/encryption"
|
|
|
|
"storj.io/storj/pkg/pb"
|
|
|
|
"storj.io/storj/pkg/storj"
|
2019-10-28 16:23:20 +00:00
|
|
|
"storj.io/storj/uplink/metainfo"
|
2018-11-06 11:40:06 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var _ storj.ReadOnlyStream = (*readonlyStream)(nil)
|
|
|
|
|
|
|
|
type readonlyStream struct {
|
2018-11-14 09:26:18 +00:00
|
|
|
db *DB
|
2018-11-06 11:40:06 +00:00
|
|
|
|
2019-09-10 16:39:47 +01:00
|
|
|
id storj.StreamID
|
2019-06-24 20:23:07 +01:00
|
|
|
info storj.Object
|
|
|
|
bucket string
|
|
|
|
encPath storj.Path
|
|
|
|
streamKey *storj.Key // lazySegmentReader derivedKey
|
2018-11-06 11:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (stream *readonlyStream) Info() storj.Object { return stream.info }
|
|
|
|
|
|
|
|
func (stream *readonlyStream) SegmentsAt(ctx context.Context, byteOffset int64, limit int64) (infos []storj.Segment, more bool, err error) {
|
2018-11-16 13:59:27 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2018-11-06 11:40:06 +00:00
|
|
|
if stream.info.FixedSegmentSize <= 0 {
|
|
|
|
return nil, false, errors.New("not implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
index := byteOffset / stream.info.FixedSegmentSize
|
|
|
|
return stream.Segments(ctx, index, limit)
|
|
|
|
}
|
|
|
|
|
2018-11-19 11:08:28 +00:00
|
|
|
func (stream *readonlyStream) segment(ctx context.Context, index int64) (segment storj.Segment, err error) {
|
2018-11-16 13:59:27 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2018-11-19 11:08:28 +00:00
|
|
|
segment = storj.Segment{
|
2018-11-06 11:40:06 +00:00
|
|
|
Index: index,
|
|
|
|
}
|
|
|
|
|
|
|
|
isLastSegment := segment.Index+1 == stream.info.SegmentCount
|
|
|
|
if !isLastSegment {
|
2019-10-28 16:23:20 +00:00
|
|
|
info, _, err := stream.db.metainfo.DownloadSegment(ctx, metainfo.DownloadSegmentParams{
|
|
|
|
StreamID: stream.id,
|
|
|
|
Position: storj.SegmentPosition{
|
|
|
|
Index: int32(index),
|
|
|
|
},
|
|
|
|
})
|
2018-11-06 11:40:06 +00:00
|
|
|
if err != nil {
|
|
|
|
return segment, err
|
|
|
|
}
|
|
|
|
|
|
|
|
segment.Size = stream.info.FixedSegmentSize
|
2019-10-28 16:23:20 +00:00
|
|
|
segment.EncryptedKeyNonce = info.SegmentEncryption.EncryptedKeyNonce
|
|
|
|
segment.EncryptedKey = info.SegmentEncryption.EncryptedKey
|
2018-11-06 11:40:06 +00:00
|
|
|
} else {
|
|
|
|
segment.Size = stream.info.LastSegment.Size
|
|
|
|
segment.EncryptedKeyNonce = stream.info.LastSegment.EncryptedKeyNonce
|
|
|
|
segment.EncryptedKey = stream.info.LastSegment.EncryptedKey
|
|
|
|
}
|
|
|
|
|
2019-07-03 19:07:44 +01:00
|
|
|
contentKey, err := encryption.DecryptKey(segment.EncryptedKey, stream.Info().EncryptionParameters.CipherSuite, stream.streamKey, &segment.EncryptedKeyNonce)
|
2018-11-06 11:40:06 +00:00
|
|
|
if err != nil {
|
|
|
|
return segment, err
|
|
|
|
}
|
|
|
|
|
2018-11-19 11:08:28 +00:00
|
|
|
nonce := new(storj.Nonce)
|
|
|
|
_, err = encryption.Increment(nonce, index+1)
|
|
|
|
if err != nil {
|
|
|
|
return segment, err
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:01:49 +00:00
|
|
|
if isLastSegment {
|
|
|
|
index = -1
|
|
|
|
}
|
|
|
|
|
2019-10-23 07:59:56 +01:00
|
|
|
pointer, err := stream.db.metainfo.SegmentInfoOld(ctx, stream.bucket, stream.encPath, index)
|
2018-11-19 11:08:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return segment, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if pointer.GetType() == pb.Pointer_INLINE {
|
2019-07-03 19:07:44 +01:00
|
|
|
segment.Inline, err = encryption.Decrypt(pointer.InlineSegment, stream.info.EncryptionParameters.CipherSuite, contentKey, nonce)
|
2018-11-19 11:08:28 +00:00
|
|
|
} else {
|
2019-03-18 10:55:06 +00:00
|
|
|
segment.PieceID = pointer.Remote.RootPieceId
|
2018-11-19 11:08:28 +00:00
|
|
|
segment.Pieces = make([]storj.Piece, 0, len(pointer.Remote.RemotePieces))
|
|
|
|
for _, piece := range pointer.Remote.RemotePieces {
|
|
|
|
var nodeID storj.NodeID
|
2018-11-29 18:39:27 +00:00
|
|
|
copy(nodeID[:], piece.NodeId.Bytes())
|
2018-11-19 11:08:28 +00:00
|
|
|
segment.Pieces = append(segment.Pieces, storj.Piece{Number: byte(piece.PieceNum), Location: nodeID})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-06 11:40:06 +00:00
|
|
|
return segment, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (stream *readonlyStream) Segments(ctx context.Context, index int64, limit int64) (infos []storj.Segment, more bool, err error) {
|
2018-11-16 13:59:27 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2018-11-06 11:40:06 +00:00
|
|
|
if index < 0 {
|
|
|
|
return nil, false, errors.New("invalid argument")
|
|
|
|
}
|
|
|
|
if limit <= 0 {
|
|
|
|
limit = defaultSegmentLimit
|
|
|
|
}
|
|
|
|
if index >= stream.info.SegmentCount {
|
|
|
|
return nil, false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
infos = make([]storj.Segment, 0, limit)
|
|
|
|
for ; index < stream.info.SegmentCount && limit > 0; index++ {
|
|
|
|
limit--
|
|
|
|
segment, err := stream.segment(ctx, index)
|
|
|
|
if err != nil {
|
|
|
|
return nil, false, err
|
|
|
|
}
|
|
|
|
infos = append(infos, segment)
|
|
|
|
}
|
|
|
|
|
2018-11-15 15:31:33 +00:00
|
|
|
more = index < stream.info.SegmentCount
|
2018-11-06 11:40:06 +00:00
|
|
|
return infos, more, nil
|
|
|
|
}
|
2018-11-30 13:50:52 +00:00
|
|
|
|
|
|
|
type mutableStream struct {
|
|
|
|
db *DB
|
|
|
|
info storj.Object
|
|
|
|
}
|
|
|
|
|
|
|
|
func (stream *mutableStream) Info() storj.Object { return stream.info }
|
|
|
|
|
2019-06-04 12:36:27 +01:00
|
|
|
func (stream *mutableStream) AddSegments(ctx context.Context, segments ...storj.Segment) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2018-11-30 13:50:52 +00:00
|
|
|
return errors.New("not implemented")
|
|
|
|
}
|
|
|
|
|
2019-06-04 12:36:27 +01:00
|
|
|
func (stream *mutableStream) UpdateSegments(ctx context.Context, segments ...storj.Segment) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2018-11-30 13:50:52 +00:00
|
|
|
return errors.New("not implemented")
|
|
|
|
}
|