/**
* Copyright 2012 Anjuke Inc.
*
* 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 com.anjuke.romar.mahout.model;
import com.sleepycat.bind.tuple.LongBinding;
import com.sleepycat.bind.tuple.StringBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
import com.sleepycat.bind.tuple.TupleTupleKeyCreator;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Environment;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.SecondaryConfig;
import com.sleepycat.je.SecondaryDatabase;
import com.sleepycat.je.Sequence;
import com.sleepycat.je.SequenceConfig;
/**
* Implementation which stores the reverse long-to-string mapping in BerkeleyDB.
*/
public class BDBSequenceIDMigrator extends BDBIDMigrator {
/**
* @see BDBSequenceIDMigrator
*/
public BDBSequenceIDMigrator(String directory, long cacheSize) {
this(directory, cacheSize, false);
}
/**
* @see BDBIDMigrator
*/
public BDBSequenceIDMigrator(String directory, long cacheSize,
boolean transactional) {
super(directory, cacheSize, transactional);
_secondary = createSecondaryDatabase(getEnvironment(),
getPrimaryDatabase());
_sequence = createIdSequence(getPrimaryDatabase());
}
/**
*
*/
public void close() {
if (_sequence != null) {
_sequence.close();
_sequence = null;
}
if (_secondary != null) {
_secondary.close();
_secondary = null;
}
super.close();
}
@Override
protected void finalize() throws Throwable {
close();
super.finalize();
}
@Override
public long toLongID(String stringID) {
DatabaseEntry key = new DatabaseEntry();
DatabaseEntry data = new DatabaseEntry();
DatabaseEntry primaryKey = new DatabaseEntry();
StringBinding.stringToEntry(stringID, key);
OperationStatus status = _secondary.get(null, key, primaryKey, data,
LOCK_MODE);
if (OperationStatus.SUCCESS == status) {
return LongBinding.entryToLong(primaryKey);
}
long next = _sequence.get(null, 1);
LongBinding.longToEntry(next, primaryKey);
status = getPrimaryDatabase().put(null, primaryKey, key);
if (status == OperationStatus.SUCCESS) {
return next;
}
return -next;
}
//
//
//
protected SecondaryDatabase createSecondaryDatabase(Environment environment,
Database primaryDb) {
SecondaryConfig config = SecondaryConfig.DEFAULT;
config.setAllowCreate(true);
config.setTransactional(environment.getConfig().getTransactional());
config.setSortedDuplicates(false);
config.setKeyCreator(new TupleTupleKeyCreator<Long>() {
@Override
public boolean createSecondaryKey(TupleInput primaryKeyInput,
TupleInput dataInput,
TupleOutput indexKeyOutput) {
try {
indexKeyOutput.writeString(dataInput.readString());
} catch (Exception e) {
return false;
}
return true;
}
});
return environment.openSecondaryDatabase(null, "string_id_mapping",
primaryDb, config);
}
protected Sequence createIdSequence(Database db) {
SequenceConfig config = SequenceConfig.DEFAULT;
config.setAllowCreate(true);
config.setInitialValue(1);
DatabaseEntry sequenceName = new DatabaseEntry();
StringBinding.stringToEntry("id_sequence", sequenceName);
return db.openSequence(null, sequenceName, config);
}
/**
* Returns StringID -> LongID mapping database
* @return the database
*/
protected Database getSecondaryDatabase() {
return _secondary;
}
/**
* Return sequence for LongID
* @return the sequence
*/
protected Sequence getSequence() {
return _sequence;
}
//
//
//
/**
* DB: StringID -> LongID
*/
private SecondaryDatabase _secondary;
/**
* Numeric ID sequence
*/
private Sequence _sequence;
}