@ -1,63 +1,147 @@
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Persistence manager using the Singleton pattern.
|
||||
*/
|
||||
public class PersistenceManager
|
||||
{
|
||||
public class PersistenceManager {
|
||||
private final static PersistenceManager instance;
|
||||
private Hashtable<Integer, String> _pageBuffer;
|
||||
private Hashtable<Integer, Set<Integer>> _transactionPageBuffer;
|
||||
private Hashtable<Integer, Boolean> _transactions;
|
||||
private Hashtable<Integer, Integer> _pageLSN;
|
||||
private int _nextTransactionNumber;
|
||||
private int _nextLogSequenceNumber;
|
||||
|
||||
static {
|
||||
try {
|
||||
instance = new PersistenceManager();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the persistence manager.
|
||||
*
|
||||
* @return instance
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public static PersistenceManager getInstance()
|
||||
{
|
||||
public static PersistenceManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* private constructor
|
||||
*/
|
||||
private PersistenceManager()
|
||||
{}
|
||||
private PersistenceManager() {
|
||||
_pageBuffer = new Hashtable<>();
|
||||
_transactionPageBuffer = new Hashtable<>();
|
||||
_transactions = new Hashtable<>();
|
||||
_pageLSN = new Hashtable<>();
|
||||
_nextTransactionNumber = 1;
|
||||
_nextLogSequenceNumber = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins the transaction and returns the transaction ID.
|
||||
*
|
||||
* @return transaction ID
|
||||
*/
|
||||
public int beginTransaction()
|
||||
{
|
||||
return 0;
|
||||
public int beginTransaction() {
|
||||
_transactions.put(_nextTransactionNumber, false);
|
||||
// return the next transaction number and increase it by one afterwards
|
||||
return _nextTransactionNumber++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits the transaction specified by given ID.
|
||||
* @param taid transaction ID
|
||||
*
|
||||
* @param taid
|
||||
* transaction ID
|
||||
*/
|
||||
public void commit(int taid)
|
||||
{
|
||||
|
||||
public void commit(int taid) {
|
||||
if (!_transactions.containsKey(taid)) {
|
||||
throw new IllegalArgumentException("No transaction with given ID exists.");
|
||||
}
|
||||
// only perform commit actions if transaction isn't commited yet
|
||||
if (!_transactions.get(taid)) {
|
||||
_transactions.replace(taid, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes given data into given page in given transaction.
|
||||
* @param taid transaction ID
|
||||
* @param pageid page ID
|
||||
* @param data data
|
||||
*
|
||||
* @param taid
|
||||
* transaction ID
|
||||
* @param pageid
|
||||
* page ID
|
||||
* @param data
|
||||
* data
|
||||
*/
|
||||
public void write(int taid, int pageid, String data)
|
||||
{
|
||||
public void write(int taid, int pageid, String data) {
|
||||
if (!_transactions.containsKey(taid)) {
|
||||
throw new IllegalArgumentException("No transaction with given ID exists.");
|
||||
}
|
||||
if (_transactions.get(taid)) {
|
||||
throw new IllegalArgumentException("Write operations cannot be performed for committed transactions.");
|
||||
}
|
||||
Set<Integer> pageIDs = _transactionPageBuffer.getOrDefault(taid, new HashSet<>());
|
||||
pageIDs.add(pageid);
|
||||
_transactionPageBuffer.put(taid, pageIDs);
|
||||
_pageBuffer.put(pageid, data);
|
||||
// log changes
|
||||
int lsn = log(taid, pageid, data);
|
||||
_pageLSN.put(pageid, lsn);
|
||||
// call persist
|
||||
persist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the necessary information to the log file.
|
||||
*
|
||||
* @param taid
|
||||
* affected transaction
|
||||
* @param pageid
|
||||
* modified page
|
||||
* @param data
|
||||
* written data
|
||||
* @return log sequence number
|
||||
*/
|
||||
private int log(int taid, int pageid, String data) {
|
||||
return _nextLogSequenceNumber++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for full buffer and persists data of committed transactions to storage if buffer is full.
|
||||
*/
|
||||
private void persist() {
|
||||
if (_pageBuffer.size() <= 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO persist the data of committed transactions
|
||||
Enumeration<Integer> transactionIDs = _transactions.keys();
|
||||
List<Integer> commitedTransactions = new ArrayList<>();
|
||||
while (transactionIDs.hasMoreElements()) {
|
||||
Integer taid = transactionIDs.nextElement();
|
||||
boolean committed = _transactions.get(taid);
|
||||
if (committed) {
|
||||
commitedTransactions.add(taid);
|
||||
}
|
||||
}
|
||||
|
||||
for (int taid : commitedTransactions) {
|
||||
// TODO persist data of committed transaction
|
||||
Set<Integer> pageIDs = _transactionPageBuffer.get(taid);
|
||||
for (int pageid : pageIDs) {
|
||||
// TODO persist data of pageID
|
||||
_pageBuffer.remove(pageid);
|
||||
}
|
||||
_transactionPageBuffer.remove(taid);
|
||||
_transactions.remove(taid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user