/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.cassandra.utils.progress.jmx; import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Pattern; import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import javax.management.ObjectName; import org.apache.cassandra.utils.progress.ProgressEvent; import org.apache.cassandra.utils.progress.ProgressListener; import static org.apache.cassandra.service.ActiveRepairService.Status; /** * ProgressListener that translates ProgressEvent to legacy JMX Notification message (backward compatibility support) */ public class LegacyJMXProgressSupport implements ProgressListener { protected static final Pattern SESSION_FAILED_MATCHER = Pattern.compile("Repair session .* for range .* failed with error .*"); protected static final Pattern SESSION_SUCCESS_MATCHER = Pattern.compile("Repair session .* for range .* finished"); private final AtomicLong notificationSerialNumber = new AtomicLong(); private final ObjectName jmxObjectName; private final NotificationBroadcasterSupport broadcaster; public LegacyJMXProgressSupport(NotificationBroadcasterSupport broadcaster, ObjectName jmxObjectName) { this.broadcaster = broadcaster; this.jmxObjectName = jmxObjectName; } @Override public void progress(String tag, ProgressEvent event) { if (tag.startsWith("repair:")) { Optional<int[]> legacyUserData = getLegacyUserdata(tag, event); if (legacyUserData.isPresent()) { Notification jmxNotification = new Notification("repair", jmxObjectName, notificationSerialNumber.incrementAndGet(), event.getMessage()); jmxNotification.setUserData(legacyUserData.get()); broadcaster.sendNotification(jmxNotification); } } } protected static Optional<int[]> getLegacyUserdata(String tag, ProgressEvent event) { Optional<Status> status = getStatus(event); if (status.isPresent()) { int[] result = new int[2]; result[0] = getCmd(tag); result[1] = status.get().ordinal(); return Optional.of(result); } return Optional.empty(); } protected static Optional<Status> getStatus(ProgressEvent event) { switch (event.getType()) { case START: return Optional.of(Status.STARTED); case COMPLETE: return Optional.of(Status.FINISHED); case PROGRESS: if (SESSION_FAILED_MATCHER.matcher(event.getMessage()).matches()) { return Optional.of(Status.SESSION_FAILED); } else if (SESSION_SUCCESS_MATCHER.matcher(event.getMessage()).matches()) { return Optional.of(Status.SESSION_SUCCESS); } } return Optional.empty(); } protected static int getCmd(String tag) { return Integer.valueOf(tag.split(":")[1]); } }