All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hornetq.jms.persistence.impl.journal.JMSJournalStorageManagerImpl Maven / Gradle / Ivy

/*
 * Copyright 2010 Red Hat, Inc.
 * Red Hat 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.hornetq.jms.persistence.impl.journal;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.hornetq.api.core.HornetQBuffer;
import org.hornetq.api.core.HornetQBuffers;
import org.hornetq.api.core.Pair;
import org.hornetq.core.config.Configuration;
import org.hornetq.core.journal.Journal;
import org.hornetq.core.journal.PreparedTransactionInfo;
import org.hornetq.core.journal.RecordInfo;
import org.hornetq.core.journal.SequentialFileFactory;
import org.hornetq.core.journal.impl.JournalImpl;
import org.hornetq.core.journal.impl.NIOSequentialFileFactory;
import org.hornetq.core.replication.ReplicatedJournal;
import org.hornetq.core.replication.ReplicationManager;
import org.hornetq.core.server.JournalType;
import org.hornetq.jms.persistence.JMSStorageManager;
import org.hornetq.jms.persistence.config.PersistedConnectionFactory;
import org.hornetq.jms.persistence.config.PersistedDestination;
import org.hornetq.jms.persistence.config.PersistedJNDI;
import org.hornetq.jms.persistence.config.PersistedType;
import org.hornetq.utils.IDGenerator;

/**
 * A JournalJMSStorageManagerImpl
 *
 * @author Clebert Suconic
 *
 *
 */
public final class JMSJournalStorageManagerImpl implements JMSStorageManager
{

   // Constants -----------------------------------------------------

   public static final byte CF_RECORD = 1;

   public static final byte DESTINATION_RECORD = 2;

   public static final byte JNDI_RECORD = 3;

   // Attributes ----------------------------------------------------

   private final IDGenerator idGenerator;

   private final String journalDir;

   private final boolean createDir;

   private final Journal jmsJournal;

   private volatile boolean started;

   private final Map mapFactories = new ConcurrentHashMap();

   private final Map, PersistedDestination> destinations = new ConcurrentHashMap, PersistedDestination>();

   private final Map, PersistedJNDI> mapJNDI = new ConcurrentHashMap, PersistedJNDI>();

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------
   public JMSJournalStorageManagerImpl(final IDGenerator idGenerator,
                                       final Configuration config,
                                final ReplicationManager replicator)
   {
      if (config.getJournalType() != JournalType.NIO && config.getJournalType() != JournalType.ASYNCIO)
      {
         throw new IllegalArgumentException("Only NIO and AsyncIO are supported journals");
      }

      // Will use the same place as the bindings directory from the core journal
      journalDir = config.getBindingsDirectory();

      if (journalDir == null)
      {
         throw new NullPointerException("bindings-dir is null");
      }

      createDir = config.isCreateBindingsDir();

      SequentialFileFactory bindingsJMS = new NIOSequentialFileFactory(journalDir);

      Journal localJMS = new JournalImpl(1024 * 1024,
                                              2,
                                              config.getJournalCompactMinFiles(),
                                              config.getJournalCompactPercentage(),
                                              bindingsJMS,
                                              "hornetq-jms",
                                              "jms",
                                              1);

      if (replicator != null)
      {
         jmsJournal = new ReplicatedJournal((byte)2, localJMS, replicator);
      }
      else
      {
         jmsJournal = localJMS;
      }

      this.idGenerator = idGenerator;
   }


   // Public --------------------------------------------------------
   @Override
   public List recoverConnectionFactories()
   {
      List cfs = new ArrayList(mapFactories.size());
      cfs.addAll(mapFactories.values());
      return cfs;
   }

   @Override
   public void storeConnectionFactory(final PersistedConnectionFactory connectionFactory) throws Exception
   {
      deleteConnectionFactory(connectionFactory.getName());
      long id = idGenerator.generateID();
      connectionFactory.setId(id);
      jmsJournal.appendAddRecord(id, CF_RECORD, connectionFactory, true);
      mapFactories.put(connectionFactory.getName(), connectionFactory);
   }

   public void deleteConnectionFactory(final String cfName) throws Exception
   {
      PersistedConnectionFactory oldCF = mapFactories.remove(cfName);
      if (oldCF != null)
      {
         jmsJournal.appendDeleteRecord(oldCF.getId(), false);
      }
   }

   @Override
   public List recoverDestinations()
   {
      List destinations = new ArrayList(this.destinations.size());
      destinations.addAll(this.destinations.values());
      return destinations;
   }

   @Override
   public void storeDestination(final PersistedDestination destination) throws Exception
   {
      deleteDestination(destination.getType(), destination.getName());
      long id = idGenerator.generateID();
      destination.setId(id);
      jmsJournal.appendAddRecord(id, DESTINATION_RECORD, destination, true);
      destinations.put(new Pair(destination.getType(), destination.getName()), destination);
   }

   public List recoverPersistedJNDI() throws Exception
   {
      ArrayList list = new ArrayList();

      list.addAll(mapJNDI.values());

      return list;
   }

   public void addJNDI(PersistedType type, String name, String ... address) throws Exception
   {
      Pair key = new Pair(type, name);

      long tx = idGenerator.generateID();

      PersistedJNDI currentJNDI = mapJNDI.get(key);
      if (currentJNDI != null)
      {
         jmsJournal.appendDeleteRecordTransactional(tx, currentJNDI.getId());
      }
      else
      {
         currentJNDI = new PersistedJNDI(type, name);
      }

      mapJNDI.put(key, currentJNDI);

      for (String adItem : address)
      {
         currentJNDI.addJNDI(adItem);
      }


      long newId = idGenerator.generateID();

      currentJNDI.setId(newId);

      jmsJournal.appendAddRecordTransactional(tx, newId, JNDI_RECORD, currentJNDI);

      jmsJournal.appendCommitRecord(tx, true);
   }

   public void deleteJNDI(PersistedType type, String name, String address) throws Exception
   {
      Pair key = new Pair(type, name);

      long tx = idGenerator.generateID();

      PersistedJNDI currentJNDI = mapJNDI.get(key);
      if (currentJNDI == null)
      {
         return;
      }
      else
      {
         jmsJournal.appendDeleteRecordTransactional(tx, currentJNDI.getId());
      }

      currentJNDI.deleteJNDI(address);

      if (currentJNDI.getJndi().size() == 0)
      {
         mapJNDI.remove(key);
      }
      else
      {
         long newId = idGenerator.generateID();
         currentJNDI.setId(newId);
         jmsJournal.appendAddRecordTransactional(tx, newId, JNDI_RECORD, currentJNDI);
      }

      jmsJournal.appendCommitRecord(tx, true);
   }


   public void deleteJNDI(PersistedType type, String name) throws Exception
   {
      Pair key = new Pair(type, name);

      PersistedJNDI currentJNDI = mapJNDI.remove(key);

      if (currentJNDI != null)
      {
         jmsJournal.appendDeleteRecord(currentJNDI.getId(), true);
      }
   }

   public void deleteDestination(final PersistedType type, final String name) throws Exception
   {
      PersistedDestination destination = destinations.remove(new Pair(type, name));
      if(destination != null)
      {
         jmsJournal.appendDeleteRecord(destination.getId(), false);
      }
   }

   @Override
   public boolean isStarted()
   {
      return started;
   }


   @Override
   public void start() throws Exception
   {

      checkAndCreateDir(journalDir, createDir);

      jmsJournal.start();

      started = true;
   }

   @Override
   public void stop() throws Exception
   {
      this.started = false;
      jmsJournal.stop();
   }

   public void load() throws Exception
   {
      mapFactories.clear();

      List data = new ArrayList();

      ArrayList list = new ArrayList();

      jmsJournal.load(data, list, null);

      for (RecordInfo record : data)
      {
         long id = record.id;

         HornetQBuffer buffer = HornetQBuffers.wrappedBuffer(record.data);

         byte rec = record.getUserRecordType();

         if (rec == CF_RECORD)
         {
            PersistedConnectionFactory cf = new PersistedConnectionFactory();
            cf.decode(buffer);
            cf.setId(id);
            mapFactories.put(cf.getName(), cf);
         }
         else if(rec == DESTINATION_RECORD)
         {
            PersistedDestination destination = new PersistedDestination();
            destination.decode(buffer);
            destination.setId(id);
            destinations.put(new Pair(destination.getType(), destination.getName()), destination);
         }
         else if (rec == JNDI_RECORD)
         {
            PersistedJNDI jndi = new PersistedJNDI();
            jndi.decode(buffer);
            jndi.setId(id);
            Pair key = new Pair(jndi.getType(), jndi.getName());
            mapJNDI.put(key, jndi);
         }
         else
         {
            throw new IllegalStateException("Invalid record type " + rec);
         }

      }

   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------


   private void checkAndCreateDir(final String dir, final boolean create)
   {
      File f = new File(dir);

      if (!f.exists())
      {
         if (create)
         {
            if (!f.mkdirs())
            {
               throw new IllegalStateException("Failed to create directory " + dir);
            }
         }
         else
         {
            throw new IllegalArgumentException("Directory " + dir + " does not exist and will not create it");
         }
      }
   }



   // Inner classes -------------------------------------------------

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy