minor database API change

This commit is contained in:
Eyck Jentzsch 2021-01-14 23:13:11 +01:00
parent 26e8ea8a51
commit 0372e03abb
16 changed files with 206 additions and 199 deletions

View File

@ -11,6 +11,8 @@
package com.minres.scviewer.database.sqlite; package com.minres.scviewer.database.sqlite;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -46,7 +48,7 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
} }
@Override @Override
public int getWidth() { public int getRowCount() {
if(maxConcurrency==null){ if(maxConcurrency==null){
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("SELECT MAX(concurrencyLevel) as concurrencyLevel FROM ScvTx where stream="); sb.append("SELECT MAX(concurrencyLevel) as concurrencyLevel FROM ScvTx where stream=");
@ -126,4 +128,11 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
return WaveformType.TRANSACTION; return WaveformType.TRANSACTION;
} }
/**
* Calculate concurrency.
*/
public void calculateConcurrency() {
}
} }

View File

@ -99,7 +99,6 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
@Override @Override
public void load(IWaveformDb db, File file) throws InputFormatException { public void load(IWaveformDb db, File file) throws InputFormatException {
dispose();
database=new SQLiteDatabase(file.getAbsolutePath(), db); database=new SQLiteDatabase(file.getAbsolutePath(), db);
database.setData("TIMERESOLUTION", 1L); database.setData("TIMERESOLUTION", 1L);
SQLiteDatabaseSelectHandler<ScvSimProps> handler = new SQLiteDatabaseSelectHandler<>(ScvSimProps.class, database); SQLiteDatabaseSelectHandler<ScvSimProps> handler = new SQLiteDatabaseSelectHandler<>(ScvSimProps.class, database);

View File

@ -65,8 +65,7 @@ public class Tx implements ITx {
return trGenerator; return trGenerator;
} }
@Override int getConcurrencyIndex() {
public int getConcurrencyIndex() {
return scvTx.getConcurrencyLevel(); return scvTx.getConcurrencyLevel();
} }

View File

@ -56,4 +56,10 @@ public class TxEvent implements ITxEvent {
public WaveformType getType() { public WaveformType getType() {
return WaveformType.TRANSACTION; return WaveformType.TRANSACTION;
} }
@Override
public int getRowIndex() {
return ((Tx)tx).getConcurrencyIndex();
}
} }

View File

