Example #1
0
/*
 * GetPageWithFreeSpace - try to find a page in the given relation with
 *		at least the specified amount of free space.
 *
 * If successful, return the block number; if not, return InvalidBlockNumber.
 *
 * The caller must be prepared for the possibility that the returned page
 * will turn out to have too little space available by the time the caller
 * gets a lock on it.  In that case, the caller should report the actual
 * amount of free space available on that page and then try again (see
 * RecordAndGetPageWithFreeSpace).  If InvalidBlockNumber is returned,
 * extend the relation.
 */
BlockNumber
GetPageWithFreeSpace(Relation rel, Size spaceNeeded)
{
	uint8		min_cat = fsm_space_needed_to_cat(spaceNeeded);

	return fsm_search(rel, min_cat);
}
Example #2
0
/*
 * RecordAndGetPageWithFreeSpace - update info about a page and try again.
 *
 * We provide this combo form to save some locking overhead, compared to
 * separate RecordPageWithFreeSpace + GetPageWithFreeSpace calls. There's
 * also some effort to return a page close to the old page; if there's a
 * page with enough free space on the same FSM page where the old one page
 * is located, it is preferred.
 *
 * For very small heap relations that don't have a FSM, we update the local
 * map to indicate we have tried a page, and return the next page to try.
 */
BlockNumber
RecordAndGetPageWithFreeSpace(Relation rel, BlockNumber oldPage,
							  Size oldSpaceAvail, Size spaceNeeded)
{
	int			old_cat;
	int			search_cat;
	FSMAddress	addr;
	uint16		slot;
	int			search_slot;
	BlockNumber nblocks = InvalidBlockNumber;

	/* First try the local map, if it exists. */
	if (FSM_LOCAL_MAP_EXISTS)
	{
		Assert((rel->rd_rel->relkind == RELKIND_RELATION ||
				rel->rd_rel->relkind == RELKIND_TOASTVALUE) &&
			   fsm_local_map.map[oldPage] == FSM_LOCAL_AVAIL);

		fsm_local_map.map[oldPage] = FSM_LOCAL_NOT_AVAIL;
		return fsm_local_search();
	}

	if (!fsm_allow_writes(rel, oldPage, InvalidBlockNumber, &nblocks))
	{
		/*
		 * If we have neither a local map nor a FSM, we probably just tried
		 * the target block in the smgr relation entry and failed, so we'll
		 * need to create the local map.
		 */
		fsm_local_set(rel, nblocks);
		return fsm_local_search();
	}

	/* Normal FSM logic follows */

	old_cat = fsm_space_avail_to_cat(oldSpaceAvail);
	search_cat = fsm_space_needed_to_cat(spaceNeeded);

	/* Get the location of the FSM byte representing the heap block */
	addr = fsm_get_location(oldPage, &slot);

	search_slot = fsm_set_and_search(rel, addr, slot, old_cat, search_cat);

	/*
	 * If fsm_set_and_search found a suitable new block, return that.
	 * Otherwise, search as usual.
	 */
	if (search_slot != -1)
		return fsm_get_heap_blk(addr, search_slot);
	else
		return fsm_search(rel, search_cat);
}
Example #3
0
File: avoid.c Project: bobbens/LACE
void fsm( event_t *evt )
{
   /* Start with the init loop. */
   if (fsm_state == FSM_INIT) {
      fsm_init( evt );
      return;
   }
   else if (fsm_state == FSM_ERR) {
      LED0_ON();
      return;
   }

   /* Handle normal events. */
   switch (evt->type) {
      case EVENT_TYPE_TIMER:
         if (evt->timer.timer == 0) {
            LED0_TOGGLE();
            timer_start( 0, 500, NULL );
         }
         else if (evt->timer.timer == 1) {

            if (fsm_state == FSM_SEARCH)
               fsm_search();
            else if (fsm_state == FSM_RUN)
               fsm_run();
         }
         break;

      case EVENT_TYPE_ADC:
         fsm_adcBuf[ fsm_adc ]  = ADCL;
         fsm_adcBuf[ fsm_adc ] += ADCH<<8;
         /*printf( "adc %d: %u", fsm_adc, fsm_adcBuf[ fsm_adc ] );*/
         fsm_adc = 1-fsm_adc;
         adc_start( fsm_adc );
         break;

      default:
         break;
   }
}
Example #4
0
/*
 * RecordAndGetPageWithFreeSpace - update info about a page and try again.
 *
 * We provide this combo form to save some locking overhead, compared to
 * separate RecordPageWithFreeSpace + GetPageWithFreeSpace calls. There's
 * also some effort to return a page close to the old page; if there's a
 * page with enough free space on the same FSM page where the old one page
 * is located, it is preferred.
 */
BlockNumber
RecordAndGetPageWithFreeSpace(Relation rel, BlockNumber oldPage,
							  Size oldSpaceAvail, Size spaceNeeded)
{
	int			old_cat = fsm_space_avail_to_cat(oldSpaceAvail);
	int			search_cat = fsm_space_needed_to_cat(spaceNeeded);
	FSMAddress	addr;
	uint16		slot;
	int			search_slot;

	/* Get the location of the FSM byte representing the heap block */
	addr = fsm_get_location(oldPage, &slot);

	search_slot = fsm_set_and_search(rel, addr, slot, old_cat, search_cat);

	/*
	 * If fsm_set_and_search found a suitable new___ block, return that.
	 * Otherwise, search as usual.
	 */
	if (search_slot != -1)
		return fsm_get_heap_blk(addr, search_slot);
	else
		return fsm_search(rel, search_cat);
}
Example #5
0
/*
 * GetPageWithFreeSpace - try to find a page in the given relation with
 *		at least the specified amount of free space.
 *
 * If successful, return the block number; if not, return InvalidBlockNumber.
 *
 * The caller must be prepared for the possibility that the returned page
 * will turn out to have too little space available by the time the caller
 * gets a lock on it.  In that case, the caller should report the actual
 * amount of free space available on that page and then try again (see
 * RecordAndGetPageWithFreeSpace).  If InvalidBlockNumber is returned,
 * extend the relation.
 *
 * For very small heap relations that don't have a FSM, we try every other
 * page before extending the relation.  To keep track of which pages have
 * been tried, initialize a local in-memory map of pages.
 */
BlockNumber
GetPageWithFreeSpace(Relation rel, Size spaceNeeded, bool check_fsm_only)
{
	uint8		min_cat = fsm_space_needed_to_cat(spaceNeeded);
	BlockNumber target_block,
				nblocks;

	/* First try the FSM, if it exists. */
	target_block = fsm_search(rel, min_cat);

	if (target_block == InvalidBlockNumber &&
		(rel->rd_rel->relkind == RELKIND_RELATION ||
		 rel->rd_rel->relkind == RELKIND_TOASTVALUE) &&
		!check_fsm_only)
	{
		nblocks = RelationGetNumberOfBlocks(rel);

		if (nblocks > HEAP_FSM_CREATION_THRESHOLD)
		{
			/*
			 * If the FSM knows nothing of the rel, try the last page before
			 * we give up and extend.  This avoids one-tuple-per-page syndrome
			 * during bootstrapping or in a recently-started system.
			 */
			target_block = nblocks - 1;
		}
		else if (nblocks > 0)
		{
			/* Create or update local map and get first candidate block. */
			fsm_local_set(rel, nblocks);
			target_block = fsm_local_search();
		}
	}

	return target_block;
}