94 import org.openjdk.jmc.flightrecorder.rules.tree.TimeRangeFilter;
95 import org.openjdk.jmc.flightrecorder.rules.tree.TimeRangeThreadFilter;
96 import org.openjdk.jmc.flightrecorder.stacktrace.FrameSeparator;
97 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceFormatToolkit;
98 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceFrame;
99 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceModel;
100 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceModel.Branch;
101
102 /**
103 * A collection of useful methods when evaluating rules.
104 */
105 // FIXME: Should probably be broken apart into methods related to rules (kept here) and methods related to JDK events (which should be moved to wherever JfrAttributes etc. are)
106 public class RulesToolkit {
107
108 // FIXME: Quick and dirty inlining of constants constants defined in SettingsTransformer. These should be handled in some other way.
109 private static final String REC_SETTING_NAME_ENABLED = "enabled"; //$NON-NLS-1$
110 private static final String REC_SETTING_NAME_THRESHOLD = "threshold"; //$NON-NLS-1$
111 public static final String REC_SETTING_NAME_PERIOD = "period"; //$NON-NLS-1$
112 public static final String REC_SETTING_PERIOD_EVERY_CHUNK = "everyChunk"; //$NON-NLS-1$
113
114 private static final IAccessorFactory<String> TYPE_NAME_ACCESSOR_FACTORY = new IAccessorFactory<String>() {
115
116 @Override
117 public <T> IMemberAccessor<String, T> getAccessor(IType<T> type) {
118 final IMemberAccessor<LabeledIdentifier, T> ta = JdkAttributes.REC_SETTING_FOR.getAccessor(type);
119 return new IMemberAccessor<String, T>() {
120
121 @Override
122 public String getMember(T inObject) {
123 LabeledIdentifier eventType = ta.getMember(inObject);
124 return eventType == null ? null : eventType.getName();
125 }
126
127 };
128 }
129 };
130 private final static LinearUnit MEBIBYTES = UnitLookup.MEMORY.getUnit(BinaryPrefix.MEBI);
131
132 /**
133 * Matches strings containing an identifiable version number as presented in a JVM info event.
134 * The minimal matching form is "JRE (" followed by 1 to 4 numbers on the format a.b.c_d or
135 * a.b.c.d. Examples are 1.7.0, 1.8.0_70, 9, 9.1, and 9.1.2.3. Match group 1 will contain the
136 * matched version string.
137 */
138 private static final Pattern VERSION_PATTERN = Pattern
139 .compile(".*?JRE \\((\\d+(?:\\.\\d+(?:\\.\\d+(?:[\\._]\\d+)?)?)?(?:-ea)?).*"); //$NON-NLS-1$
140
141 /**
142 * Knowledge about the state of affairs of an event type in an IItemCollection.
143 */
144 public enum EventAvailability {
145 /**
146 * The type has events available in the collection.
405 * the {@link EventAvailability} to check
406 * @return false if any {@link EventAvailability} is disabled or unavailable. Otherwise true.
407 */
408 public static boolean isEventsEnabled(EventAvailability ... eventAvailabilities) {
409 for (EventAvailability availability : eventAvailabilities) {
410 if (availability == EventAvailability.DISABLED || availability == EventAvailability.UNKNOWN) {
411 return false;
412 }
413 }
414 return true;
415 }
416
417 /**
418 * This method checks if the provided event types were explicitly disabled by checking the
419 * recording setting events.
420 *
421 * @param items
422 * the collection to check.
423 * @param typeIds
424 * the identifiers for the event types to check.
425 * @return true if all of the required event types were known to be explicitly enabled.
426 */
427 private static boolean isEventsDisabled(IItemCollection items, String ... typeIds) {
428 IQuantity aggregate = items.apply(createEnablementFilter(false, typeIds)).getAggregate(Aggregators.count());
429 return aggregate != null && aggregate.longValue() == typeIds.length;
430 }
431
432 /**
433 * Checks the event availability for the event types.
434 * <p>
435 * Care should be taken when used with multiple typeIds. Use it when all of the provided typeIds
436 * are expected to have the same availability; if mixed, the lowest common availability for all
437 * types will be returned.
438 *
439 * @param items
440 * the collection to check
441 * @param typeIds
442 * the type identifiers to check
443 * @return the availability for the event types
444 */
445 public static EventAvailability getEventAvailability(IItemCollection items, final String ... typeIds) {
925 try {
926 if (REC_SETTING_PERIOD_EVERY_CHUNK.equals(s)) {
927 return null;
928 }
929 IQuantity p = parsePersistedJvmTimespan(s);
930 if (maxPeriod == null || maxPeriod.compareTo(p) < 0) {
931 maxPeriod = p;
932 }
933 } catch (QuantityConversionException e) {
934 throw new RuntimeException(e);
935 }
936 }
937 return maxPeriod;
938 }
939
940 private static Set<String> getPeriodSettings(IItemCollection items, String ... typeIds) {
941 IItemFilter filter = getSettingsFilter(REC_SETTING_NAME_PERIOD, typeIds);
942 return items.apply(filter).getAggregate(Aggregators.distinct(JdkAttributes.REC_SETTING_VALUE));
943 }
944
945 private static String getDisabledEventTypeNames(IItemCollection items, String ... typeIds) {
946 return getEventTypeNames(items.apply(createEnablementFilter(false, typeIds)));
947 }
948
949 private static String getEventTypeNames(IItemCollection items, String ... typeIds) {
950 return getEventTypeNames(items.apply(getSettingsFilter(REC_SETTING_NAME_ENABLED, typeIds)));
951 }
952
953 private static String getEventTypeNames(IItemCollection items) {
954 Set<String> names = items.getAggregate(Aggregators.distinct("", TYPE_NAME_ACCESSOR_FACTORY)); //$NON-NLS-1$
955 if (names == null) {
956 return null;
957 }
958 List<String> quotedNames = new ArrayList<>();
959 for (String name : names) {
960 quotedNames.add("'" + name + "'"); //$NON-NLS-1$ //$NON-NLS-2$
961 }
962 Collections.sort(quotedNames);
963 return StringToolkit.join(quotedNames, ", "); //$NON-NLS-1$
964 }
|
94 import org.openjdk.jmc.flightrecorder.rules.tree.TimeRangeFilter;
95 import org.openjdk.jmc.flightrecorder.rules.tree.TimeRangeThreadFilter;
96 import org.openjdk.jmc.flightrecorder.stacktrace.FrameSeparator;
97 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceFormatToolkit;
98 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceFrame;
99 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceModel;
100 import org.openjdk.jmc.flightrecorder.stacktrace.StacktraceModel.Branch;
101
102 /**
103 * A collection of useful methods when evaluating rules.
104 */
105 // FIXME: Should probably be broken apart into methods related to rules (kept here) and methods related to JDK events (which should be moved to wherever JfrAttributes etc. are)
106 public class RulesToolkit {
107
108 // FIXME: Quick and dirty inlining of constants constants defined in SettingsTransformer. These should be handled in some other way.
109 private static final String REC_SETTING_NAME_ENABLED = "enabled"; //$NON-NLS-1$
110 private static final String REC_SETTING_NAME_THRESHOLD = "threshold"; //$NON-NLS-1$
111 public static final String REC_SETTING_NAME_PERIOD = "period"; //$NON-NLS-1$
112 public static final String REC_SETTING_PERIOD_EVERY_CHUNK = "everyChunk"; //$NON-NLS-1$
113
114 /*
115 * Returns the type name, as available in the recording settings, or simply the type id, if not
116 * available.
117 */
118 private static final IAccessorFactory<String> TYPE_NAME_ACCESSOR_FACTORY = new IAccessorFactory<String>() {
119 @Override
120 public <T> IMemberAccessor<String, T> getAccessor(final IType<T> type) {
121 final IMemberAccessor<LabeledIdentifier, T> ta = JdkAttributes.REC_SETTING_FOR.getAccessor(type);
122 return new IMemberAccessor<String, T>() {
123 @Override
124 public String getMember(T inObject) {
125 LabeledIdentifier labeledIdentifier = ta.getMember(inObject);
126 return labeledIdentifier == null ? type.getIdentifier() : labeledIdentifier.getName();
127 }
128 };
129 }
130 };
131 private final static LinearUnit MEBIBYTES = UnitLookup.MEMORY.getUnit(BinaryPrefix.MEBI);
132
133 /**
134 * Matches strings containing an identifiable version number as presented in a JVM info event.
135 * The minimal matching form is "JRE (" followed by 1 to 4 numbers on the format a.b.c_d or
136 * a.b.c.d. Examples are 1.7.0, 1.8.0_70, 9, 9.1, and 9.1.2.3. Match group 1 will contain the
137 * matched version string.
138 */
139 private static final Pattern VERSION_PATTERN = Pattern
140 .compile(".*?JRE \\((\\d+(?:\\.\\d+(?:\\.\\d+(?:[\\._]\\d+)?)?)?(?:-ea)?).*"); //$NON-NLS-1$
141
142 /**
143 * Knowledge about the state of affairs of an event type in an IItemCollection.
144 */
145 public enum EventAvailability {
146 /**
147 * The type has events available in the collection.
406 * the {@link EventAvailability} to check
407 * @return false if any {@link EventAvailability} is disabled or unavailable. Otherwise true.
408 */
409 public static boolean isEventsEnabled(EventAvailability ... eventAvailabilities) {
410 for (EventAvailability availability : eventAvailabilities) {
411 if (availability == EventAvailability.DISABLED || availability == EventAvailability.UNKNOWN) {
412 return false;
413 }
414 }
415 return true;
416 }
417
418 /**
419 * This method checks if the provided event types were explicitly disabled by checking the
420 * recording setting events.
421 *
422 * @param items
423 * the collection to check.
424 * @param typeIds
425 * the identifiers for the event types to check.
426 * @return true if all of the required event types were known to be explicitly disabled.
427 */
428 private static boolean isEventsDisabled(IItemCollection items, String ... typeIds) {
429 IQuantity aggregate = items.apply(createEnablementFilter(false, typeIds)).getAggregate(Aggregators.count());
430 return aggregate != null && aggregate.longValue() == typeIds.length;
431 }
432
433 /**
434 * Checks the event availability for the event types.
435 * <p>
436 * Care should be taken when used with multiple typeIds. Use it when all of the provided typeIds
437 * are expected to have the same availability; if mixed, the lowest common availability for all
438 * types will be returned.
439 *
440 * @param items
441 * the collection to check
442 * @param typeIds
443 * the type identifiers to check
444 * @return the availability for the event types
445 */
446 public static EventAvailability getEventAvailability(IItemCollection items, final String ... typeIds) {
926 try {
927 if (REC_SETTING_PERIOD_EVERY_CHUNK.equals(s)) {
928 return null;
929 }
930 IQuantity p = parsePersistedJvmTimespan(s);
931 if (maxPeriod == null || maxPeriod.compareTo(p) < 0) {
932 maxPeriod = p;
933 }
934 } catch (QuantityConversionException e) {
935 throw new RuntimeException(e);
936 }
937 }
938 return maxPeriod;
939 }
940
941 private static Set<String> getPeriodSettings(IItemCollection items, String ... typeIds) {
942 IItemFilter filter = getSettingsFilter(REC_SETTING_NAME_PERIOD, typeIds);
943 return items.apply(filter).getAggregate(Aggregators.distinct(JdkAttributes.REC_SETTING_VALUE));
944 }
945
946 /**
947 * Returns the names of the explicitly disabled event types.
948 */
949 private static String getDisabledEventTypeNames(IItemCollection items, String ... typeIds) {
950 return getEventTypeNames(items.apply(createEnablementFilter(false, typeIds)));
951 }
952
953 private static String getEventTypeNames(IItemCollection items, String ... typeIds) {
954 return getEventTypeNames(items.apply(getSettingsFilter(REC_SETTING_NAME_ENABLED, typeIds)));
955 }
956
957 private static String getEventTypeNames(IItemCollection items) {
958 Set<String> names = items.getAggregate(Aggregators.distinct("", TYPE_NAME_ACCESSOR_FACTORY)); //$NON-NLS-1$
959 if (names == null) {
960 return null;
961 }
962 List<String> quotedNames = new ArrayList<>();
963 for (String name : names) {
964 quotedNames.add("'" + name + "'"); //$NON-NLS-1$ //$NON-NLS-2$
965 }
966 Collections.sort(quotedNames);
967 return StringToolkit.join(quotedNames, ", "); //$NON-NLS-1$
968 }
|