001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.store; 019 020 import java.util.Properties; 021 022 import javax.jdo.PersistenceManager; 023 024 import org.cumulus4j.store.model.Sequence; 025 import org.datanucleus.store.connection.ManagedConnection; 026 import org.datanucleus.store.valuegenerator.AbstractDatastoreGenerator; 027 import org.datanucleus.store.valuegenerator.ValueGenerationBlock; 028 import org.datanucleus.store.valuegenerator.ValueGenerator; 029 030 /** 031 * {@link ValueGenerator} implementation generating values by incrementing a counter. 032 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 033 */ 034 public class Cumulus4jIncrementGenerator extends AbstractDatastoreGenerator 035 { 036 private String sequenceName; 037 038 /** 039 * Create an instance. This is called by DataNucleus. 040 * @param name symbolic name for the generator. 041 * @param props Properties controlling the behaviour of the generator. 042 */ 043 public Cumulus4jIncrementGenerator(String name, Properties props) { 044 super(name, props); 045 allocationSize = 5; 046 047 // TODO Check these names and what we want to use for Cumulus4j (classname or fieldname) 048 if (properties.getProperty("sequence-name") != null) { 049 // Specified sequence-name so use that 050 sequenceName = properties.getProperty("sequence-name"); 051 } 052 else if (properties.getProperty("field-name") != null) { 053 // Use field name as the sequence name so we have one sequence per field on the class 054 sequenceName = properties.getProperty("field-name"); 055 } 056 else { 057 // Use actual class name as the sequence name so we have one sequence per class 058 sequenceName = properties.getProperty("class-name"); 059 } 060 } 061 062 @Override 063 protected ValueGenerationBlock reserveBlock(long size) { 064 if (size > Integer.MAX_VALUE) 065 throw new IllegalStateException("Cannot reserve a block of more than " + Integer.MAX_VALUE + " values!"); 066 067 Long[] values = new Long[(int)size]; 068 ManagedConnection mconn = connectionProvider.retrieveConnection(); 069 try { 070 PersistenceManagerConnection pmConn = (PersistenceManagerConnection)mconn.getConnection(); 071 PersistenceManager pm = pmConn.getDataPM(); 072 pm.currentTransaction().setSerializeRead(true); 073 try { 074 Sequence sequence = Sequence.createSequence(pm, sequenceName); 075 long nextValue = sequence.getNextValue(); 076 for (int idx = 0; idx < values.length; ++idx) { 077 values[idx] = nextValue++; 078 } 079 sequence.setNextValue(nextValue); 080 } finally { 081 pm.currentTransaction().setSerializeRead(false); 082 } 083 } finally { 084 connectionProvider.releaseConnection(); 085 } 086 return new ValueGenerationBlock(values); 087 } 088 }