001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.batch.index;
021
022 import com.google.common.collect.Lists;
023 import com.google.common.collect.Maps;
024 import org.slf4j.Logger;
025 import org.slf4j.LoggerFactory;
026 import org.sonar.api.batch.events.DecoratorExecutionHandler;
027 import org.sonar.api.batch.events.DecoratorsPhaseHandler;
028 import org.sonar.api.batch.events.SensorExecutionHandler;
029 import org.sonar.api.database.DatabaseSession;
030 import org.sonar.api.database.model.MeasureData;
031 import org.sonar.api.database.model.MeasureModel;
032 import org.sonar.api.measures.Measure;
033 import org.sonar.api.measures.PersistenceMode;
034
035 import java.util.List;
036 import java.util.Map;
037
038 /**
039 * @since 2.7
040 */
041 public class MemoryOptimizer implements SensorExecutionHandler, DecoratorExecutionHandler, DecoratorsPhaseHandler {
042
043 private static final Logger LOG = LoggerFactory.getLogger(MemoryOptimizer.class);
044
045 private List<Measure> loadedMeasures = Lists.newArrayList();
046 private Map<Long, Integer> dataIdByMeasureId = Maps.newHashMap();
047 private DatabaseSession session;
048
049 public MemoryOptimizer(DatabaseSession session) {
050 this.session = session;
051 }
052
053 /**
054 * Remove data of a database measure from memory.
055 */
056 public void evictDataMeasure(Measure measure, MeasureModel model) {
057 if (PersistenceMode.DATABASE.equals(measure.getPersistenceMode())) {
058 MeasureData data = model.getMeasureData();
059 if (data != null && data.getId() != null) {
060 if (LOG.isDebugEnabled()) {
061 LOG.debug("Remove data measure from memory: " + measure.getMetricKey() + ", id=" + measure.getId());
062 }
063 measure.unsetData();
064 dataIdByMeasureId.put(measure.getId(), data.getId());
065 }
066 }
067 }
068
069 public Measure reloadMeasure(Measure measure) {
070 if (measure.getId() != null && dataIdByMeasureId.containsKey(measure.getId()) && !measure.hasData()) {
071 Integer dataId = dataIdByMeasureId.get(measure.getId());
072 MeasureData data = session.getSingleResult(MeasureData.class, "id", dataId);
073 if (data == null) {
074 LoggerFactory.getLogger(getClass()).error("The MEASURE_DATA row with id " + dataId + " is lost");
075
076 } else {
077 if (LOG.isDebugEnabled()) {
078 LOG.debug("Reload the data measure: " + measure.getMetricKey() + ", id=" + measure.getId());
079 }
080 measure.setData(data.getText());
081 loadedMeasures.add(measure);
082 }
083 }
084 return measure;
085 }
086
087 public void flushMemory() {
088 if (LOG.isDebugEnabled() && !loadedMeasures.isEmpty()) {
089 LOG.debug("Flush " + loadedMeasures.size() + " data measures from memory: ");
090 }
091 for (Measure measure : loadedMeasures) {
092 measure.unsetData();
093 }
094 loadedMeasures.clear();
095 }
096
097 boolean isTracked(Long measureId) {
098 return dataIdByMeasureId.get(measureId) != null;
099 }
100
101 public void onSensorExecution(SensorExecutionEvent event) {
102 if (event.isEnd()) {
103 flushMemory();
104 session.commit();
105 }
106 }
107
108 public void onDecoratorExecution(DecoratorExecutionEvent event) {
109 if (event.isEnd()) {
110 flushMemory();
111 }
112 }
113
114 public void onDecoratorsPhase(DecoratorsPhaseEvent event) {
115 if (event.isEnd()) {
116 session.commit();
117 }
118 }
119
120 }