@ -13,6 +13,7 @@ package com.minres.scviewer.database.text;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.NavigableMap; import java.util.NavigableMap;
import java.util.TreeMap; import java.util.TreeMap;
@ -22,6 +23,7 @@ import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.WaveformType; import com.minres.scviewer.database.WaveformType;
import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxEvent; import com.minres.scviewer.database.tx.ITxEvent;
/** /**
@ -38,6 +40,9 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
/** The events. */ /** The events. */
TreeMap<Long, IEvent[]> events = new TreeMap<>(); TreeMap<Long, IEvent[]> events = new TreeMap<>();
/** The max concurrency. */
private int maxConcurrency = 0;
/** The concurrency calculated. */ /** The concurrency calculated. */
boolean concurrencyCalculated = false; boolean concurrencyCalculated = false;
@ -48,7 +53,7 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
* @param id the id * @param id the id
* @param name the name * @param name the name
*/ */
public AbstractTxStream(TextDbLoader loader, Long id, String name) { protected AbstractTxStream(TextDbLoader loader, Long id, String name) {
super(name); super(name);
this.loader = loader; this.loader = loader;
this.id = id; this.id = id;
@ -77,8 +82,6 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
*/ */
@Override @Override
public NavigableMap<Long, IEvent[]> getEvents() { public NavigableMap<Long, IEvent[]> getEvents() {
if (!concurrencyCalculated)
calculateConcurrency();
return events; return events;
} }
@ -90,8 +93,6 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
*/ */
@Override @Override
public IEvent[] getEventsAtTime(Long time) { public IEvent[] getEventsAtTime(Long time) {
if (!concurrencyCalculated)
calculateConcurrency();
return events.get(time); return events.get(time);
} }
@ -103,8 +104,6 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
*/ */
@Override @Override
public IEvent[] getEventsBeforeTime(Long time) { public IEvent[] getEventsBeforeTime(Long time) {
if (!concurrencyCalculated)
calculateConcurrency();
Entry<Long, IEvent[]> e = events.floorEntry(time); Entry<Long, IEvent[]> e = events.floorEntry(time);
if (e == null) if (e == null)
return new IEvent[] {}; return new IEvent[] {};
@ -132,28 +131,60 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
return id; return id;
} }
/**
* Gets the width.
*
* @return the width
*/
@Override
public int getRowCount() {
if (!concurrencyCalculated)
calculateConcurrency();
return maxConcurrency;
}
/** /**
* Calculate concurrency. * Calculate concurrency.
*/ */
synchronized void calculateConcurrency() { public void calculateConcurrency() {
if (concurrencyCalculated) if (concurrencyCalculated)
return; return;
ArrayList<Long> rowendtime = new ArrayList<>(); ArrayList<Long> rowEndTime = new ArrayList<>();
HashMap<Long, Integer> rowByTxId = new HashMap<>();
events.entrySet().stream().forEach(entry -> { events.entrySet().stream().forEach(entry -> {
IEvent[] values = entry.getValue(); Arrays.asList(entry.getValue()).stream().forEach(evt -> {
Arrays.asList(values).stream().filter(e -> e.getKind() == EventKind.BEGIN).forEach(evt -> { TxEvent txEvt = (TxEvent) evt;
Tx tx = (Tx) ((TxEvent) evt).getTransaction(); ITx tx = txEvt.getTransaction();
int rowIdx = 0; int rowIdx = 0;
for (; rowIdx < rowendtime.size() && rowendtime.get(rowIdx) > tx.getBeginTime(); rowIdx++) switch(evt.getKind()) {
; case END:
if (rowendtime.size() <= rowIdx) Long txId = txEvt.getTransaction().getId();
rowendtime.add(tx.getEndTime()); txEvt.setConcurrencyIndex(rowByTxId.get(txId));
else rowByTxId.remove(txId);
rowendtime.set(rowIdx, tx.getEndTime()); break;
tx.setConcurrencyIndex(rowIdx); case SINGLE:
for (; rowIdx < rowEndTime.size() && rowEndTime.get(rowIdx) > tx.getBeginTime(); rowIdx++);
if (rowEndTime.size() <= rowIdx)
rowEndTime.add(tx.getEndTime());
else
rowEndTime.set(rowIdx, tx.getEndTime());
((TxEvent) evt).setConcurrencyIndex(rowIdx);
break;
case BEGIN:
for (; rowIdx < rowEndTime.size() && rowEndTime.get(rowIdx) > tx.getBeginTime(); rowIdx++);
if (rowEndTime.size() <= rowIdx)
rowEndTime.add(tx.getEndTime());
else
rowEndTime.set(rowIdx, tx.getEndTime());
((TxEvent) evt).setConcurrencyIndex(rowIdx);
rowByTxId.put(tx.getId(), rowIdx);
break;
}
}); });
}); });
maxConcurrency=rowEndTime.size();
concurrencyCalculated = true; concurrencyCalculated = true;
getChildNodes().parallelStream().forEach(c -> ((TxGenerator)c).calculateConcurrency());
} }
} }

View File

