Skip to content

Commit

Permalink
Add common concurrent function to get list of objects (#354)
Browse files Browse the repository at this point in the history
We have concurrency when getting a collection that contains a set of
links to objects. But some object properties are a list themselves and
not a Collection object. This adds a common function to be used for
these types of properties to take advantage of the concurrent processing
to fetch these objects from the system.

Signed-off-by: Sean McGinnis <sean.mcginnis@gmail.com>
  • Loading branch information
stmcginnis authored Jul 8, 2024
1 parent 7fac89e commit a9703ef
Show file tree
Hide file tree
Showing 72 changed files with 285 additions and 3,996 deletions.
43 changes: 43 additions & 0 deletions common/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,46 @@ func GetObject[T any, PT interface {
entity.SetClient(c)
return entity, nil
}

// GetObject retrieves an API object from the service.
func GetObjects[T any, PT interface {
*T
SchemaObject
}](c Client, uris []string) ([]*T, error) {
var result []*T
if len(uris) == 0 {
return result, nil
}

type GetResult struct {
Item *T
Link string
Error error
}

ch := make(chan GetResult)
collectionError := NewCollectionError()
get := func(link string) {
entity, err := GetObject[T, PT](c, link)
ch <- GetResult{Item: entity, Link: link, Error: err}
}

go func() {
CollectCollection(get, uris)
close(ch)
}()

for r := range ch {
if r.Error != nil {
collectionError.Failures[r.Link] = r.Error
} else {
result = append(result, r.Item)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
}
59 changes: 2 additions & 57 deletions common/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@

package common

import (
"encoding/json"
)

// Message is This type shall define a Message as described in the
// Redfish specification.
type Message struct {
Expand Down Expand Up @@ -37,62 +33,11 @@ type Message struct {

// GetMessage will get a Message instance from the service.
func GetMessage(c Client, uri string) (*Message, error) {
resp, err := c.Get(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()

var message Message
err = json.NewDecoder(resp.Body).Decode(&message)
if err != nil {
return nil, err
}

message.SetClient(c)
return &message, nil
return GetObject[Message](c, uri)
}

// ListReferencedMessages gets the collection of Message from
// a provided reference.
func ListReferencedMessages(c Client, link string) ([]*Message, error) {
var result []*Message
if link == "" {
return result, nil
}

type GetResult struct {
Item *Message
Link string
Error error
}

ch := make(chan GetResult)
collectionError := NewCollectionError()
get := func(link string) {
message, err := GetMessage(c, link)
ch <- GetResult{Item: message, Link: link, Error: err}
}

go func() {
err := CollectList(get, c, link)
if err != nil {
collectionError.Failures[link] = err
}
close(ch)
}()

for r := range ch {
if r.Error != nil {
collectionError.Failures[r.Link] = r.Error
} else {
result = append(result, r.Item)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return GetCollectionObjects[Message](c, link)
}
36 changes: 2 additions & 34 deletions redfish/accelerationfunction.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,42 +114,10 @@ func ListReferencedAccelerationFunctions(c common.Client, link string) ([]*Accel

// Endpoints gets the endpoints connected to this accelerator.
func (accelerationfunction *AccelerationFunction) Endpoints() ([]*Endpoint, error) {
var result []*Endpoint

collectionError := common.NewCollectionError()
for _, uri := range accelerationfunction.endpoints {
endpoint, err := GetEndpoint(accelerationfunction.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, endpoint)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Endpoint](accelerationfunction.GetClient(), accelerationfunction.endpoints)
}

// PCIeFunctions gets the PCIe functions associated with this accelerator.
func (accelerationfunction *AccelerationFunction) PCIeFunctions() ([]*PCIeFunction, error) {
var result []*PCIeFunction

collectionError := common.NewCollectionError()
for _, uri := range accelerationfunction.pcieFunctions {
function, err := GetPCIeFunction(accelerationfunction.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, function)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[PCIeFunction](accelerationfunction.GetClient(), accelerationfunction.pcieFunctions)
}
36 changes: 2 additions & 34 deletions redfish/addresspool.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,44 +90,12 @@ func ListReferencedAddressPools(c common.Client, link string) ([]*AddressPool, e

// Endpoints gets the endpoints connected to this address pool.
func (addresspool *AddressPool) Endpoints() ([]*Endpoint, error) {
var result []*Endpoint

collectionError := common.NewCollectionError()
for _, uri := range addresspool.endpoints {
endpoint, err := GetEndpoint(addresspool.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, endpoint)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Endpoint](addresspool.GetClient(), addresspool.endpoints)
}

// Zones gets the zones associated with this address pool.
func (addresspool *AddressPool) Zones() ([]*Zone, error) {
var result []*Zone

collectionError := common.NewCollectionError()
for _, uri := range addresspool.zones {
endpoint, err := GetZone(addresspool.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, endpoint)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Zone](addresspool.GetClient(), addresspool.zones)
}

// BFDSingleHopOnly shall contain the BFD-related properties for an Ethernet fabric that uses Bidirectional
Expand Down
18 changes: 1 addition & 17 deletions redfish/aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,7 @@ func (aggregate *Aggregate) UnmarshalJSON(b []byte) error {

// Elements get the elements of this aggregate.
func (aggregate *Aggregate) Elements() ([]*Resource, error) {
var result []*Resource

collectionError := common.NewCollectionError()
for _, uri := range aggregate.elements {
endpoint, err := GetResource(aggregate.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, endpoint)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Resource](aggregate.GetClient(), aggregate.elements)
}

// AddElements adds one or more resources to the aggregate.
Expand Down
36 changes: 2 additions & 34 deletions redfish/battery.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,44 +215,12 @@ func (battery *Battery) BatteryMetrics() (*BatteryMetrics, error) {

// Memory returns a collection of Memory devices associated with this Battery.
func (battery *Battery) Memory() ([]*Memory, error) {
var result []*Memory

collectionError := common.NewCollectionError()
for _, uri := range battery.memory {
memory, err := GetMemory(battery.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, memory)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Memory](battery.GetClient(), battery.memory)
}

// StorageControllers returns a collection of StorageControllers associated with this Battery.
func (battery *Battery) StorageControllers() ([]*StorageController, error) {
var result []*StorageController

collectionError := common.NewCollectionError()
for _, uri := range battery.storageControllers {
sc, err := GetStorageController(battery.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, sc)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[StorageController](battery.GetClient(), battery.storageControllers)
}

// Calibrate performs a self-calibration, or learn cycle, of the battery.
Expand Down
72 changes: 4 additions & 68 deletions redfish/cable.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,86 +230,22 @@ func (cable *Cable) UnmarshalJSON(b []byte) error {

// DownstreamChassis gets the physical downstream containers connected to this cable.
func (cable *Cable) DownstreamChassis() ([]*Chassis, error) {
var result []*Chassis

collectionError := common.NewCollectionError()
for _, ethLink := range cable.downstreamChassis {
eth, err := GetChassis(cable.GetClient(), ethLink)
if err != nil {
collectionError.Failures[ethLink] = err
} else {
result = append(result, eth)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Chassis](cable.GetClient(), cable.downstreamChassis)
}

// DownstreamPorts gets the physical downstream connections connected to this cable.
func (cable *Cable) DownstreamPorts() ([]*Port, error) {
var result []*Port

collectionError := common.NewCollectionError()
for _, ethLink := range cable.downstreamPorts {
eth, err := GetPort(cable.GetClient(), ethLink)
if err != nil {
collectionError.Failures[ethLink] = err
} else {
result = append(result, eth)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Port](cable.GetClient(), cable.downstreamPorts)
}

// UpstreamChassis gets the physical upstream containers connected to this cable.
func (cable *Cable) UpstreamChassis() ([]*Chassis, error) {
var result []*Chassis

collectionError := common.NewCollectionError()
for _, ethLink := range cable.upstreamChassis {
eth, err := GetChassis(cable.GetClient(), ethLink)
if err != nil {
collectionError.Failures[ethLink] = err
} else {
result = append(result, eth)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Chassis](cable.GetClient(), cable.upstreamChassis)
}

// UpstreamPorts gets the physical upstream connections connected to this cable.
func (cable *Cable) UptreamPorts() ([]*Port, error) {
var result []*Port

collectionError := common.NewCollectionError()
for _, ethLink := range cable.upstreamPorts {
eth, err := GetPort(cable.GetClient(), ethLink)
if err != nil {
collectionError.Failures[ethLink] = err
} else {
result = append(result, eth)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
return common.GetObjects[Port](cable.GetClient(), cable.upstreamPorts)
}

// Update commits updates to this object's properties to the running system.
Expand Down
Loading

0 comments on commit a9703ef

Please sign in to comment.