2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-08-17 18:40:15 +01:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2018-11-06 17:49:17 +00:00
|
|
|
package psserver
|
2018-08-17 18:40:15 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2018-12-17 15:23:02 +00:00
|
|
|
"fmt"
|
2018-08-17 18:40:15 +01:00
|
|
|
"io"
|
2018-12-12 19:14:51 +00:00
|
|
|
"time"
|
2018-08-17 18:40:15 +01:00
|
|
|
|
|
|
|
"github.com/zeebo/errs"
|
2018-11-08 20:27:07 +00:00
|
|
|
"go.uber.org/zap"
|
2018-10-16 12:43:44 +01:00
|
|
|
|
2018-09-18 05:39:06 +01:00
|
|
|
"storj.io/storj/pkg/pb"
|
2018-08-17 18:40:15 +01:00
|
|
|
"storj.io/storj/pkg/utils"
|
|
|
|
)
|
|
|
|
|
|
|
|
// OK - Success!
|
|
|
|
const OK = "OK"
|
|
|
|
|
|
|
|
// StoreError is a type of error for failures in Server.Store()
|
|
|
|
var StoreError = errs.Class("store error")
|
|
|
|
|
|
|
|
// Store incoming data using piecestore
|
|
|
|
func (s *Server) Store(reqStream pb.PieceStoreRoutes_StoreServer) (err error) {
|
|
|
|
ctx := reqStream.Context()
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
// Receive id/ttl
|
|
|
|
recv, err := reqStream.Recv()
|
|
|
|
if err != nil {
|
|
|
|
return StoreError.Wrap(err)
|
|
|
|
}
|
|
|
|
if recv == nil {
|
2018-11-08 20:27:07 +00:00
|
|
|
return StoreError.New("error receiving Piece metadata")
|
2018-08-17 18:40:15 +01:00
|
|
|
}
|
|
|
|
|
2018-10-17 12:40:11 +01:00
|
|
|
authorization := recv.GetAuthorization()
|
|
|
|
if err := s.verifier(authorization); err != nil {
|
2018-11-08 20:27:07 +00:00
|
|
|
return ServerError.Wrap(err)
|
2018-10-17 12:40:11 +01:00
|
|
|
}
|
|
|
|
|
2018-11-24 02:46:53 +00:00
|
|
|
pd := recv.GetPieceData()
|
2018-08-17 18:40:15 +01:00
|
|
|
if pd == nil {
|
|
|
|
return StoreError.New("PieceStore message is nil")
|
|
|
|
}
|
|
|
|
|
2018-12-17 15:23:02 +00:00
|
|
|
s.log.Debug("Storing", zap.String("Piece ID", fmt.Sprint(pd.GetId())))
|
2018-08-17 18:40:15 +01:00
|
|
|
|
|
|
|
if pd.GetId() == "" {
|
2018-11-08 20:27:07 +00:00
|
|
|
return StoreError.New("piece ID not specified")
|
2018-08-17 18:40:15 +01:00
|
|
|
}
|
|
|
|
|
2018-10-23 17:03:35 +01:00
|
|
|
id, err := getNamespacedPieceID([]byte(pd.GetId()), getNamespace(authorization))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
total, err := s.storeData(ctx, reqStream, id)
|
2018-08-17 18:40:15 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-10-23 17:03:35 +01:00
|
|
|
if err = s.DB.AddTTL(id, pd.GetExpirationUnixSec(), total); err != nil {
|
|
|
|
deleteErr := s.deleteByID(id)
|
2018-09-13 15:30:45 +01:00
|
|
|
return StoreError.New("failed to write piece meta data to database: %v", utils.CombineErrors(err, deleteErr))
|
2018-09-11 13:40:45 +01:00
|
|
|
}
|
|
|
|
|
2018-10-10 15:04:42 +01:00
|
|
|
if err = s.DB.AddBandwidthUsed(total); err != nil {
|
|
|
|
return StoreError.New("failed to write bandwidth info to database: %v", err)
|
|
|
|
}
|
2019-01-24 16:09:37 +00:00
|
|
|
s.log.Info("Successfully stored", zap.String("Piece ID", fmt.Sprint(pd.GetId())))
|
2018-08-17 18:40:15 +01:00
|
|
|
|
2018-08-27 18:28:16 +01:00
|
|
|
return reqStream.SendAndClose(&pb.PieceStoreSummary{Message: OK, TotalReceived: total})
|
2018-08-17 18:40:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) storeData(ctx context.Context, stream pb.PieceStoreRoutes_StoreServer, id string) (total int64, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
// Delete data if we error
|
|
|
|
defer func() {
|
|
|
|
if err != nil && err != io.EOF {
|
2018-08-27 19:35:27 +01:00
|
|
|
if deleteErr := s.deleteByID(id); deleteErr != nil {
|
2018-12-17 15:23:02 +00:00
|
|
|
s.log.Error("Failed on deleteByID in Store", zap.Error(deleteErr))
|
2018-08-17 18:40:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Initialize file for storing data
|
2019-01-11 11:26:39 +00:00
|
|
|
storeFile, err := s.storage.Writer(id)
|
2018-08-17 18:40:15 +01:00
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
2019-01-29 15:41:01 +00:00
|
|
|
defer func() {
|
|
|
|
err = errs.Combine(err, storeFile.Close())
|
|
|
|
}()
|
2018-08-17 18:40:15 +01:00
|
|
|
|
2018-12-12 19:14:51 +00:00
|
|
|
bwUsed, err := s.DB.GetTotalBandwidthBetween(getBeginningOfMonth(), time.Now())
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
spaceUsed, err := s.DB.SumTTLSizes()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
bwLeft := s.totalBwAllocated - bwUsed
|
|
|
|
spaceLeft := s.totalAllocated - spaceUsed
|
|
|
|
reader := NewStreamReader(s, stream, bwLeft, spaceLeft)
|
2018-08-17 18:40:15 +01:00
|
|
|
|
|
|
|
total, err = io.Copy(storeFile, reader)
|
|
|
|
|
|
|
|
if err != nil && err != io.EOF {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
2018-12-17 15:23:02 +00:00
|
|
|
err = s.DB.WriteBandwidthAllocToDB(reader.bandwidthAllocation)
|
|
|
|
|
|
|
|
return total, err
|
2018-08-17 18:40:15 +01:00
|
|
|
}
|