/* * 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.activemq.artemis.core.journal.impl; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import org.apache.activemq.artemis.core.io.SequentialFile; import org.jboss.logging.Logger; public class JournalFileImpl implements JournalFile { private final SequentialFile file; private final long fileID; private final int recordID; private long offset; private final AtomicInteger posCount = new AtomicInteger(0); private final AtomicInteger liveBytes = new AtomicInteger(0); // Flags to be used by determine if the journal file can be reclaimed private boolean posReclaimCriteria = false; private boolean negReclaimCriteria = false; private final AtomicInteger totalNegativeToOthers = new AtomicInteger(0); private final int version; private final ConcurrentMap<JournalFile, AtomicInteger> negCounts = new ConcurrentHashMap<>(); private static final Logger logger = Logger.getLogger(JournalFileImpl.class); public JournalFileImpl(final SequentialFile file, final long fileID, final int version) { this.file = file; this.fileID = fileID; this.version = version; recordID = (int) (fileID & Integer.MAX_VALUE); } @Override public int getPosCount() { return posCount.intValue(); } @Override public boolean isPosReclaimCriteria() { return posReclaimCriteria; } @Override public void setPosReclaimCriteria() { this.posReclaimCriteria = true; } @Override public boolean isNegReclaimCriteria() { return negReclaimCriteria; } @Override public void setNegReclaimCriteria() { this.negReclaimCriteria = true; } @Override public boolean isCanReclaim() { return posReclaimCriteria && negReclaimCriteria; } @Override public void incNegCount(final JournalFile file) { if (file != this) { totalNegativeToOthers.incrementAndGet(); } AtomicInteger previous = negCounts.putIfAbsent(file, new AtomicInteger(1)); if (previous != null) { previous.incrementAndGet(); } } @Override public int getNegCount(final JournalFile file) { AtomicInteger count = negCounts.get(file); if (count == null) { return 0; } else { return count.intValue(); } } @Override public int getJournalVersion() { return version; } @Override public void incPosCount() { posCount.incrementAndGet(); } @Override public void decPosCount() { posCount.decrementAndGet(); } public long getOffset() { return offset; } @Override public long getFileID() { return fileID; } @Override public int getRecordID() { return recordID; } public void setOffset(final long offset) { this.offset = offset; } @Override public SequentialFile getFile() { return file; } @Override public String toString() { try { return "JournalFileImpl: (" + file.getFileName() + " id = " + fileID + ", recordID = " + recordID + ")"; } catch (Exception e) { logger.warn("Error during method invocation", e.getMessage(), e); return "Error:" + e.toString(); } } /** * Receive debug information about the journal */ public String debug() { StringBuilder builder = new StringBuilder(); for (Entry<JournalFile, AtomicInteger> entry : negCounts.entrySet()) { builder.append(" file = " + entry.getKey() + " negcount value = " + entry.getValue() + "\n"); } return builder.toString(); } @Override public void addSize(final int bytes) { liveBytes.addAndGet(bytes); } @Override public void decSize(final int bytes) { liveBytes.addAndGet(-bytes); } @Override public int getLiveSize() { return liveBytes.get(); } @Override public int getTotalNegativeToOthers() { return totalNegativeToOthers.get(); } }