package graph import ( "time" "cloud.o-forge.io/core/oc-lib/models/resources" "cloud.o-forge.io/core/oc-lib/tools" ) // Graph is a struct that represents a graph type Graph struct { Zoom float64 `bson:"zoom" json:"zoom" default:"1"` // Zoom is the graphical zoom of the graph Items map[string]GraphItem `bson:"items" json:"items" default:"{}" validate:"required"` // Items is the list of elements in the graph Links []GraphLink `bson:"links" json:"links" default:"{}" validate:"required"` // Links is the list of links between elements in the graph } func (wf *Graph) IsProcessing(item GraphItem) bool { return item.Processing != nil } func (wf *Graph) IsCompute(item GraphItem) bool { return item.Compute != nil } func (wf *Graph) IsData(item GraphItem) bool { return item.Data != nil } func (wf *Graph) IsStorage(item GraphItem) bool { return item.Storage != nil } func (wf *Graph) IsWorkflow(item GraphItem) bool { return item.Workflow != nil } func (g *Graph) GetAverageTimeRelatedToProcessingActivity(start time.Time, processings []*resources.ProcessingResource, resource resources.ResourceInterface, f func(GraphItem) resources.ResourceInterface, request *tools.APIRequest) (float64, float64) { nearestStart := float64(10000000000) oneIsInfinite := false longestDuration := float64(0) for _, link := range g.Links { for _, processing := range processings { var source string // source is the source of the link if link.Destination.ID == processing.GetID() && f(g.Items[link.Source.ID]) != nil && f(g.Items[link.Source.ID]).GetID() == resource.GetID() { // if the destination is the processing and the source is not a compute source = link.Source.ID } else if link.Source.ID == processing.GetID() && f(g.Items[link.Source.ID]) != nil && f(g.Items[link.Source.ID]).GetID() == resource.GetID() { // if the source is the processing and the destination is not a compute source = link.Destination.ID } priced := processing.ConvertToPricedResource(tools.PROCESSING_RESOURCE, request) if source != "" { if priced.GetLocationStart() != nil { near := float64(priced.GetLocationStart().Sub(start).Seconds()) if near < nearestStart { nearestStart = near } } if priced.GetLocationEnd() != nil { duration := float64(priced.GetLocationEnd().Sub(*priced.GetLocationStart()).Seconds()) if longestDuration < duration { longestDuration = duration } } else { oneIsInfinite = true } } } } if oneIsInfinite { return nearestStart, -1 } return nearestStart, longestDuration } /* * GetAverageTimeBeforeStart is a function that returns the average time before the start of a processing */ func (g *Graph) GetAverageTimeProcessingBeforeStart(average float64, processingID string, request *tools.APIRequest) float64 { currents := []float64{} // list of current time for _, link := range g.Links { // for each link var source string // source is the source of the link if link.Destination.ID == processingID && g.Items[link.Source.ID].Processing == nil { // if the destination is the processing and the source is not a compute source = link.Source.ID } else if link.Source.ID == processingID && g.Items[link.Source.ID].Processing == nil { // if the source is the processing and the destination is not a compute source = link.Destination.ID } if source == "" { // if source is empty, continue continue } dt, r := g.GetResource(source) // get the resource of the source if r == nil { // if item is nil, continue continue } priced := r.ConvertToPricedResource(dt, request) current := priced.GetExplicitDurationInS() // get the explicit duration of the item if current < 0 { // if current is negative, its means that duration of a before could be infinite continue return current } current += g.GetAverageTimeProcessingBeforeStart(current, source, request) // get the average time before start of the source currents = append(currents, current) // append the current to the currents } var max float64 // get the max time to wait dependancies to finish for _, current := range currents { if current > max { max = current } } return max } func (g *Graph) GetResource(id string) (tools.DataType, resources.ResourceInterface) { if item, ok := g.Items[id]; ok { if item.Data != nil { return tools.DATA_RESOURCE, item.Data } else if item.Compute != nil { return tools.COMPUTE_RESOURCE, item.Compute } else if item.Workflow != nil { return tools.WORKFLOW_RESOURCE, item.Workflow } else if item.Processing != nil { return tools.PROCESSING_RESOURCE, item.Processing } else if item.Storage != nil { return tools.STORAGE_RESOURCE, item.Storage } } return tools.INVALID, nil }