@ -28,14 +28,15 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import org.eclipse.collections.impl.map.mutable.UnifiedMap; import org.eclipse.collections.impl.map.mutable.UnifiedMap;
import org.mapdb.DB; import org.mapdb.DB;
import org.mapdb.DB.HashMapMaker;
import org.mapdb.DB.TreeMapSink;
import org.mapdb.DBMaker; import org.mapdb.DBMaker;
import org.mapdb.HTreeMap; import org.mapdb.HTreeMap;
import org.mapdb.Serializer; import org.mapdb.Serializer;
@ -106,6 +107,26 @@ public class TextDbLoader implements IWaveformDbLoader {
/** The Constant x. */ /** The Constant x. */
static final byte[] x = "scv_tr_stream".getBytes(); static final byte[] x = "scv_tr_stream".getBytes();
/**
* Adds the property change listener.
*
* @param l the l
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
/**
* Removes the property change listener.
*
* @param l the l
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
/** /**
* Gets the max time. * Gets the max time.
* *
@ -116,8 +137,30 @@ public class TextDbLoader implements IWaveformDbLoader {
return maxTime; return maxTime;
} }
/**
* Gets the transaction.
*
* @param txId the tx id
* @return the transaction
*/
public ITx getTransaction(long txId) {
if (txCache.containsKey(txId))
return txCache.get(txId);
if(transactions.containsKey(txId)) {
Tx tx = new Tx(this, txId);
txCache.put(txId, tx);
return tx;
} else {
Set<Long> keys = new TreeSet<>(transactions.keySet());
throw new IllegalArgumentException();
}
}
public ScvTx getScvTx(long id) { public ScvTx getScvTx(long id) {
return transactions.get(id); if(transactions.containsKey(id))
return transactions.get(id);
else
throw new IllegalArgumentException();
} }
/** /**
@ -130,6 +173,15 @@ public class TextDbLoader implements IWaveformDbLoader {
return new ArrayList<>(txStreams.values()); return new ArrayList<>(txStreams.values());
} }
/**
* Gets the all relation types.
*
* @return the all relation types
*/
public Collection<RelationType> getAllRelationTypes() {
return relationTypes.values();
}
/** /**
* Can load. * Can load.
* *
@ -156,6 +208,22 @@ public class TextDbLoader implements IWaveformDbLoader {
return false; return false;
} }
/**
* Checks if is gzipped.
*
* @param f the f
* @return true, if is gzipped
*/
private static boolean isGzipped(File f) {
try (InputStream is = new FileInputStream(f)) {
byte[] signature = new byte[2];
int nread = is.read(signature); // read the gzip signature
return nread == 2 && signature[0] == (byte) 0x1f && signature[1] == (byte) 0x8b;
} catch (IOException e) {
return false;
}
}
/** /**
* Load. * Load.
* *
@ -197,19 +265,7 @@ public class TextDbLoader implements IWaveformDbLoader {
} catch (Exception e) { } catch (Exception e) {
throw new InputFormatException(e.toString()); throw new InputFormatException(e.toString());
} }
for (TxStream stream : txStreams.values()) { txStreams.values().parallelStream().forEach(TxStream::calculateConcurrency);
Thread t = new Thread() {
@Override
public void run() {
try {
stream.calculateConcurrency();
} catch (Exception e) {
/* don't let exceptions bubble up */ }
}
};
threads.add(t);
t.start();
}
} }
/** /**
@ -231,31 +287,6 @@ public class TextDbLoader implements IWaveformDbLoader {
} }
} }
/**
* Checks if is gzipped.
*
* @param f the f
* @return true, if is gzipped
*/
private static boolean isGzipped(File f) {
try (InputStream is = new FileInputStream(f)) {
byte[] signature = new byte[2];
int nread = is.read(signature); // read the gzip signature
return nread == 2 && signature[0] == (byte) 0x1f && signature[1] == (byte) 0x8b;
} catch (IOException e) {
return false;
}
}
/**
* Gets the all relation types.
*
* @return the all relation types
*/
public Collection<RelationType> getAllRelationTypes() {
return relationTypes.values();
}
/** /**
* The Class TextDbParser. * The Class TextDbParser.
*/ */
@ -321,6 +352,11 @@ public class TextDbLoader implements IWaveformDbLoader {
} }
if (curLine != null) if (curLine != null)
parseLine(curLine, nextLine); parseLine(curLine, nextLine);
for(Entry<Long, ScvTx> e: transactionById.entrySet()) {
ScvTx scvTx = e.getValue();
scvTx.endTime=loader.maxTime;
txSink.put(e.getKey(), scvTx);
}
} }
/** /**
@ -368,8 +404,6 @@ public class TextDbLoader implements IWaveformDbLoader {
ScvTx scvTx = new ScvTx(id, gen.stream.getId(), genId, ScvTx scvTx = new ScvTx(id, gen.stream.getId(), genId,
Long.parseLong(tokens[3]) * stringToScale(tokens[4])); Long.parseLong(tokens[3]) * stringToScale(tokens[4]));
loader.maxTime = loader.maxTime > scvTx.beginTime ? loader.maxTime : scvTx.beginTime; loader.maxTime = loader.maxTime > scvTx.beginTime ? loader.maxTime : scvTx.beginTime;
TxStream stream = loader.txStreams.get(gen.stream.getId());
stream.setConcurrency(stream.getConcurrency() + 1);
if (nextLine != null && nextLine.charAt(0) == 'a') { if (nextLine != null && nextLine.charAt(0) == 'a') {
int idx = 0; int idx = 0;
while (nextLine != null && nextLine.charAt(0) == 'a') { while (nextLine != null && nextLine.charAt(0) == 'a') {
@ -402,7 +436,6 @@ public class TextDbLoader implements IWaveformDbLoader {
stream.addEvent(endEvt); stream.addEvent(endEvt);
gen.addEvent(endEvt); gen.addEvent(endEvt);
} }
stream.setConcurrency(stream.getConcurrency() - 1);
if (nextLine != null && nextLine.charAt(0) == 'a') { if (nextLine != null && nextLine.charAt(0) == 'a') {
int idx = 0; int idx = 0;
while (nextLine != null && nextLine.charAt(0) == 'a') { while (nextLine != null && nextLine.charAt(0) == 'a') {
@ -521,38 +554,4 @@ public class TextDbLoader implements IWaveformDbLoader {
} }
/**
* Gets the transaction.
*
* @param txId the tx id
* @return the transaction
*/
public ITx getTransaction(long txId) {
if (txCache.containsKey(txId))
return txCache.get(txId);
Tx tx = new Tx(this, txId);
txCache.put(txId, tx);
return tx;
}
/**
* Adds the property change listener.
*
* @param l the l
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
/**
* Removes the property change listener.
*
* @param l the l
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
} }

View File

@ -31,7 +31,7 @@ class Tx implements ITx {
private final TextDbLoader loader; private final TextDbLoader loader;
/** The id. */ /** The id. */
private long id; private final long id;
/** The begin time. */ /** The begin time. */
long beginTime = -1; long beginTime = -1;
@ -39,9 +39,6 @@ class Tx implements ITx {
/** The end time. */ /** The end time. */
long endTime = -1; long endTime = -1;
/** The concurrency index. */
private int concurrencyIndex;
/** /**
* Instantiates a new tx. * Instantiates a new tx.
* *
@ -51,6 +48,8 @@ class Tx implements ITx {
public Tx(TextDbLoader loader, ScvTx scvTx) { public Tx(TextDbLoader loader, ScvTx scvTx) {
this.loader = loader; this.loader = loader;
id = scvTx.id; id = scvTx.id;
beginTime=scvTx.beginTime;
endTime=scvTx.endTime;
} }
/** /**
@ -113,7 +112,7 @@ class Tx implements ITx {
return true; return true;
if (obj == null || getClass() != obj.getClass()) if (obj == null || getClass() != obj.getClass())
return false; return false;
return this.loader.getScvTx(id).equals(((Tx) obj).loader.getScvTx(id)); return this.getScvTx().equals(((Tx) obj).getScvTx());
} }
/** /**
@ -123,7 +122,7 @@ class Tx implements ITx {
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
return loader.getScvTx(id).hashCode(); return getScvTx().hashCode();
} }
/** /**
@ -143,7 +142,7 @@ class Tx implements ITx {
*/ */
@Override @Override
public Long getId() { public Long getId() {
return loader.getScvTx(id).id; return getScvTx().id;
} }
/** /**
@ -153,7 +152,7 @@ class Tx implements ITx {
*/ */
@Override @Override
public IWaveform getStream() { public IWaveform getStream() {
return loader.txStreams.get(loader.getScvTx(id).streamId); return loader.txStreams.get(getScvTx().streamId);
} }
/** /**
@ -163,7 +162,7 @@ class Tx implements ITx {
*/ */
@Override @Override
public ITxGenerator getGenerator() { public ITxGenerator getGenerator() {
return loader.txGenerators.get(loader.getScvTx(id).generatorId); return loader.txGenerators.get(getScvTx().generatorId);
} }
/** /**
@ -174,7 +173,7 @@ class Tx implements ITx {
@Override @Override
public Long getBeginTime() { public Long getBeginTime() {
if (beginTime < 0) if (beginTime < 0)
beginTime = loader.getScvTx(id).beginTime; beginTime = getScvTx().beginTime;
return beginTime; return beginTime;
} }
@ -186,7 +185,7 @@ class Tx implements ITx {
@Override @Override
public Long getEndTime() { public Long getEndTime() {
if (endTime < 0) if (endTime < 0)
endTime = loader.getScvTx(id).endTime; endTime = getScvTx().endTime;
return endTime; return endTime;
} }
@ -196,26 +195,7 @@ class Tx implements ITx {
* @param time the new end time * @param time the new end time
*/ */
void setEndTime(Long time) { void setEndTime(Long time) {
loader.getScvTx(id).endTime = time; getScvTx().endTime = time;
}
/**
* Gets the concurrency index.
*
* @return the concurrency index
*/
@Override
public int getConcurrencyIndex() {
return concurrencyIndex;
}
/**
* Sets the concurrency index.
*
* @param idx the new concurrency index
*/
void setConcurrencyIndex(int idx) {
concurrencyIndex = idx;
} }
/** /**
@ -225,7 +205,11 @@ class Tx implements ITx {
*/ */
@Override @Override
public List<ITxAttribute> getAttributes() { public List<ITxAttribute> getAttributes() {
return loader.getScvTx(id).attributes; return getScvTx().attributes;
} }
private ScvTx getScvTx() {
ScvTx scvTx=loader.getScvTx(id);
return scvTx;
}
} }

View File

@ -32,6 +32,7 @@ class TxEvent implements ITxEvent {
/** The time. */ /** The time. */
final long time; final long time;
private int concurrencyIdx=-1;
/** /**
* Instantiates a new tx event. * Instantiates a new tx event.
* *
@ -107,4 +108,13 @@ class TxEvent implements ITxEvent {
public ITx getTransaction() { public ITx getTransaction() {
return loader.getTransaction(transaction); return loader.getTransaction(transaction);
} }
@Override
public int getRowIndex() {
return concurrencyIdx;
}
public void setConcurrencyIndex(int idx) {
concurrencyIdx=idx;
}
} }

View File

@ -100,7 +100,7 @@ class TxGenerator extends AbstractTxStream implements ITxGenerator {
* @return the width * @return the width
*/ */
@Override @Override
public int getWidth() { public int getRowCount() {
return stream.getWidth(); return stream.getRowCount();
} }
} }

View File

@ -55,40 +55,4 @@ class TxStream extends AbstractTxStream {
return kind; return kind;
} }
/** The max concurrency. */
private int maxConcurrency = 0;
/** The concurrency. */
private int concurrency = 0;
/**
* Sets the concurrency.
*
* @param concurrency the new concurrency
*/
void setConcurrency(int concurrency) {
this.concurrency = concurrency;
if (concurrency > maxConcurrency)
maxConcurrency = concurrency;
}
/**
* Gets the concurrency.
*
* @return the concurrency
*/
int getConcurrency() {
return this.concurrency;
}
/**
* Gets the width.
*
* @return the width
*/
@Override
public int getWidth() {
return maxConcurrency;
}
} }

