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

📄 filecontainer.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
					RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT);		}		// For the following properties, do not check value set in global		// properties, we only listen to what access has to say about them.		//		// whether or not container's recordIds can be reused		// if container is to be created with a large number of pages		if (createArgs != null)		{			String reusableRecordIdParameter = 				createArgs.getProperty(RawStoreFactory.PAGE_REUSABLE_RECORD_ID);			if (reusableRecordIdParameter != null)			{					Boolean reusableRecordId = new Boolean(reusableRecordIdParameter);				setReusableRecordIdState(reusableRecordId.booleanValue());			}			String containerInitialPageParameter =				createArgs.getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES);			if (containerInitialPageParameter != null)			{				initialPages = 					Short.parseShort(containerInitialPageParameter);				if (initialPages > 1)				{					if (initialPages > RawStoreFactory.MAX_CONTAINER_INITIAL_PAGES)						initialPages = RawStoreFactory.MAX_CONTAINER_INITIAL_PAGES;				}			}		}	}	/**	*/	protected boolean canUpdate() {		return canUpdate;	}	/**		Deallocate a page from the container.  		@param handle the container handle doing the deallocation		@param page the page to be deallocated.  It is latched upon entry and		will be unlatched by the caller of this function		@exception StandardException Cloudscape Standard error policy	*/	protected void deallocatePage(BaseContainerHandle handle, BasePage page)		 throws StandardException	{		if (SanityManager.DEBUG) {			SanityManager.ASSERT(page.isLatched(), "page is not latched");			SanityManager.ASSERT(page.getPageNumber() != FIRST_ALLOC_PAGE_NUMBER, 								 "cannot deallocate an alloc page");		}		long pnum = page.getPageNumber();		// dealloc the page from the alloc page		deallocatePagenum(handle, pnum);		// mark the page as deallocated.  Page should not be touched after this		// the page latch is released by the BaseContainer upon return of this		// method.  Regardless of whether this operation is successful or not,		// the page will be unlatched by BaseContainer.		page.deallocatePage();			}	/** deallocate the page from the alloc page */	private void deallocatePagenum(BaseContainerHandle handle, long pnum)		 throws StandardException	{		synchronized(allocCache)		{			long allocPageNum = allocCache.getAllocPageNumber(handle, pnum, firstAllocPageNumber);			if (SanityManager.DEBUG)			{				if (allocPageNum == ContainerHandle.INVALID_PAGE_NUMBER)					allocCache.dumpAllocationCache();				if (allocPageNum == ContainerHandle.INVALID_PAGE_NUMBER)					SanityManager.THROWASSERT(									 "can't find alloc page for page number " +									 pnum);			}			// get the alloc page to deallocate this pnum			AllocPage allocPage = (AllocPage)handle.getAllocPage(allocPageNum);			if (allocPage == null)			{				PageKey pkey = new PageKey(identity, allocPageNum);				throw StandardException.newException(                        SQLState.FILE_NO_ALLOC_PAGE, pkey);			}			try			{				allocCache.invalidate(allocPage, allocPageNum); 				// Unlatch alloc page.  The page is protected by the dealloc				// lock. 				allocPage.deallocatePage(handle, pnum);			}			finally			{				allocPage.unlatch();			}		}		// make sure this page gets looked at when someone needs a new page		if (pnum <= lastAllocatedPage) 		{			lastAllocatedPage = pnum - 1;		}	}	/**	  Compress free space from container.	  <BR> MT - thread aware - It is assumed that our caller (our super class)	  has already arranged a logical lock on page allocation to only allow a	  single thread through here.      Compressing free space is done in allocation page units, working      it's way from the end of the container to the beginning.  Each      loop operates on the last allocation page in the container.      Freeing space in the container page involves 2 transactions, an      update to an allocation page, N data pages, and possibly the delete      of the allocation page.	  The User Transaction (UT) initiated the compress call.	  The Nested Top Transaction (NTT) is the transaction started by RawStore	  inside the compress call.  This NTT is committed before compress returns.	  The NTT is used to access high traffic data structures such as the       AllocPage.	  This is outline of the algorithm used in compressing the container.      Until a non free page is found loop, in each loop return to the OS         all space at the end of the container occupied by free pages, including         the allocation page itself if all of it's pages are free.        	  1) Find last 2 allocation pages in container (last if there is only one).	  2) invalidate the allocation information cached by the container.		 Without the cache no page can be gotten from the container.  Pages		 already in the page cache are not affected.  Thus by latching the 		 allocPage and invalidating the allocation cache, this NTT blocks out 		 all page gets from this container until it commits.	  3) the allocPage determines which pages can be released to the OS,          mark that in its data structure (the alloc extent).  Mark the          contiguous block of nallocated/free pages at the end of the file         as unallocated.  This change is associated with the NTT.      4) The NTT calls the OS to deallocate the space from the file.  Note         that the system can handle being booted and asked to get an allocated         page which is past end of file, it just extends the file automatically.	  5) If freeing all space on the alloc page, and there is more than one         alloc page, then free the alloc page - this requires an update to the          previous alloc page which the loop has kept latched also.      6) if the last alloc page was deleted, restart loop at #1      All NTT latches are released before this routine returns.	  If we use an NTT, the caller has to commit the NTT to release the	  allocPage latch.  If we don't use an NTT, the allocPage latch is released	  as this routine returns.	  @param ntt - the nested top transaction for the purpose of freeing space.						If ntt is null, use the user transaction for allocation.	  #param allocHandle - the container handle opened by the ntt, 						use this to latch the alloc page	  @exception StandardException Standard Cloudscape error policy 	*/	protected void compressContainer(    RawTransaction      ntt,    BaseContainerHandle allocHandle)		 throws StandardException 	{		AllocPage alloc_page      = null;		AllocPage prev_alloc_page = null;		if (firstAllocPageNumber == ContainerHandle.INVALID_PAGE_NUMBER)        {            // no allocation pages in container, no work to do!			return;        }        // make sure we don't execute redo recovery on any page        // which is getting truncated.  At this point we have an exclusive        // table lock on the table, so after checkpoint no page change        // can happen between checkpoint log record and compress of space.        dataFactory.getRawStoreFactory().checkpoint();		try		{            synchronized(allocCache)            {                // loop until last 2 alloc pages are reached.                alloc_page = (AllocPage)                     allocHandle.getAllocPage(firstAllocPageNumber);                while (!alloc_page.isLast())                {                    if (prev_alloc_page != null)                    {                        // there are more than 2 alloc pages, unlatch the                         // earliest one.                        prev_alloc_page.unlatch();                    }                    prev_alloc_page = alloc_page;                    alloc_page      = null;                    long nextAllocPageNumber =                         prev_alloc_page.getNextAllocPageNumber();                    long nextAllocPageOffset =                         prev_alloc_page.getNextAllocPageOffset();                    alloc_page = (AllocPage)                         allocHandle.getAllocPage(nextAllocPageNumber);                }                // invalidate cache before compress changes cached information,                // while holding synchronization on cache and latch on                 // allocation page.  This should guarantee that only new info                // is seen after this operation completes.				allocCache.invalidate();                 // reset, as pages may not exist after compress                lastUnfilledPage    = ContainerHandle.INVALID_PAGE_NUMBER;                lastAllocatedPage   = ContainerHandle.INVALID_PAGE_NUMBER;                alloc_page.compress(ntt, this);            }		}        finally        {			if (alloc_page != null)            {				alloc_page.unlatch();                alloc_page = null;            }			if (prev_alloc_page != null)            {				prev_alloc_page.unlatch();				prev_alloc_page = null;            }            // flush all changes to this file from cache.            flushAll();            // make sure all truncated pages are removed from the cache,            // as it will get confused in the future if we allocate the same            // page again, but find an existing copy of it in the cache -             // it expects to not find new pages in the cache.  Could just            // get rid of truncated pages, iterface allows one page or            // all pages.            pageCache.discard(identity);        }	}	/**	  Create a new page in the container.	  <BR> MT - thread aware - It is assumed that our caller (our super class)	  has already arranged a logical lock on page allocation to only allow a	  single thread through here.	  Adding a new page involves 2 transactions and 2 pages.  	  The User Transaction (UT) initiated the addPage call and expects a	  latched page (owns by the UT) to be returned.	  The Nested Top Transaction (NTT) is the transaction started by RawStore	  inside an addPage call.  This NTT is committed before the page is	  returned.  The NTT is used to accessed high traffic data structure such	  as the AllocPage.	  This is outline of the algorithm used in adding a page:	  1) find or make an allocPage which can handle the addding of a new page.		Latch the allocPage with the NTT.	  2) invalidate the allocation information cached by the container.		Without the cache no page can be gotten from the container.  Pages		already in the page cache is not affected.  Thus by latching the 		allocPage and invalidating the allocation cache, this NTT blocks out 		all page gets from this container until it commits.	  3) the allocPage determines which page can be allocated, mark that in its		data structure (the alloc extent) and returns the page number of the		new page.  This change is associated with the NTT.	  4) the NTT gets or creates the new page in the page cache (bypassing the		lookup of the allocPage since that is already latched by the NTT and		will deadlock).	  5) the NTT initializes the page (mark it is being a VALID page).	  6) the page latch is transfered to the UT from the NTT.	  7) the new page is returned, latched by UT	  If we use an NTT, the caller has to commit the NTT to release the	  allocPage latch.  If we don't use an NTT, the allocPage latch is released	  as this routine returns.	  @param userHandle - the container handle opened by the user transaction, 						use this to latch the new user page	  @param ntt - the nested top transaction for the purpose of allocating the new page						If ntt is null, use the user transaction for allocation.	  #param allocHandle - the container handle opened by the ntt, 						use this to latch the alloc page	  @exception StandardException Standard Cloudscape error policy 	*/	protected BasePage newPage(BaseContainerHandle userHandle,							   RawTransaction ntt,							   BaseContainerHandle allocHandle,							   boolean isOverflow) 		 throws StandardException 	{		// NOTE: we are single threaded thru this method, see MT comment		boolean useNTT = (ntt != null);		// if ntt is null, use user transaction		if (!useNTT)			ntt = userHandle.getTransaction();		long lastPage;			// last allocated page		long lastPreallocPage;	// last pre-allcated page		long pageNumber;		// the page number of the new page		PageKey pkey;			// the identity of the new page		boolean reuse;			// if true, we are trying to reuse a page		/* in case the page recommeded by allocPage is not committed yet, may		/* need to retry a couple of times */		boolean retry;		int numtries = 0;		long startSearch = lastAllocatedPage;		AllocPage allocPage = null;	// the alloc page		BasePage page = null;	// the new page		try		{			do			{				retry = false;		// we don't expect we need to retry				synchronized(allocCache)				{					if (SanityManager.DEBUG)					{						SanityManager.ASSERT(                            ntt.getId().equals(                                allocHandle.getTransaction().getId()));						if (useNTT)							SanityManager.ASSERT(                                !ntt.getId().equals(                                    userHandle.getTransaction().getId()));					}                    /* find an allocation page that can handle adding a new                      * page.                     *                     * allocPage is unlatched when the ntt commits. The new                      * page is initialized by the ntt but the latch is                      * transfered to the user transaction before the allocPage                      * is unlatched.  The allocPage latch prevents almost any                      * other reader or writer from finding the new page until                      * the ntt is committed and the new page is latched by the                     * user transaction.                     *                     * (If the page is being reused, it is possible for another                     * xact which kept a handle on the reused page to find the                      * page during the transfer UT -> NTT. If this unlikely                      * even occurs and the transfer fails [see code relating                      * to transfer below], we retry from the beginning.)                     *                     * After the NTT commits a reader (getNextPageNumber) may                      * get the page number of the newly allocated page and it                      * will wait for the new page and latch it when the user                      * transaction commits, aborts or unlatches the new page.                      * Whether the user transaction commits or aborts, the new                      * page stay allocated.                     *                     * RESOLVE: before NTT rolls back (or commits) the latch is                     * released.  To repopulate the allocation cache, need to                      * get either the container lock on add page, or get a per                      * allocation page lock.                     *

⌨️ 快捷键说明

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