You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
5.9 KiB

  1. package s3api
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
  6. "github.com/aws/aws-sdk-go/service/s3"
  7. "github.com/seaweedfs/seaweedfs/weed/glog"
  8. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  9. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  10. //"github.com/seaweedfs/seaweedfs/weed/s3api"
  11. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  12. "github.com/seaweedfs/seaweedfs/weed/util"
  13. "math"
  14. "sync"
  15. )
  16. var loadBucketMetadataFromFiler = func(r *BucketRegistry, bucketName string) (*BucketMetaData, error) {
  17. entry, err := filer_pb.GetEntry(r.s3a, util.NewFullPath(r.s3a.option.BucketsPath, bucketName))
  18. if err != nil {
  19. return nil, err
  20. }
  21. return buildBucketMetadata(entry), nil
  22. }
  23. type BucketMetaData struct {
  24. _ struct{} `type:"structure"`
  25. Name string
  26. //By default, when another AWS account uploads an object to S3 bucket,
  27. //that account (the object writer) owns the object, has access to it, and
  28. //can grant other users access to it through ACLs. You can use Object Ownership
  29. //to change this default behavior so that ACLs are disabled and you, as the
  30. //bucket owner, automatically own every object in your bucket.
  31. ObjectOwnership string
  32. // Container for the bucket owner's display name and ID.
  33. Owner *s3.Owner `type:"structure"`
  34. // A list of grants for access controls.
  35. Acl []*s3.Grant `locationName:"AccessControlList" locationNameList:"Grant" type:"list"`
  36. }
  37. type BucketRegistry struct {
  38. metadataCache map[string]*BucketMetaData
  39. metadataCacheLock sync.RWMutex
  40. notFound map[string]struct{}
  41. notFoundLock sync.RWMutex
  42. s3a *S3ApiServer
  43. }
  44. func NewBucketRegistry(s3a *S3ApiServer) *BucketRegistry {
  45. br := &BucketRegistry{
  46. metadataCache: make(map[string]*BucketMetaData),
  47. notFound: make(map[string]struct{}),
  48. s3a: s3a,
  49. }
  50. err := br.init()
  51. if err != nil {
  52. glog.Fatal("init bucket registry failed", err)
  53. return nil
  54. }
  55. return br
  56. }
  57. func (r *BucketRegistry) init() error {
  58. err := filer_pb.List(r.s3a, r.s3a.option.BucketsPath, "", func(entry *filer_pb.Entry, isLast bool) error {
  59. r.LoadBucketMetadata(entry)
  60. return nil
  61. }, "", false, math.MaxUint32)
  62. return err
  63. }
  64. func (r *BucketRegistry) LoadBucketMetadata(entry *filer_pb.Entry) {
  65. bucketMetadata := buildBucketMetadata(entry)
  66. r.metadataCacheLock.Lock()
  67. defer r.metadataCacheLock.Unlock()
  68. r.metadataCache[entry.Name] = bucketMetadata
  69. }
  70. func buildBucketMetadata(entry *filer_pb.Entry) *BucketMetaData {
  71. entryJson, _ := json.Marshal(entry)
  72. glog.V(3).Infof("build bucket metadata,entry=%s", entryJson)
  73. bucketMetadata := &BucketMetaData{
  74. Name: entry.Name,
  75. //Default ownership: OwnershipBucketOwnerEnforced, which means Acl is disabled
  76. ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
  77. // Default owner: `AccountAdmin`
  78. Owner: &s3.Owner{
  79. ID: &AccountAdmin.Id,
  80. DisplayName: &AccountAdmin.Name,
  81. },
  82. }
  83. if entry.Extended != nil {
  84. //ownership control
  85. ownership, ok := entry.Extended[s3_constants.ExtOwnershipKey]
  86. if ok {
  87. ownership := string(ownership)
  88. valid := s3_constants.ValidateOwnership(ownership)
  89. if valid {
  90. bucketMetadata.ObjectOwnership = ownership
  91. } else {
  92. glog.Warningf("Invalid ownership: %s, bucket: %s", ownership, bucketMetadata.Name)
  93. }
  94. }
  95. //access control policy
  96. acpBytes, ok := entry.Extended[s3_constants.ExtAcpKey]
  97. if ok {
  98. var acp s3.AccessControlPolicy
  99. err := jsonutil.UnmarshalJSON(&acp, bytes.NewReader(acpBytes))
  100. if err == nil {
  101. //validate owner
  102. if acp.Owner != nil && acp.Owner.ID != nil {
  103. bucketMetadata.Owner = acp.Owner
  104. } else {
  105. glog.Warningf("bucket ownerId is empty! bucket: %s", bucketMetadata.Name)
  106. }
  107. //acl
  108. bucketMetadata.Acl = acp.Grants
  109. } else {
  110. glog.Warningf("Unmarshal ACP: %s(%v), bucket: %s", string(acpBytes), err, bucketMetadata.Name)
  111. }
  112. }
  113. }
  114. return bucketMetadata
  115. }
  116. func (r *BucketRegistry) RemoveBucketMetadata(entry *filer_pb.Entry) {
  117. r.removeMetadataCache(entry.Name)
  118. r.unMarkNotFound(entry.Name)
  119. }
  120. func (r *BucketRegistry) GetBucketMetadata(bucketName string) (*BucketMetaData, s3err.ErrorCode) {
  121. r.metadataCacheLock.RLock()
  122. bucketMetadata, ok := r.metadataCache[bucketName]
  123. r.metadataCacheLock.RUnlock()
  124. if ok {
  125. return bucketMetadata, s3err.ErrNone
  126. }
  127. r.notFoundLock.RLock()
  128. _, ok = r.notFound[bucketName]
  129. r.notFoundLock.RUnlock()
  130. if ok {
  131. return nil, s3err.ErrNoSuchBucket
  132. }
  133. bucketMetadata, errCode := r.LoadBucketMetadataFromFiler(bucketName)
  134. if errCode != s3err.ErrNone {
  135. return nil, errCode
  136. }
  137. r.setMetadataCache(bucketMetadata)
  138. r.unMarkNotFound(bucketName)
  139. return bucketMetadata, s3err.ErrNone
  140. }
  141. func (r *BucketRegistry) LoadBucketMetadataFromFiler(bucketName string) (*BucketMetaData, s3err.ErrorCode) {
  142. r.notFoundLock.Lock()
  143. defer r.notFoundLock.Unlock()
  144. //check if already exists
  145. r.metadataCacheLock.RLock()
  146. bucketMetaData, ok := r.metadataCache[bucketName]
  147. r.metadataCacheLock.RUnlock()
  148. if ok {
  149. return bucketMetaData, s3err.ErrNone
  150. }
  151. //if not exists, load from filer
  152. bucketMetadata, err := loadBucketMetadataFromFiler(r, bucketName)
  153. if err != nil {
  154. if err == filer_pb.ErrNotFound {
  155. // The bucket doesn't actually exist and should no longer loaded from the filer
  156. r.notFound[bucketName] = struct{}{}
  157. return nil, s3err.ErrNoSuchBucket
  158. }
  159. return nil, s3err.ErrInternalError
  160. }
  161. return bucketMetadata, s3err.ErrNone
  162. }
  163. func (r *BucketRegistry) setMetadataCache(metadata *BucketMetaData) {
  164. r.metadataCacheLock.Lock()
  165. defer r.metadataCacheLock.Unlock()
  166. r.metadataCache[metadata.Name] = metadata
  167. }
  168. func (r *BucketRegistry) removeMetadataCache(bucket string) {
  169. r.metadataCacheLock.Lock()
  170. defer r.metadataCacheLock.Unlock()
  171. delete(r.metadataCache, bucket)
  172. }
  173. func (r *BucketRegistry) markNotFound(bucket string) {
  174. r.notFoundLock.Lock()
  175. defer r.notFoundLock.Unlock()
  176. r.notFound[bucket] = struct{}{}
  177. }
  178. func (r *BucketRegistry) unMarkNotFound(bucket string) {
  179. r.notFoundLock.Lock()
  180. defer r.notFoundLock.Unlock()
  181. delete(r.notFound, bucket)
  182. }