/** * Method to find an object value generator based on its name. Caches the generators once * generated. * * @param ec ExecutionContext * @param genName The generator name * @return The value generator (if any) * @throws NucleusException if no generator of that name is found */ protected static ObjectValueGenerator getObjectValueGenerator( ExecutionContext ec, String genName) { if (!objectValGenerators.isEmpty()) { ObjectValueGenerator valGen = objectValGenerators.get(genName); if (valGen != null) { return valGen; } } try { ObjectValueGenerator valGen = (ObjectValueGenerator) ec.getNucleusContext() .getPluginManager() .createExecutableExtension( "org.datanucleus.store_objectvaluegenerator", new String[] {"name"}, new String[] {genName}, "class-name", null, null); objectValGenerators.put(genName, valGen); return valGen; } catch (Exception e) { NucleusLogger.VALUEGENERATION.info( "Exception thrown generating value using objectvaluegenerator " + genName, e); throw new NucleusException("Exception thrown generating value for object", e); } }
/* (non-Javadoc) * @see org.datanucleus.store.valuegenerator.AbstractGenerator#reserveBlock(long) */ protected synchronized ValueGenerationBlock<Long> reserveBlock(long size) { if (size < 1) { return null; } if (this.table == null) { this.initialiseTable(); } // Allocate value(s) long number; List<Long> oids = new ArrayList<Long>(); try { number = table.incrementColumnValue( Bytes.toBytes(key), Bytes.toBytes(INCREMENT_COL_NAME), Bytes.toBytes(INCREMENT_COL_NAME), size); long nextNumber = number - size + 1; for (int i = 0; i < size; i++) { oids.add(nextNumber++); } } catch (IOException ex) { NucleusLogger.VALUEGENERATION.error( "IncrementGenerator: Error incrementing generated value", ex); throw new NucleusDataStoreException("Error incrementing generated value.", ex); } return new ValueGenerationBlock<Long>(oids); }
private synchronized void initialiseTable() { if (this.table == null) { try { HBaseStoreManager hbaseMgr = (HBaseStoreManager) storeMgr; Configuration config = hbaseMgr.getHbaseConfig(); HBaseAdmin admin = new HBaseAdmin(config); try { if (!admin.tableExists(this.tableName)) { if (!storeMgr.getSchemaHandler().isAutoCreateTables()) { throw new NucleusUserException(Localiser.msg("040011", tableName)); } NucleusLogger.VALUEGENERATION.debug( "IncrementGenerator: Creating Table '" + this.tableName + "'"); HTableDescriptor ht = new HTableDescriptor(this.tableName); HColumnDescriptor hcd = new HColumnDescriptor(INCREMENT_COL_NAME); hcd.setCompressionType(Algorithm.NONE); hcd.setMaxVersions(1); ht.addFamily(hcd); admin.createTable(ht); } } finally { admin.close(); } this.table = new HTable(config, this.tableName); if (!this.table.exists(new Get(Bytes.toBytes(key)))) { long initialValue = 0; if (properties.containsKey("key-initial-value")) { initialValue = Long.valueOf(properties.getProperty("key-initial-value")) - 1; } this.table.put( new Put(Bytes.toBytes(key)) .add( Bytes.toBytes(INCREMENT_COL_NAME), Bytes.toBytes(INCREMENT_COL_NAME), Bytes.toBytes(initialValue))); } } catch (IOException ex) { NucleusLogger.VALUEGENERATION.fatal("Error instantiating IncrementGenerator", ex); } } }
/** * Method to reserve a block of "size" identities. * * @param size Block size * @return The reserved block */ public ValueGenerationBlock reserveBlock(long size) { if (size < 1) { return null; } // search for an ID in the database List oid = new ArrayList(); try { if (sequenceTable == null) { initialiseSequenceTable(); } DatastoreIdentifier sourceTableIdentifier = null; if (properties.getProperty("table-name") != null) { sourceTableIdentifier = ((RDBMSStoreManager) storeMgr) .getIdentifierFactory() .newTableIdentifier(properties.getProperty("table-name")); // TODO Apply passed in catalog/schema to this identifier rather than the default for the // factory } Long nextId = sequenceTable.getNextVal( sequenceName, connection, (int) size, sourceTableIdentifier, properties.getProperty("column-name"), initialValue); for (int i = 0; i < size; i++) { oid.add(nextId); nextId = Long.valueOf(nextId.longValue() + 1); } if (NucleusLogger.VALUEGENERATION.isDebugEnabled()) { NucleusLogger.VALUEGENERATION.debug(LOCALISER.msg("040004", "" + size)); } return new ValueGenerationBlock(oid); } catch (SQLException e) { throw new ValueGenerationException(LOCALISER_RDBMS.msg("061001", e.getMessage())); } }
/** * Utility to create the datastore identity column and mapping. This is used in 2 modes. The first * is where we have a (primary) class table and we aren't creating the OID mapping as a FK to * another class. The second is where we have a (secondary) class table and we are creating the * OID mapping as a FK to the primary class. In the second case the refTable will be specified. * * @param columnMetaData The column MetaData for the datastore id * @param refTable Table used as a reference (if any) * @param cmd The MetaData for the class */ void addDatastoreId( ColumnMetaData columnMetaData, DatastoreClass refTable, AbstractClassMetaData cmd) { // Create the mapping, setting its table datastoreIDMapping = new DatastoreIdMapping(); datastoreIDMapping.setTable(this); datastoreIDMapping.initialize(storeMgr, cmd.getFullClassName()); // Create a ColumnMetaData in the container if none is defined ColumnMetaData colmd = null; if (columnMetaData == null) { colmd = new ColumnMetaData(); } else { colmd = columnMetaData; } if (colmd.getName() == null) { // Provide default column naming if none is defined if (refTable != null) { colmd.setName( storeMgr .getIdentifierFactory() .newColumnIdentifier( refTable.getIdentifier().getName(), this.storeMgr .getNucleusContext() .getTypeManager() .isDefaultEmbeddedType(DatastoreId.class), FieldRole.ROLE_OWNER, false) .getName()); } else { colmd.setName( storeMgr .getIdentifierFactory() .newColumnIdentifier( identifier.getName(), this.storeMgr .getNucleusContext() .getTypeManager() .isDefaultEmbeddedType(DatastoreId.class), FieldRole.ROLE_NONE, false) .getName()); } } // Add the datastore identity column as the PK Column idColumn = addColumn( DatastoreId.class.getName(), storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colmd.getName()), datastoreIDMapping, colmd); idColumn.setPrimaryKey(); // Set the identity column type based on the IdentityStrategy String strategyName = cmd.getIdentityMetaData().getValueStrategy().toString(); if (cmd.getIdentityMetaData().getValueStrategy().equals(IdentityStrategy.CUSTOM)) { strategyName = cmd.getIdentityMetaData().getValueStrategy().getCustomName(); } if (strategyName != null && IdentityStrategy.NATIVE.toString().equals(strategyName)) { strategyName = storeMgr.getStrategyForNative(cmd, -1); } // Check the value generator type being stored Class valueGeneratedType = Long.class; if (strategyName != null && IdentityStrategy.IDENTITY.toString().equals(strategyName)) { valueGeneratedType = dba.getAutoIncrementJavaTypeForType(valueGeneratedType); if (valueGeneratedType != Long.class) { NucleusLogger.DATASTORE_SCHEMA.debug( "Class " + cmd.getFullClassName() + " uses IDENTITY strategy and rather than using BIGINT " + " for the column type, using " + valueGeneratedType.getName() + " since the datastore requires that"); } } try { // Create generator so we can find the generated type // a). Try as unique generator first AbstractGenerator generator = (AbstractGenerator) storeMgr .getNucleusContext() .getPluginManager() .createExecutableExtension( "org.datanucleus.store_valuegenerator", new String[] {"name", "unique"}, new String[] {strategyName, "true"}, "class-name", new Class[] {String.class, Properties.class}, new Object[] {null, null}); if (generator == null) { // b). Try as datastore-specific generator generator = (AbstractGenerator) storeMgr .getNucleusContext() .getPluginManager() .createExecutableExtension( "org.datanucleus.store_valuegenerator", new String[] {"name", "datastore"}, new String[] {strategyName, storeMgr.getStoreManagerKey()}, "class-name", new Class[] {String.class, Properties.class}, new Object[] {null, null}); } try { if (generator != null) { ParameterizedType parameterizedType = (ParameterizedType) generator.getClass().getGenericSuperclass(); valueGeneratedType = (Class) parameterizedType.getActualTypeArguments()[0]; if (valueGeneratedType == null) { // Use getStorageClass method if available valueGeneratedType = (Class) generator.getClass().getMethod("getStorageClass").invoke(null); } } } catch (Exception e) { } } catch (Exception e) { NucleusLogger.VALUEGENERATION.warn( "Error obtaining generator for strategy=" + strategyName, e); } storeMgr .getMappingManager() .createDatastoreMapping(datastoreIDMapping, idColumn, valueGeneratedType.getName()); logMapping("DATASTORE_ID", datastoreIDMapping); // Handle any auto-increment requirement if (isObjectIdDatastoreAttributed()) { if (this instanceof DatastoreClass && ((DatastoreClass) this).isBaseDatastoreClass()) { // Only the base class can be autoincremented idColumn.setIdentity(true); } } // Check if auto-increment and that it is supported by this RDBMS if (idColumn.isIdentity() && !dba.supportsOption(DatastoreAdapter.IDENTITY_COLUMNS)) { throw new NucleusException( Localiser.msg("057020", cmd.getFullClassName(), "datastore-identity")) .setFatal(); } }