如何确定Java中数据库页面的内容何时被更改?

如何确定Java中数据库页面的内容何时被更改?,java,database,Java,Database,所以我有一个simpleDB数据库,它是用Java编写的多用户事务数据库服务器,通过JDBC与Java客户机程序交互。问题是,我的文件管理器中的flush函数基本上是将数据写入a块的,它有不必要的调用,因此我需要一个标志,它基本上检查页面是否已被修改但未刷新到磁盘,然后刷新它,否则忽略。我的问题是,如果页面实际上是用多种方法修改的,我会感到困惑 我已经修改了一个变量来检查这一点。对我来说最明显的地方是appendval()函数,因为页面显然正在更改。但很明显,还有其他地方的页面正在被更改,我不知

所以我有一个simpleDB数据库,它是用Java编写的多用户事务数据库服务器,通过JDBC与Java客户机程序交互。问题是,我的文件管理器中的flush函数基本上是将数据写入a块的,它有不必要的调用,因此我需要一个标志,它基本上检查页面是否已被修改但未刷新到磁盘,然后刷新它,否则忽略。我的问题是,如果页面实际上是用多种方法修改的,我会感到困惑

我已经修改了一个变量来检查这一点。对我来说最明显的地方是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);
   }
}
public类LogMgr实现Iterable{
/**
*指向页面中最后一个整数的指针所在的位置。
*值为0表示指针是页面中的第一个值。
*/
公共静态最终整数最后位置=0;
私有字符串日志文件;
私有页面mypage=新页面();
私人大厦;
私人国际邮政局;
私有整数增量=0;
私有布尔值wasModified=false;
/**
*为指定的日志文件创建管理器。
*如果日志文件尚不存在,则会创建它
*第一个街区是空的。
*此构造函数依赖于{@link FileMgr}对象
*它从方法中得到的
*{@link simpledb.server.simpledb#fileMgr()}。
*该对象是在系统初始化期间创建的。
*因此,直到
*{@link simpledb.server.simpledb#initFileMgr(字符串)}
*第一个被称为。
*@param logfile日志文件的名称
*/
公共日志管理器(字符串日志文件){
this.logfile=logfile;
int logsize=SimpleDB.fileMgr().size(日志文件);
如果(logsize==0)
appendNewBlock();
否则{
currentblk=新块(日志文件,日志大小-1);
mypage.read(当前BLK);
currentpos=getLastRecordPosition()+整数大小;
}
}
/**
*确保日志记录与
*指定的LSN已写入磁盘。
*所有以前的日志记录也将写入磁盘。
*@param lsn日志记录的lsn
*/
公共无效刷新(内部lsn){
如果(lsn>=currentLSN()){
冲洗();
}
}
/**
*返回日志记录的迭代器,
*将从最新的开始以相反的顺序返回。
*@see java.lang.Iterable#iterator()
*/
公共同步迭代器迭代器(){
冲洗();
返回新的登录器(currentblk);
}
/**
*将日志记录追加到文件。
*该记录包含字符串和整数的任意数组。
*该方法还将一个整数写入其值为
*是上一个日志记录对应整数的偏移量。
*这些整数允许以相反的顺序读取日志记录。
*@param rec值列表
*@返回最终值的LSN
*/
公共同步int-append(对象[]rec){
int recsize=int_SIZE;//指向上一个日志记录的整数为4字节
用于(对象对象对象:rec)
recsize+=尺寸(obj);
如果(currentpos+recsize>=块大小){//日志记录不适合,
flush();//因此移动到下一个块。
appendNewBlock();
}
用于(对象对象对象:rec)
阑尾;
终结记录();
//int lsn=currentLSN()+(++增量);
int lsn=currentLSN();
返回lsn;
}
/**
*将指定的值添加到页面的以下位置
*currentpos。然后按值的大小递增currentpos。
*@param val要添加到页面的整数或字符串
*/
私有无效附件(对象val){
if(字符串的val instanceof){
mypage.setString(currentpos,(String)val);
wasModified=true;
}
否则{
mypage.setInt(currentpos,(整数)val);
wasModified=true;
}
currentpos+=大小(val);
}
/**
*计算指定整数或字符串的大小。
*@param val值
*@返回值的大小,以字节为单位
*/
私有整数大小(对象值){
if(字符串的val instanceof){
字符串sval=(字符串)val;
返回stru大小(sval.length());
}
其他的
返回整数大小;
}
/**
*返回最近日志记录的LSN。
*在实现时,LSN是存储记录的块号。
*因此,块中的每个日志记录都具有相同的LSN。
*@返回最近日志记录的LSN
*/
private int currentLSN(){
返回currentblk.number();
}
/**
*将当前页写入日志文件。
*/
私有空间刷新(){
如果(已修改){
mypage.write(当前BLK);
wasModified=false;
}
}
/**
*清除当前页面,并将其附加到日志文件中。
*/
私有void appendNewBlock(){
wasModified=true;
setLastRecordPosition(0);
currentpos=整数大小;
currentblk=mypage.append(日志文件);
}
/**
*设置指向页面中记录的循环指针链。
*每个日志记录的末尾都添加了一个整数
*其值是上一个日志记录的偏移量。
*页面的前四个字节包含一个值为
*是页面中最后一条日志记录的整数偏移量。
*/
私有void finalizeRecord(){
setInt(currentpos,getLastRecordPosition());
setLastRecordPosition(当前位置);
currentpos+=内部大小;
}
私有int getLastRecordPosition(){
返回mypage.getInt(最后一个位置);
}
私有无效setLastRe