-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rename forestrie mmrblobs to massifs (#178)
* Rename forestrie mmrblobs to massifs re: AB#9461 --------- Co-authored-by: jgough <[email protected]>
- Loading branch information
1 parent
0ea8fde
commit fd22295
Showing
41 changed files
with
5,466 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package massifs | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
|
||
azStorageBlob "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" | ||
"github.com/datatrails/go-datatrails-common/azblob" | ||
) | ||
|
||
var ( | ||
ErrBlobNotFound = errors.New("the blob was not found") | ||
) | ||
|
||
// LastPrefixedBlob returns the details of last blob found under the prefix path | ||
// And the total number of blobs under the path. | ||
func LastPrefixedBlob( | ||
ctx context.Context, store logBlobReader, blobPrefixPath string, | ||
opts ...azblob.Option, | ||
) (LogBlobContext, uint64, error) { | ||
|
||
bc := LogBlobContext{} | ||
|
||
var foundCount uint64 | ||
|
||
opts = append([]azblob.Option{azblob.WithListPrefix(blobPrefixPath)}, opts...) | ||
|
||
var marker azblob.ListMarker | ||
for { | ||
r, err := store.List(ctx, append(opts, azblob.WithListMarker(marker))...) | ||
if err != nil { | ||
return bc, foundCount, err | ||
} | ||
if len(r.Items) == 0 { | ||
return bc, foundCount, nil | ||
} | ||
|
||
foundCount += uint64(len(r.Items)) | ||
|
||
// we want the _last_ listed, so we just keep over-writing | ||
i := r.Items[len(r.Items)-1] | ||
bc.ETag = *i.Properties.Etag | ||
bc.LastModified = *i.Properties.LastModified | ||
if i.Properties.ContentLength != nil { | ||
bc.ContentLength = *i.Properties.ContentLength | ||
} | ||
bc.BlobPath = *i.Name | ||
marker = r.Marker | ||
if marker == nil || *marker == "" { | ||
bc.Tags = listResponseTags(i.BlobTags) | ||
break | ||
} | ||
} | ||
|
||
return bc, foundCount, nil | ||
} | ||
|
||
// FirstPrefixedBlob returns the first blob found under the prefix path | ||
func FirstPrefixedBlob( | ||
ctx context.Context, store logBlobReader, blobPrefixPath string, | ||
opts ...azblob.Option, | ||
) (LogBlobContext, error) { | ||
|
||
bc := LogBlobContext{} | ||
|
||
opts = append([]azblob.Option{ | ||
azblob.WithListPrefix(blobPrefixPath), | ||
azblob.WithListMaxResults(1), | ||
}, opts...) | ||
|
||
r, err := store.List(ctx, opts...) | ||
if err != nil { | ||
return bc, err | ||
} | ||
if len(r.Items) == 0 { | ||
return bc, ErrBlobNotFound | ||
} | ||
|
||
i := r.Items[0] | ||
bc.ETag = *i.Properties.Etag | ||
bc.LastModified = *i.Properties.LastModified | ||
if i.Properties.ContentLength != nil { | ||
bc.ContentLength = *i.Properties.ContentLength | ||
} | ||
bc.BlobPath = *i.Name | ||
bc.Tags = listResponseTags(r.Items[0].BlobTags) | ||
|
||
return bc, nil | ||
} | ||
|
||
// PrefixedBlobLastN returns contexts for the last n blobs under the provided prefix. | ||
// | ||
// The number of items in the returned tail is always min(massifCount, n) | ||
// Un filled items are zero valued. | ||
func PrefixedBlobLastN( | ||
ctx context.Context, | ||
store logBlobReader, | ||
blobPrefixPath string, | ||
n int, | ||
opts ...azblob.Option, | ||
) ([]LogBlobContext, uint64, error) { | ||
|
||
opts = append([]azblob.Option{azblob.WithListPrefix(blobPrefixPath)}, opts...) | ||
|
||
tail := make([]LogBlobContext, n) | ||
|
||
var foundCount uint64 | ||
|
||
var marker azblob.ListMarker | ||
for { | ||
r, err := store.List(ctx, append(opts, azblob.WithListMarker(marker))...) | ||
if err != nil { | ||
return tail, foundCount, err | ||
} | ||
if len(r.Items) == 0 { | ||
return tail, foundCount, nil | ||
} | ||
|
||
foundCount += uint64(len(r.Items)) | ||
|
||
// The stale items are those from the previous round that can be | ||
// replaced by the current. Typically, len(r.Items) will be greater than | ||
// n and so it will be n. Note that stale is > 0 here due to the len 0 | ||
// check above. | ||
stale := min(len(r.Items), n) | ||
|
||
// copy the items *after* the stale items to the front. | ||
if stale != n { | ||
copy(tail, tail[n-stale-1:]) | ||
} | ||
|
||
for i := 0; i < stale; i++ { | ||
|
||
// stale is also the count of items we are taking from items. | ||
|
||
it := r.Items[len(r.Items)-stale+i] | ||
tail[n-stale+i].ETag = *it.Properties.Etag | ||
tail[n-stale+i].LastModified = *it.Properties.LastModified | ||
if it.Properties.ContentLength != nil { | ||
tail[n-stale+i].ContentLength = *it.Properties.ContentLength | ||
} | ||
tail[n-stale+i].BlobPath = *it.Name | ||
tail[n-stale+i].Tags = listResponseTags(it.BlobTags) | ||
} | ||
|
||
marker = r.Marker | ||
if marker == nil || *marker == "" { | ||
break | ||
} | ||
} | ||
|
||
// Note massifIndex will be zero, the id of the first massif blob | ||
return tail, foundCount, nil | ||
} | ||
|
||
func listResponseTags(blobTags *azStorageBlob.BlobTags) map[string]string { | ||
if blobTags == nil { | ||
return nil | ||
} | ||
tags := map[string]string{} | ||
for _, tag := range blobTags.BlobTagSet { | ||
if tag.Key == nil || tag.Value == nil { | ||
continue | ||
} | ||
tags[*tag.Key] = *tag.Value | ||
} | ||
return tags | ||
} |
Oops, something went wrong.