feat: load model from oci image
This commit is contained in:
84
vendor/oras.land/oras-go/v2/internal/syncutil/limit.go
vendored
Normal file
84
vendor/oras.land/oras-go/v2/internal/syncutil/limit.go
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright The ORAS Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package syncutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
// LimitedRegion provides a way to bound concurrent access to a code block.
|
||||
type LimitedRegion struct {
|
||||
ctx context.Context
|
||||
limiter *semaphore.Weighted
|
||||
ended bool
|
||||
}
|
||||
|
||||
// LimitRegion creates a new LimitedRegion.
|
||||
func LimitRegion(ctx context.Context, limiter *semaphore.Weighted) *LimitedRegion {
|
||||
if limiter == nil {
|
||||
return nil
|
||||
}
|
||||
return &LimitedRegion{
|
||||
ctx: ctx,
|
||||
limiter: limiter,
|
||||
ended: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts the region with concurrency limit.
|
||||
func (lr *LimitedRegion) Start() error {
|
||||
if lr == nil || !lr.ended {
|
||||
return nil
|
||||
}
|
||||
if err := lr.limiter.Acquire(lr.ctx, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
lr.ended = false
|
||||
return nil
|
||||
}
|
||||
|
||||
// End ends the region with concurrency limit.
|
||||
func (lr *LimitedRegion) End() {
|
||||
if lr == nil || lr.ended {
|
||||
return
|
||||
}
|
||||
lr.limiter.Release(1)
|
||||
lr.ended = true
|
||||
}
|
||||
|
||||
// GoFunc represents a function that can be invoked by Go.
|
||||
type GoFunc[T any] func(ctx context.Context, region *LimitedRegion, t T) error
|
||||
|
||||
// Go concurrently invokes fn on items.
|
||||
func Go[T any](ctx context.Context, limiter *semaphore.Weighted, fn GoFunc[T], items ...T) error {
|
||||
eg, egCtx := errgroup.WithContext(ctx)
|
||||
for _, item := range items {
|
||||
region := LimitRegion(ctx, limiter)
|
||||
if err := region.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
eg.Go(func(t T) func() error {
|
||||
return func() error {
|
||||
defer region.End()
|
||||
return fn(egCtx, region, t)
|
||||
}
|
||||
}(item))
|
||||
}
|
||||
return eg.Wait()
|
||||
}
|
67
vendor/oras.land/oras-go/v2/internal/syncutil/limitgroup.go
vendored
Normal file
67
vendor/oras.land/oras-go/v2/internal/syncutil/limitgroup.go
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright The ORAS Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package syncutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// A LimitedGroup is a collection of goroutines working on subtasks that are part of
|
||||
// the same overall task.
|
||||
type LimitedGroup struct {
|
||||
grp *errgroup.Group
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// LimitGroup returns a new LimitedGroup and an associated Context derived from ctx.
|
||||
//
|
||||
// The number of active goroutines in this group is limited to the given limit.
|
||||
// A negative value indicates no limit.
|
||||
//
|
||||
// The derived Context is canceled the first time a function passed to Go
|
||||
// returns a non-nil error or the first time Wait returns, whichever occurs
|
||||
// first.
|
||||
func LimitGroup(ctx context.Context, limit int) (*LimitedGroup, context.Context) {
|
||||
grp, ctx := errgroup.WithContext(ctx)
|
||||
grp.SetLimit(limit)
|
||||
return &LimitedGroup{grp: grp, ctx: ctx}, ctx
|
||||
}
|
||||
|
||||
// Go calls the given function in a new goroutine.
|
||||
// It blocks until the new goroutine can be added without the number of
|
||||
// active goroutines in the group exceeding the configured limit.
|
||||
//
|
||||
// The first call to return a non-nil error cancels the group's context.
|
||||
// After which, any subsequent calls to Go will not execute their given function.
|
||||
// The error will be returned by Wait.
|
||||
func (g *LimitedGroup) Go(f func() error) {
|
||||
g.grp.Go(func() error {
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
return g.ctx.Err()
|
||||
default:
|
||||
return f()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Wait blocks until all function calls from the Go method have returned, then
|
||||
// returns the first non-nil error (if any) from them.
|
||||
func (g *LimitedGroup) Wait() error {
|
||||
return g.grp.Wait()
|
||||
}
|
140
vendor/oras.land/oras-go/v2/internal/syncutil/merge.go
vendored
Normal file
140
vendor/oras.land/oras-go/v2/internal/syncutil/merge.go
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright The ORAS Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package syncutil
|
||||
|
||||
import "sync"
|
||||
|
||||
// mergeStatus represents the merge status of an item.
|
||||
type mergeStatus struct {
|
||||
// main indicates if items are being merged by the current go-routine.
|
||||
main bool
|
||||
// err represents the error of the merge operation.
|
||||
err error
|
||||
}
|
||||
|
||||
// Merge represents merge operations on items.
|
||||
// The state transfer is shown as below:
|
||||
//
|
||||
// +----------+
|
||||
// | Start +--------+-------------+
|
||||
// +----+-----+ | |
|
||||
// | | |
|
||||
// v v v
|
||||
// +----+-----+ +----+----+ +----+----+
|
||||
// +-------+ Prepare +<--+ Pending +-->+ Waiting |
|
||||
// | +----+-----+ +---------+ +----+----+
|
||||
// | | |
|
||||
// | v |
|
||||
// | + ---+---- + |
|
||||
// On Error | Resolve | |
|
||||
// | + ---+---- + |
|
||||
// | | |
|
||||
// | v |
|
||||
// | +----+-----+ |
|
||||
// +------>+ Complete +<---------------------+
|
||||
// +----+-----+
|
||||
// |
|
||||
// v
|
||||
// +----+-----+
|
||||
// | End |
|
||||
// +----------+
|
||||
type Merge[T any] struct {
|
||||
lock sync.Mutex
|
||||
committed bool
|
||||
items []T
|
||||
status chan mergeStatus
|
||||
pending []T
|
||||
pendingStatus chan mergeStatus
|
||||
}
|
||||
|
||||
// Do merges concurrent operations of items into a single call of prepare and
|
||||
// resolve.
|
||||
// If Do is called multiple times concurrently, only one of the calls will be
|
||||
// selected to invoke prepare and resolve.
|
||||
func (m *Merge[T]) Do(item T, prepare func() error, resolve func(items []T) error) error {
|
||||
status := <-m.assign(item)
|
||||
if status.main {
|
||||
err := prepare()
|
||||
items := m.commit()
|
||||
if err == nil {
|
||||
err = resolve(items)
|
||||
}
|
||||
m.complete(err)
|
||||
return err
|
||||
}
|
||||
return status.err
|
||||
}
|
||||
|
||||
// assign adds a new item into the item list.
|
||||
func (m *Merge[T]) assign(item T) <-chan mergeStatus {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if m.committed {
|
||||
if m.pendingStatus == nil {
|
||||
m.pendingStatus = make(chan mergeStatus, 1)
|
||||
}
|
||||
m.pending = append(m.pending, item)
|
||||
return m.pendingStatus
|
||||
}
|
||||
|
||||
if m.status == nil {
|
||||
m.status = make(chan mergeStatus, 1)
|
||||
m.status <- mergeStatus{main: true}
|
||||
}
|
||||
m.items = append(m.items, item)
|
||||
return m.status
|
||||
}
|
||||
|
||||
// commit closes the assignment window, and the assigned items will be ready
|
||||
// for resolve.
|
||||
func (m *Merge[T]) commit() []T {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
m.committed = true
|
||||
return m.items
|
||||
}
|
||||
|
||||
// complete completes the previous merge, and moves the pending items to the
|
||||
// stage for the next merge.
|
||||
func (m *Merge[T]) complete(err error) {
|
||||
// notify results
|
||||
if err == nil {
|
||||
close(m.status)
|
||||
} else {
|
||||
remaining := len(m.items) - 1
|
||||
status := m.status
|
||||
for remaining > 0 {
|
||||
status <- mergeStatus{err: err}
|
||||
remaining--
|
||||
}
|
||||
}
|
||||
|
||||
// move pending items to the stage
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
m.committed = false
|
||||
m.items = m.pending
|
||||
m.status = m.pendingStatus
|
||||
m.pending = nil
|
||||
m.pendingStatus = nil
|
||||
|
||||
if m.status != nil {
|
||||
m.status <- mergeStatus{main: true}
|
||||
}
|
||||
}
|
70
vendor/oras.land/oras-go/v2/internal/syncutil/once.go
vendored
Normal file
70
vendor/oras.land/oras-go/v2/internal/syncutil/once.go
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright The ORAS Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package syncutil
|
||||
|
||||
import "context"
|
||||
|
||||
// Once is an object that will perform exactly one action.
|
||||
// Unlike sync.Once, this Once allowes the action to have return values.
|
||||
type Once struct {
|
||||
result interface{}
|
||||
err error
|
||||
status chan bool
|
||||
}
|
||||
|
||||
// NewOnce creates a new Once instance.
|
||||
func NewOnce() *Once {
|
||||
status := make(chan bool, 1)
|
||||
status <- true
|
||||
return &Once{
|
||||
status: status,
|
||||
}
|
||||
}
|
||||
|
||||
// Do calls the function f if and only if Do is being called first time or all
|
||||
// previous function calls are cancelled, deadline exceeded, or panicking.
|
||||
// When `once.Do(ctx, f)` is called multiple times, the return value of the
|
||||
// first call of the function f is stored, and is directly returned for other
|
||||
// calls.
|
||||
// Besides the return value of the function f, including the error, Do returns
|
||||
// true if the function f passed is called first and is not cancelled, deadline
|
||||
// exceeded, or panicking. Otherwise, returns false.
|
||||
func (o *Once) Do(ctx context.Context, f func() (interface{}, error)) (bool, interface{}, error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
o.status <- true
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case inProgress := <-o.status:
|
||||
if !inProgress {
|
||||
return false, o.result, o.err
|
||||
}
|
||||
result, err := f()
|
||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||
o.status <- true
|
||||
return false, nil, err
|
||||
}
|
||||
o.result, o.err = result, err
|
||||
close(o.status)
|
||||
return true, result, err
|
||||
case <-ctx.Done():
|
||||
return false, nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
64
vendor/oras.land/oras-go/v2/internal/syncutil/pool.go
vendored
Normal file
64
vendor/oras.land/oras-go/v2/internal/syncutil/pool.go
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright The ORAS Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package syncutil
|
||||
|
||||
import "sync"
|
||||
|
||||
// poolItem represents an item in Pool.
|
||||
type poolItem[T any] struct {
|
||||
value T
|
||||
refCount int
|
||||
}
|
||||
|
||||
// Pool is a scalable pool with items identified by keys.
|
||||
type Pool[T any] struct {
|
||||
// New optionally specifies a function to generate a value when Get would
|
||||
// otherwise return nil.
|
||||
// It may not be changed concurrently with calls to Get.
|
||||
New func() T
|
||||
|
||||
lock sync.Mutex
|
||||
items map[any]*poolItem[T]
|
||||
}
|
||||
|
||||
// Get gets the value identified by key.
|
||||
// The caller should invoke the returned function after using the returned item.
|
||||
func (p *Pool[T]) Get(key any) (*T, func()) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
item, ok := p.items[key]
|
||||
if !ok {
|
||||
if p.items == nil {
|
||||
p.items = make(map[any]*poolItem[T])
|
||||
}
|
||||
item = &poolItem[T]{}
|
||||
if p.New != nil {
|
||||
item.value = p.New()
|
||||
}
|
||||
p.items[key] = item
|
||||
}
|
||||
item.refCount++
|
||||
|
||||
return &item.value, func() {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
item.refCount--
|
||||
if item.refCount <= 0 {
|
||||
delete(p.items, key)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user