/* * Copyright (c) 2002-2009 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.kernel.impl.transaction.xaframework; import java.io.IOException; import java.nio.channels.ReadableByteChannel; import java.util.Map; import java.util.StringTokenizer; /** * <CODE>XaDataSource</CODE> is as a factory for creating * {@link XaConnection XaConnections}. * <p> * If you're writing a data source towards a XA compatible resource the * implementation should be fairly straight forward. This will basically be a * factory for your {@link XaConnection XaConnections} that in turn will wrap * the XA compatible <CODE>XAResource</CODE>. * <p> * If you're writing a data source towards a non XA compatible resource use the * {@link XaContainer} and extend the {@link XaConnectionHelpImpl} as your * {@link XaConnection} implementation. Here is an example: * <p> * * <pre> * <CODE> * public class MyDataSource implements XaDataSource { * MyDataSource( params ) { * // ... initalization stuff * container = XaContainer.create( myLogicalLogFile, myCommandFactory, * myTransactionFactory ); * // ... more initialization stuff * container.openLogicalLog(); * } * public XaConnection getXaCo nnection() { * return new MyXaConnection( params ); * } * public void close() { * // ... cleanup * container.close(); * } * } * </CODE> * </pre> */ public abstract class XaDataSource { private byte[] branchId = null; private String name = null; /** * Constructor used by the Neo4j kernel to create datasources. * * @param params * A map containing configuration parameters */ public XaDataSource( Map<?,?> params ) throws InstantiationException { } /** * Creates a XA connection to the resource this data source represents. * * @return A connection to an XA resource */ public abstract XaConnection getXaConnection(); /** * Closes this data source. Calling <CODE>getXaConnection</CODE> after * this method has been invoked is illegal. */ public abstract void close(); /** * Used by the container/transaction manager in place to assign a branch * id for this data source. * * @param branchId the branch id */ public void setBranchId( byte branchId[] ) { this.branchId = branchId; } /** * Returns any assigned or default branch id for this data source. * * @return the branch id */ public byte[] getBranchId() { return this.branchId; } /** * Returns a timestamp when this data source was created. Note this is not * the timestamp for the creation of the data source object instance, if * the data source is for example a database timestamp is meant to be when * the database was created. * <p> * Creation time together with random identifier can be used to uniqley * identify a data source (since it is possible to have multiple sources * of same type). * * @return timestamp when this datasource was created */ public long getCreationTime() { throw new UnsupportedOperationException(); } public String getFileName( long version ) { throw new UnsupportedOperationException(); } /** * Returns a random identifier that gets generated when the data source is * created. Note with "created" we mean first time data source is created * and not object creation. * <p> * Creation time together with the random identifier can be used to uniquely * identify a data source (since it is possible to have multiple sources of * the same type). * * @return random identifier for this data source */ public long getRandomIdentifier() { throw new UnsupportedOperationException(); } /** * Returns the current version of this data source. A invoke to the * {@link #rotateLogicalLog()} when {@link #keepLogicalLogs(boolean)} is * set to <code>true</code> will result in a log with that version created. * * @return the current version of the logical log */ public long getCurrentLogVersion() { throw new UnsupportedOperationException(); } /** * Attempts to apply a logical log to this data source. * * @param byteChannel readable channel containing the logical log data * * @throws IOException if a problem with reading the log occurs * @throws IllegalStateException if log being applied is not of right * version, if not in backup slave mode or there are active transactions */ public void applyLog( ReadableByteChannel byteChannel ) throws IOException { throw new UnsupportedOperationException(); } /** * Rotates this logical log. If {@link #keepLogicalLogs(boolean)} is * configured to true the log will be saved and can be retrieved with the * {@link #getLogicalLog(long)} method. If not it will be deleted. Active * transactions get copied to a new logical log. * * @throws IOException if unable to read old log or write to new one */ public void rotateLogicalLog() throws IOException { throw new UnsupportedOperationException(); } /** * Returns a readable byte channel of the specified logical log. * * @param version version of the logical log * @return readable byte channel of the logical log * @throws IOException if no such log exist */ public ReadableByteChannel getLogicalLog( long version ) throws IOException { throw new UnsupportedOperationException(); } /** * Tests if a specific logical log exists. * * @param version the version of the logical log * @return <CODE>true</CODE> if the log exists */ public boolean hasLogicalLog( long version ) { throw new UnsupportedOperationException(); } public long getLogicalLogLength( long version ) { throw new UnsupportedOperationException(); } /** * Deletes a log specific logical log. * * @param version version of log to delete * * @return true if the log existed and was deleted */ public boolean deleteLogicalLog( long version ) { throw new UnsupportedOperationException(); } /** * Sets wether logical logs should be saved upon rotation or not. Default * is <CODE>false</CODE>. * * @param keepLogs <CODE>true</CODE> means save, <CODE>false</CODE> means * delete */ public void keepLogicalLogs( boolean keepLogs ) { throw new UnsupportedOperationException(); } public boolean isLogicalLogKept() { throw new UnsupportedOperationException(); } /** * Used by the container to assign a name to this resource. * * @param name name of this resource */ public void setName( String name ) { this.name = name; } /** * Returns the assigned name of this resource. * * @return the assigned name of this resource */ public String getName() { return name; } /** * Makes this data source a backup slave. This method can not be called * while there are active transactions. Once set in "backup slave" mode * no new transactions can start, the resource has to be closed and * reopened for that. * * @throws IllegalStateException if this resource has active transactions */ public void makeBackupSlave() { throw new UnsupportedOperationException(); } /** * Turns off/on auto rotate of logical logs. Default is <CODE>true</CODE>. * * @param rotate <CODE>true</CODE> to turn on */ public void setAutoRotate( boolean rotate ) { throw new UnsupportedOperationException(); } /** * Sets the target size of the logical log that will cause a rotation of * the log if {@link #setAutoRotate(boolean)} is set to <CODE>true</CODE>. * * @param size target size in bytes */ public void setLogicalLogTargetSize( long size ) { throw new UnsupportedOperationException(); } /** * If the config says that logical logs should be kept for the given * {@code resourceName} this method will return {@code true}, otherwise * {@code false}. The format of the configuration value is either: * <ul> * <li><b>=</b> : no data sources will keep its logs</li> * <li><b>=nioneodb,lucene</b> : the specified data sources will keep its logs</li> * <li><b>=true</b> : all data sources will keep their logical logs</li> * </ul> * The first and last are recommended, since the data source names are really * an implementation detail. * * @param config the configuration value specified by user configuration. * @param resourceName the name of the xa data source to check. * @return whether or not logical logs should be kept for the data source * by the name {@code resourceName} or not. */ protected boolean shouldKeepLog( String config, String resourceName ) { if ( config != null ) { if ( config.equals( Boolean.TRUE.toString() ) ) { return true; } StringTokenizer tok = new StringTokenizer( config, "," ); while ( tok.hasMoreTokens() ) { String element = tok.nextToken().trim(); if ( resourceName.equals( element ) ) { return true; } } } return false; } }