/* * Copyright 2012 LinkedIn, Inc * * 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 com.linkedin.parseq.trace; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * @author Jaroslaw Odzga (jodzga@linkedin.com) */ public class TraceBuilder { static final long UNKNOWN_PLAN_ID = -1L; static final String UNKNOWN_PLAN_CLASS = "unknown"; private static final int INITIAL_RELATIONSHIP_ARRAY_SIZE = 128; private static final int INITIAL_BUILDER_ARRAY_SIZE = 128; private final int _maxTraceBuildersPerTrace; private final String _planClass; private final Long _planId; private final ArrayList<TraceRelationship> _relationships; private final ArrayList<ShallowTraceBuilder> _traceBuilders; // TODO: this constructor should be removed. // Need to fix in the next major version release. public TraceBuilder(int maxRelationshipsCount) { this(maxRelationshipsCount, UNKNOWN_PLAN_CLASS, UNKNOWN_PLAN_ID); } public TraceBuilder(int maxRelationshipsCount, String planClass, Long planId) { _relationships = new ArrayList<>(INITIAL_RELATIONSHIP_ARRAY_SIZE); _traceBuilders = new ArrayList<>(INITIAL_BUILDER_ARRAY_SIZE); _maxTraceBuildersPerTrace = maxRelationshipsCount; _planClass = planClass; _planId = planId; } public synchronized void addShallowTrace(final ShallowTraceBuilder shallowTrace) { if (_traceBuilders.size() < _maxTraceBuildersPerTrace) { _traceBuilders.add(shallowTrace); } } public synchronized void addRelationship(final Relationship relationship, final ShallowTraceBuilder from, final ShallowTraceBuilder to) { if (_relationships.size() < _maxTraceBuildersPerTrace) { TraceRelationship rel = new TraceRelationship(from, to, relationship); _relationships.add(rel); } } public synchronized Trace build() { final Map<Long, ShallowTrace> traceMap = new HashMap<>(); final Set<TraceRelationship> relationships = new HashSet<>(); for (ShallowTraceBuilder builder : _traceBuilders) { traceMap.put(builder.getId(), builder.build()); } for (TraceRelationship rel : _relationships) { traceMap.computeIfAbsent(rel._from.getId(), key -> rel._from.build()); traceMap.computeIfAbsent(rel._to.getId(), key -> rel._to.build()); switch (rel.getRelationhsip()) { case SUCCESSOR_OF: relationships.remove(new TraceRelationship(rel._from, rel._to, Relationship.POSSIBLE_SUCCESSOR_OF)); relationships.add(rel); break; case POSSIBLE_SUCCESSOR_OF: if (!relationships.contains(new TraceRelationship(rel._from, rel._to, Relationship.SUCCESSOR_OF))) { relationships.add(rel); } break; case CHILD_OF: relationships.remove(new TraceRelationship(rel._to, rel._from, Relationship.POTENTIAL_PARENT_OF)); relationships.add(new TraceRelationship(rel._to, rel._from, Relationship.PARENT_OF)); break; case POTENTIAL_CHILD_OF: if (!relationships.contains(new TraceRelationship(rel._to, rel._from, Relationship.PARENT_OF))) { relationships.add(new TraceRelationship(rel._to, rel._from, Relationship.POTENTIAL_PARENT_OF)); } break; case POTENTIAL_PARENT_OF: if (!relationships.contains(new TraceRelationship(rel._from, rel._to, Relationship.PARENT_OF))) { relationships.add(rel); } break; case PARENT_OF: relationships.remove(new TraceRelationship(rel._from, rel._to, Relationship.POTENTIAL_PARENT_OF)); relationships.add(rel); break; default: throw new IllegalStateException("Unknown relationship type: " + rel); } } return new Trace(traceMap, relationships, _planClass, _planId); } }