⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 table.java

📁 java 数据库 功能强大 效率高 SmallSQL Database is a free DBMS library for the Java(tm) platform. It runs on
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
    final long getFirstPage(){
        return firstPage;
    }


    /**
     * Return a list of Links to not commited rows. The list include only the rows that are visible for 
     * the current isolation level.
     */
    List getInserts(SSConnection con){
		synchronized(locks){
			ArrayList inserts = new ArrayList();
			if(con.isolationLevel <= Connection.TRANSACTION_READ_UNCOMMITTED){
				for(int i=0; i<locksInsert.size(); i++){
					TableStorePageInsert lock = (TableStorePageInsert)locksInsert.get(i);
					inserts.add(lock.getLink());
				}
			}else{
				for(int i=0; i<locksInsert.size(); i++){
					TableStorePageInsert lock = (TableStorePageInsert)locksInsert.get(i);
					if(lock.con == con)
						inserts.add(lock.getLink());
				}
			}
			return inserts;
		}    	
    }
    
    
    /**
     * Request a page lock. If the request is valid then it return the StorePage. 
     * If the lock can not be created within 5 seconds then it throw an exception.
     * @param con The connection that request the lock
     * @param pageOperation The operation that should be perform
     * @param page The offset of the page
     * @return a valid StorePage
     * @throws Exception if a timeout occurs
     */
    final TableStorePage requestLock(SSConnection con, int pageOperation, long page) throws Exception{
    	synchronized(locks){
            if(raFile == null){
                throw Utils.createSQLException("Table '" + name + "' was modified.");
            }
			long endTime = 0;
			while(true){
				TableStorePage storePage = requestLockImpl( con, pageOperation, page);
				if(storePage != null) 
					return storePage; // the normal case should be the fasted
				if(endTime == 0)
					endTime = System.currentTimeMillis() + 5000;
				long waitTime = endTime - System.currentTimeMillis();
				if(waitTime <= 0)
					throw Utils.createSQLException("Deadlock, can not create a lock on table '"+name+"'");
				locks.wait(waitTime);
			}
    	}
    }
    
    /**
     * Request a page lock. If the request is valid then it return the StorePage. 
     * In the other case it return null.
     * @param page The fileOffset or -1 for a new page
     * @throws SQLException 
     */
	final private TableStorePage requestLockImpl(SSConnection con, int pageOperation, long page) throws SQLException{
		synchronized(locks){
			if(tabLockConnection != null && tabLockConnection != con) return null;
			switch(con.isolationLevel){
				case Connection.TRANSACTION_SERIALIZABLE:
					serializeConnections.put( con, con);
					break;
			}
		
			switch(pageOperation){
				case SQLTokenizer.CREATE:{
						// first check if another connection has a lock before creating a table lock
						if(locks.size() > 0){
							Iterator values = locks.values().iterator();
							while(values.hasNext()){
								TableStorePage lock = (TableStorePage)values.next();
								if(lock.con != con) return null;
							}
						}
						for(int i=0; i<locksInsert.size(); i++){
							//the first StorePage in the linked list must be ever TableStorePageInsert
							TableStorePageInsert lock = (TableStorePageInsert)locksInsert.get(i);
							if(lock.con != con) return null;
						}
						if(serializeConnections.size() > 0){
							Iterator values = serializeConnections.values().iterator();
							while(values.hasNext()){
								TableStorePage lock = (TableStorePage)values.next();
								if(lock.con != con) return null;
							}
						}
						tabLockConnection = con;
						tabLockCount++;
						TableStorePage lock = new TableStorePage(con, this, LOCK_TAB, page);
						con.add(lock);
						return lock;
					}
                case SQLTokenizer.ALTER:{
                    // first check if there is any lock before creating a table lock
                    if(locks.size() > 0 || locksInsert.size() > 0){
                        return null;
                    }
                    if(serializeConnections.size() > 0){
                        Iterator values = serializeConnections.values().iterator();
                        while(values.hasNext()){
                            TableStorePage lock = (TableStorePage)values.next();
                            if(lock.con != con) return null;
                        }
                    }
                    tabLockConnection = con;
                    tabLockCount++;
                    TableStorePage lock = new TableStorePage(con, this, LOCK_TAB, page);
                    lock.rollback();
                    return lock;
                }
				case SQLTokenizer.INSERT:{
						// if there are more as one Connection with a serializable lock then an INSERT is not valid
						if(serializeConnections.size() > 1) return null;
						if(serializeConnections.size() == 1 && serializeConnections.get(con) != null) return null;
						TableStorePageInsert lock = new TableStorePageInsert(con, this, LOCK_INSERT);
						locksInsert.add( lock );
						con.add(lock);
						return lock;
					}
				case SQLTokenizer.SELECT:{
						Long pageKey = new Long(page); //TODO performance
						TableStorePage lockFirst;
						TableStorePage lock = lockFirst = (TableStorePage)locks.get( pageKey );
						while(lock != null){
							if(lock.con == con || 
							   con.isolationLevel <= Connection.TRANSACTION_READ_UNCOMMITTED) return lock;
							if(lock.lockType == LOCK_WRITE) return null; // write lock of another Connection
							lock = lock.nextLock;
						}
						lock = new TableStorePage( con, this, LOCK_NONE, page);
						if(con.isolationLevel >= Connection.TRANSACTION_REPEATABLE_READ){
							lock.lockType = LOCK_READ;
							lock.nextLock = lockFirst;
							locks.put( pageKey, lock );
							con.add(lock);
						}
						return lock;							
					}
				case SQLTokenizer.LONGVARBINARY:
					// is used for written BLOB and CLOB
					// the difference to INSERT is that page descript the size of the byte buffer
					return new TableStorePage( con, this, LOCK_INSERT, -1);
				default:
					throw new Error("pageOperation:"+pageOperation);
			}
		}
	}
	
	
	/**
	 * Request a write lock for a page that is read.
	 * @throws SQLException 
	 */
	TableStorePage requestWriteLock(SSConnection con, TableStorePage readlock) throws SQLException{
		if(readlock.lockType == LOCK_INSERT){
			TableStorePage lock = new TableStorePage( con, this, LOCK_INSERT, -1);
			readlock.nextLock = lock;
			con.add(lock);
			return lock;									
		}
		Long pageKey = new Long(readlock.fileOffset); //TODO performance
		TableStorePage lockFirst;
		TableStorePage lock = lockFirst = (TableStorePage)locks.get( pageKey );
		while(lock != null){
			if(lock.con != con) return null; // there is already any lock from another connection, we can not start write
			if(lock.lockType < LOCK_WRITE){
				// if there is only a read lock we can transfer it
				// this is requied for rollback to a savepoint
				lock.lockType = LOCK_WRITE;
				return lock;
			}
			lock = lock.nextLock;
		}
		lock = new TableStorePage( con, this, LOCK_WRITE, readlock.fileOffset);
		lock.nextLock = lockFirst;
		locks.put( pageKey, lock );
		con.add(lock);
		return lock;									
	}
	
	
	/**
	 * Remove the lock from this table.
	 */
	void freeLock(TableStorePage storePage){
		final int lockType = storePage.lockType;
		final long fileOffset = storePage.fileOffset;
		synchronized(locks){
			try{
				TableStorePage lock;
				TableStorePage prev;
				switch(lockType){
					case LOCK_INSERT:
						for(int i=0; i<locksInsert.size(); i++){
							prev = lock = (TableStorePage)locksInsert.get(i);
							while(lock != null){
								if(lock == storePage){
									//remove lock
									if(lock == prev){
										if(lock.nextLock == null){
											// the first lock is the only lock in the list
											locksInsert.remove(i--);
										}else{
											// only the first lock of the list is remove
											locksInsert.set( i, lock.nextLock );
										}
									}else{
										// a lock in the mid or end is removed
										prev.nextLock = lock.nextLock;
									}
									return;
								}
								prev = lock;
								lock = lock.nextLock;
							}
						}
						break;
					case LOCK_READ:
					case LOCK_WRITE:
						Long pageKey = new Long(fileOffset); //TODO performance
						lock = (TableStorePage)locks.get( pageKey );
						prev = lock;
						while(lock != null){
							if(lock == storePage){
								//lock entfernen
								if(lock == prev){
									if(lock.nextLock == null){
										// erste und einzige Lock in Liste
										locks.remove(pageKey);
									}else{
										// erste Lock in liste f鋖lt weg
										locks.put( pageKey, lock.nextLock );
									}
								}else{
									// lock in mitte oder ende der Liste f鋖lt weg
									prev = lock.nextLock;
								}
								return;
							}
							prev = lock;
							lock = lock.nextLock;
						}
						// Durchl鋟fer kann auftreten, wenn eine Lock hochgestuft wurde und damit der type nicht stimmt
						break;
					case LOCK_TAB:
						assert storePage.con == tabLockConnection : "Internal Error with TabLock";
						if(--tabLockCount == 0) tabLockConnection = null;
						break;
					default:
						throw new Error();
				}
			}finally{
				locks.notifyAll();
			}
		}
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -