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

org.snmp4j.agent.db.MOXodusPersistenceProvider Maven / Gradle / Ivy

There is a newer version: 3.8.1
Show newest version
/*_############################################################################
  _## 
  _##  SNMP4J-Agent-DB 3 - MOXodusPersistenceProvider.java  
  _## 
  _##  Copyright (C) 2017-2018  Frank Fock (SNMP4J.org)
  _##  
  _##  Licensed 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.snmp4j.agent.db;

import jetbrains.exodus.ArrayByteIterable;
import jetbrains.exodus.ByteIterable;
import jetbrains.exodus.bindings.IntegerBinding;
import jetbrains.exodus.bindings.StringBinding;
import jetbrains.exodus.env.*;
import org.snmp4j.agent.MOServer;
import org.snmp4j.agent.cfg.EngineBootsProvider;
import org.snmp4j.agent.cfg.EngineIdProvider;
import org.snmp4j.agent.io.ImportMode;
import org.snmp4j.agent.io.MOPersistenceProvider;
import org.snmp4j.smi.OctetString;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * The {@link MOXodusPersistenceProvider} implements a {@link MOPersistenceProvider} that uses a JetBrains Xodus
 * database for persistent storage of {@link org.snmp4j.agent.RandomAccessManagedObject}s.
 * Using {@link org.snmp4j.agent.RandomAccessManagedObject} peristence with this {@link MOXodusPersistenceProvider} has
 * the following advantages:
 * 
    *
  • Less disk space usage than with {@link org.snmp4j.agent.io.DefaultMOPersistenceProvider}
  • *
  • Any Managed object changes are store via {@link org.snmp4j.agent.mo.MOChangeListener} and * {@link org.snmp4j.agent.mo.MOTableRowListener} persistently into the database immediately.
  • *
  • Concurrent access to storage is safe.
  • *
* See {@link org.snmp4j.agent.io.MOServerPersistence} for sample code and further usage details. * * @author Frank Fock * @version 3.0 */ public class MOXodusPersistenceProvider implements MOPersistenceProvider, EngineBootsProvider, EngineIdProvider { /** * Engine store ID must be longer than 32 characters - otherwise name could clash with a SNMP context. */ private final static String ENGINE_STORE_ID = "_SNMP4J-Agent_EngineStore_______v3.0"; private static final String BOOTS_COUNTER_KEY = "BootsCounter"; private static final String ENGINE_ID_KEY = "EngineID"; private MOXodusPersistence defaultPersistence; /** * Creates a {@link MOXodusPersistenceProvider} based with a provided default {@link MOXodusPersistence} handler * that provides the default storage access operations and listens for * {@link org.snmp4j.agent.RandomAccessManagedObject} update events * (see {@link MOXodusPersistence#registerChangeListenersWithServer(MOServer)} for details). * * Additional {@link MOXodusPersistence} can be created on the fly, with {@link #store(String)}. * * @param defaultPersistence * the default persistence handler. */ public MOXodusPersistenceProvider(MOXodusPersistence defaultPersistence) { this.defaultPersistence = defaultPersistence; } /** * Restore (load) agent state from the specified URI (can be as simple as * a file path). * * @param uri a string pointing to the persistent storage from which the agent state * should be restored from. The format of he string is specified by the * persistence provider. A null value can be specified to * let the persistence provider use its default URI. If that default URI * is null too, a NullPointerException will be * thrown. * @param importMode specifies how the agent's current state should be update while * restoring a previous state. * @throws IOException if the restore operation fails. * @since 1.2 */ @Override public void restore(String uri, int importMode) throws IOException { MOXodusPersistence persistence = defaultPersistence; boolean specialURI = (uri != null && !uri.equals(getDefaultURI())); if (specialURI) { persistence = new MOXodusPersistence(defaultPersistence.getMOServer(), Environments.newInstance(getFilePath(uri))); } persistence.load(ImportMode.values()[importMode]); if (specialURI) { persistence.getEnvironment().close(); } } /** * Stores the current agent state to persistent storage specified by the * supplied URI. * * @param uri a string pointing to the persistent storage from which the agent state * should be stored to. The format of the string is specified by the * persistence provider. A null value can be specified to * let the persistence provider use its default URI. If that default URI * is null too, a NullPointerException will be * thrown. * @throws IOException if the store operation fails. * @since 1.2 */ @Override public void store(String uri) throws IOException { MOXodusPersistence persistence = defaultPersistence; boolean specialURI = (uri != null && !uri.equals(getDefaultURI())); if (specialURI) { persistence = new MOXodusPersistence(defaultPersistence.getMOServer(), Environments.newInstance(getFilePath(uri))); } persistence.save(); if (specialURI) { persistence.getEnvironment().close(); } } /** * Checks whether the supplied URI string is valid for this persistence * provider. * * @param uriString a string identifying a persistent storage location for this storage * provider. * @return true if the uri is valid, false * otherwise. * @since 1.2 */ @Override public boolean isValidPersistenceURI(String uriString) { try { URI uri = new URI(uriString); if (uri.getScheme() == null || uri.getScheme().equals("file")) { return true; } return false; } catch (URISyntaxException e) { return false; } } /** * Returns an unique ID of the persistence provider which should identify the * format and type of the persistence provider. * * @return an 1-32 character long string that identifies the persistence provider. * @since 1.2 */ @Override public String getPersistenceProviderID() { return "default"; } /** * Gets the URI of the default persistent storage for this provider. * * @return the URI (e.g. file path) for the default persistent storage location of * this provider. A provider may use a different one. A null * value indicates that there is no default location. */ @Override public String getDefaultURI() { return defaultPersistence.getEnvironment().getLocation(); } private String getFilePath(String uri) { File f; if (uri.toUpperCase().startsWith("FILE:")) { URI u = URI.create(uri); f = new File(u); } else { f = new File(uri); } return f.getPath(); } /** * Returns the current engine boot counter value incremented by one. If * that number would by greater than 2^31-1 then one is returned. The * engine boots provider has to make sure that the returned value is * persistently stored before the method returns. * * @return the last engine boots counter incremented by one. */ @Override public int updateEngineBoots() { Environment environment = defaultPersistence.getEnvironment(); Transaction txn = environment.beginExclusiveTransaction(); Store store = environment.openStore(ENGINE_STORE_ID, StoreConfig.WITHOUT_DUPLICATES, txn); ByteIterable bootsCounterKey = StringBinding.stringToEntry(BOOTS_COUNTER_KEY); ByteIterable bootsCounterRaw = store.get(txn, bootsCounterKey); int bootsCounter = 0; if (bootsCounterRaw != null) { bootsCounter = IntegerBinding.entryToInt(bootsCounterRaw); bootsCounter++; store.put(txn, bootsCounterKey, IntegerBinding.intToEntry(bootsCounter)); } txn.flush(); txn.commit(); return bootsCounter; } /** * Returns current engine boot counter value. * * @return the last engine boots counter. */ @Override public int getEngineBoots() { Environment environment = defaultPersistence.getEnvironment(); Transaction txn = environment.beginReadonlyTransaction(); Store store = environment.openStore(ENGINE_STORE_ID, StoreConfig.WITHOUT_DUPLICATES, txn); ByteIterable bootsCounterKey = StringBinding.stringToEntry(BOOTS_COUNTER_KEY); ByteIterable bootsCounterRaw = store.get(txn, bootsCounterKey); int bootsCounter = 0; if (bootsCounterRaw != null) { bootsCounter = IntegerBinding.entryToInt(bootsCounterRaw); } txn.abort(); return bootsCounter; } @Override public OctetString getEngineId(OctetString defaultEngineID) { Environment environment = defaultPersistence.getEnvironment(); Transaction txn = environment.beginExclusiveTransaction(); Store store = environment.openStore(ENGINE_STORE_ID, StoreConfig.WITHOUT_DUPLICATES, txn); ByteIterable engineIdKey = StringBinding.stringToEntry(ENGINE_ID_KEY); ByteIterable engineIdRaw = store.get(txn, engineIdKey); byte[] engineID = null; if (engineIdRaw != null) { engineID = new byte[engineIdRaw.getLength()]; System.arraycopy(engineIdRaw.getBytesUnsafe(), 0, engineID, 0, engineID.length); } else if (defaultEngineID != null) { engineID = defaultEngineID.getValue(); resetEngineId(txn, store, engineID); } txn.flush(); txn.commit(); return (engineIdRaw != null) ? new OctetString(engineID) : defaultEngineID; } @Override public void resetEngineId(OctetString engineId) { Environment environment = defaultPersistence.getEnvironment(); Transaction txn = environment.beginExclusiveTransaction(); Store store = environment.openStore(ENGINE_STORE_ID, StoreConfig.WITHOUT_DUPLICATES, txn); resetEngineId(txn, store, engineId.getValue()); } private void resetEngineId(Transaction txn, Store store, byte[] engineID) { ByteIterable engineIdKey = StringBinding.stringToEntry(ENGINE_ID_KEY); store.put(txn, engineIdKey, new ArrayByteIterable(engineID)); ByteIterable bootsCounterKey = StringBinding.stringToEntry(BOOTS_COUNTER_KEY); store.put(txn, bootsCounterKey, IntegerBinding.intToEntry(1)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy