Итак, у меня есть база данных simpleDB, которая является многопользовательским сервером транзакционных баз данных, написанным на Java, который взаимодействует с клиентскими программами Java через JDBC.Проблема в том, что моя функция сброса в моем файловом менеджере, которая в основном записывает данные в блок, имеет ненужные вызовы, поэтому мне нужен флаг, который в основном проверяет, была ли страница изменена, но не сброшена на диск, затем сбросьте ее, в противном случае игнорируйте,Моя проблема в том, что я запутался, если страница на самом деле была изменена более чем одним методом?
У меня есть переменная wasModified, чтобы проверить это.Очевидное место для меня - функция appendval (), потому что страница явно изменяется.Но, видимо, есть и другие места, где страница меняется, и я не могу понять, где.
public class LogMgr implements Iterable<BasicLogRecord> {
/**
* The location where the pointer to the last integer in the page is.
* A value of 0 means that the pointer is the first value in the page.
*/
public static final int LAST_POS = 0;
private String logfile;
private Page mypage = new Page();
private Block currentblk;
private int currentpos;
private int increment = 0;
private boolean wasModified = false;
/**
* Creates the manager for the specified log file.
* If the log file does not yet exist, it is created
* with an empty first block.
* This constructor depends on a {@link FileMgr} object
* that it gets from the method
* {@link simpledb.server.SimpleDB#fileMgr()}.
* That object is created during system initialization.
* Thus this constructor cannot be called until
* {@link simpledb.server.SimpleDB#initFileMgr(String)}
* is called first.
* @param logfile the name of the log file
*/
public LogMgr(String logfile) {
this.logfile = logfile;
int logsize = SimpleDB.fileMgr().size(logfile);
if (logsize == 0)
appendNewBlock();
else {
currentblk = new Block(logfile, logsize-1);
mypage.read(currentblk);
currentpos = getLastRecordPosition() + INT_SIZE;
}
}
/**
* Ensures that the log records corresponding to the
* specified LSN has been written to disk.
* All earlier log records will also be written to disk.
* @param lsn the LSN of a log record
*/
public void flush(int lsn) {
if (lsn >= currentLSN()) {
flush();
}
}
/**
* Returns an iterator for the log records,
* which will be returned in reverse order starting with the most recent.
* @see java.lang.Iterable#iterator()
*/
public synchronized Iterator<BasicLogRecord> iterator() {
flush();
return new LogIterator(currentblk);
}
/**
* Appends a log record to the file.
* The record contains an arbitrary array of strings and integers.
* The method also writes an integer to the end of each log record whose value
* is the offset of the corresponding integer for the previous log record.
* These integers allow log records to be read in reverse order.
* @param rec the list of values
* @return the LSN of the final value
*/
public synchronized int append(Object[] rec) {
int recsize = INT_SIZE; // 4 bytes for the integer that points to the previous log record
for (Object obj : rec)
recsize += size(obj);
if (currentpos + recsize >= BLOCK_SIZE){ // the log record doesn't fit,
flush(); // so move to the next block.
appendNewBlock();
}
for (Object obj : rec)
appendVal(obj);
finalizeRecord();
//int lsn = currentLSN() + (++increment);
int lsn = currentLSN() ;
return lsn;
}
/**
* Adds the specified value to the page at the position denoted by
* currentpos. Then increments currentpos by the size of the value.
* @param val the integer or string to be added to the page
*/
private void appendVal(Object val) {
if (val instanceof String) {
mypage.setString(currentpos, (String)val);
wasModified = true;
}
else {
mypage.setInt(currentpos, (Integer)val);
wasModified = true;
}
currentpos += size(val);
}
/**
* Calculates the size of the specified integer or string.
* @param val the value
* @return the size of the value, in bytes
*/
private int size(Object val) {
if (val instanceof String) {
String sval = (String) val;
return STR_SIZE(sval.length());
}
else
return INT_SIZE;
}
/**
* Returns the LSN of the most recent log record.
* As implemented, the LSN is the block number where the record is stored.
* Thus every log record in a block has the same LSN.
* @return the LSN of the most recent log record
*/
private int currentLSN() {
return currentblk.number();
}
/**
* Writes the current page to the log file.
*/
private void flush() {
if(wasModified) {
mypage.write(currentblk);
wasModified = false;
}
}
/**
* Clear the current page, and append it to the log file.
*/
private void appendNewBlock() {
wasModified = true;
setLastRecordPosition(0);
currentpos = INT_SIZE;
currentblk = mypage.append(logfile);
}
/**
* Sets up a circular chain of pointers to the records in the page.
* There is an integer added to the end of each log record
* whose value is the offset of the previous log record.
* The first four bytes of the page contain an integer whose value
* is the offset of the integer for the last log record in the page.
*/
private void finalizeRecord() {
mypage.setInt(currentpos, getLastRecordPosition());
setLastRecordPosition(currentpos);
currentpos += INT_SIZE;
}
private int getLastRecordPosition() {
return mypage.getInt(LAST_POS);
}
private void setLastRecordPosition(int pos) {
mypage.setInt(LAST_POS, pos);
}
}