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 { Partial bool `json:"partial" default:"false"` // Partial is a flag that indicates if the graph is partial 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 NewGraph() *Graph { return &Graph{ Partial: false, Zoom: 1, Items: map[string]GraphItem{}, Links: []GraphLink{}, } } func (g *Graph) Clear(id string) { realItems := map[string]GraphItem{} for k, it := range g.Items { if k == id { realinks := []GraphLink{} for _, link := range g.Links { if link.Source.ID != id && link.Destination.ID != id { realinks = append(realinks, link) } } g.Links = realinks g.Partial = true } else { realItems[k] = it } } g.Items = realItems } func (wf *Graph) IsProcessing(item GraphItem) bool { return item.Processing != nil } func (wf *Graph) IsNativeTool(item GraphItem) bool { return item.NativeTool != 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, instance int, bookingMode int, request *tools.APIRequest) (float64, float64, error) { 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, err := processing.ConvertToPricedResource(tools.PROCESSING_RESOURCE, &instance, &bookingMode, request) if err != nil { return 0, 0, err } 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, nil } return nearestStart, longestDuration, nil } /* * GetAverageTimeBeforeStart is a function that returns the average time before the start of a processing */ func (g *Graph) GetAverageTimeProcessingBeforeStart(average float64, processingID string, instance int, bookingMode int, request *tools.APIRequest) (float64, error) { 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, err := r.ConvertToPricedResource(dt, &instance, &bookingMode, request) if err != nil { return 0, err } 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, nil } add, err := g.GetAverageTimeProcessingBeforeStart(current, source, instance, bookingMode, request) if err != nil { return 0, err } current += add // 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, nil } func (g *Graph) GetResource(id string) (tools.DataType, resources.ResourceInterface) { if item, ok := g.Items[id]; ok { if item.Data != nil { return tools.NATIVE_TOOL, item.NativeTool } else 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 }