View File

@ -204,7 +204,7 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
@Override @Override
public int getNetWidth(int intValue) { public int getNetWidth(int intValue) {
VCDSignal<?> signal = (VCDSignal<?>) signals.get(intValue); VCDSignal<?> signal = (VCDSignal<?>) signals.get(intValue);
return signal.getWidth(); return signal.getRowCount();
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@ -109,7 +109,7 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
} }
@Override @Override
public int getWidth() { public int getRowCount() {
return width; return width;
} }
@ -118,4 +118,8 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
return "signal"; return "signal";
} }
@Override
public void calculateConcurrency() {
}
} }

View File

@ -76,6 +76,7 @@ public interface IWaveform extends IHierNode {
* *
* @return the width * @return the width
*/ */
public int getWidth(); public int getRowCount();
public void calculateConcurrency();
} }

View File

@ -123,31 +123,31 @@ public class WaveformDb extends HierNode implements IWaveformDb, PropertyChangeL
*/ */
@Override @Override
public boolean load(File inp) { public boolean load(File inp) {
boolean retval = true;
for (IWaveformDbLoader loader : loaders) { for (IWaveformDbLoader loader : loaders) {
if (loader.canLoad(inp)) { if (loader.canLoad(inp)) {
loader.addPropertyChangeListener(this);
try { try {
loader.addPropertyChangeListener(this);
loader.load(this, inp); loader.load(this, inp);
loader.removePropertyChangeListener(this);
for (IWaveform w : loader.getAllWaves()) {
waveforms.put(w.getFullName(), w);
}
if (loader.getMaxTime() > maxTime) {
maxTime = loader.getMaxTime();
}
if (name == null)
name = getFileBasename(inp.getName());
buildHierarchyNodes();
relationTypes.addAll(loader.getAllRelationTypes());
pcs.firePropertyChange(IHierNode.LOADING_FINISHED, null, null);
loaded = true;
return true;
} catch (Exception e) { } catch (Exception e) {
return false; retval=false;
} }
loader.removePropertyChangeListener(this);
for (IWaveform w : loader.getAllWaves()) {
waveforms.put(w.getFullName(), w);
}
if (loader.getMaxTime() > maxTime) {
maxTime = loader.getMaxTime();
}
if (name == null)
name = getFileBasename(inp.getName());
buildHierarchyNodes();
relationTypes.addAll(loader.getAllRelationTypes());
} }
} }
return false; pcs.firePropertyChange(IHierNode.LOADING_FINISHED, null, null);
loaded = true;
return retval;
} }
/** /**

View File

@ -55,13 +55,6 @@ public interface ITx extends Comparable<ITx> {
*/ */
public Long getEndTime(); public Long getEndTime();
/**
* Gets the concurrency index.
*
* @return the concurrency index
*/
public int getConcurrencyIndex();
/** /**
* Gets the attributes. * Gets the attributes.
* *

View File

@ -30,4 +30,12 @@ public interface ITxEvent extends IEvent {
* @return the transaction * @return the transaction
*/ */
public ITx getTransaction(); public ITx getTransaction();
/**
* Gets the concurrency index.
*
* @return the concurrency index
*/
public int getRowIndex();
} }