Пример #1
0
//连接阶段
RC GHJ::HashJoin(BufferPool *bufferPool)
{
	//缓冲池重新初始化
	m_JoinCount=0;
	bufferPool->currentSize = 0; 

	HashTable hashTable;
	PageHeader *pageHeader;//用于操作读进来的页以获得页头等信息

	LPWSTR bucketPath_R = new TCHAR[MAX_PATH]; //桶文件名
	LPWSTR bucketPath_S = new TCHAR[MAX_PATH];
	LARGE_INTEGER liFileSize;

	//Init out page buffer 
	if(SUCCESS!=InitBuffer(&m_OutPageBuffer,SSD_PAGE_SIZE, &m_Pool))
	{
		ShowMB(L"Not enough memory for output page buffer");
		return ERR_NOT_ENOUGH_MEMORY;
	} 

	//Init out page 
	InitRunPage(&m_OutPage, &m_OutPageBuffer);  

	// Init write buffer size 
	if(SUCCESS!=InitBuffer(&m_OutBuffer, m_Params.WRITE_BUFFER_SIZE, &m_Pool))
	{
		ShowMB(L"Not enough memory for output buffer");
		return ERR_NOT_ENOUGH_MEMORY;
	}

	LPWSTR outputFileName = new TCHAR[MAX_PATH];
	swprintf_s(outputFileName, MAX_PATH, L"%sGHJ_%s_%s.dat", m_Params.WORK_SPACE_PATH, m_Params.RELATION_R_NO_EXT, m_Params.RELATION_S_NO_EXT);

	m_hOutFile=CreateFile(
		(LPCWSTR)outputFileName,		// file to write
		GENERIC_WRITE,			// open for writing
		0,						// Do not share
		NULL,					// default security
		CREATE_ALWAYS,			 
		FILE_ATTRIBUTE_NORMAL,	// FILE_FLAG_OVERLAPPED
		NULL);				 

	//FILE_FLAG_NO_BUFFERING
	//http://msdn.microsoft.com/en-us/library/windows/desktop/cc644950(v=vs.85).aspx

	if (INVALID_HANDLE_VALUE==m_hOutFile) 
	{  
		ShowMB(L"Cannot create handle %s", outputFileName);
		return ERR_CANNOT_CREATE_HANDLE;
	} 

	//Init read buffer
	InitBuffer(&m_InBuffer, 0, bufferPool);

	for(UINT partitionIndex=0; partitionIndex < m_PartitionNum; partitionIndex++)
	{       
		swprintf_s(bucketPath_R, MAX_PATH, L"%s%d%s.tmp", m_Params.WORK_SPACE_PATH, partitionIndex, m_Params.RELATION_R_NO_EXT); //生成桶文件名
		swprintf_s(bucketPath_S, MAX_PATH, L"%s%d%s.tmp", m_Params.WORK_SPACE_PATH, partitionIndex, m_Params.RELATION_S_NO_EXT);

		HANDLE hBucketR=CreateFile(bucketPath_R, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		HANDLE hBucketS=CreateFile(bucketPath_S, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

		if(hBucketR==INVALID_HANDLE_VALUE || hBucketS==INVALID_HANDLE_VALUE)
		{ 
			ShowMB(L"Cannot create bucket handle %s\n or %s", bucketPath_R, bucketPath_S);
			return ERR_CANNOT_CREATE_HANDLE;
		} 

		GetFileSizeEx(hBucketR, &liFileSize);
		if (!GetFileSizeEx(hBucketR, &liFileSize))
		{       
			ShowMB(L"Cannot get file size %s", bucketPath_R);
			return ERR_CANNOT_GET_FILE_SIZE; 
		} 

		// Init input buffer 
		m_InBuffer.size = liFileSize.QuadPart;
		bufferPool->currentSize+=m_InBuffer.size;

		DWORD tupleCount = 0;
		//分区文件读入输入缓冲区
		while(TRUE)
		{   
			DWORD dwBytesRead = 0;
			ReadFile(hBucketR,
				m_InBuffer.data,
				m_InBuffer.size,
				&dwBytesRead, 
				NULL);

			if(dwBytesRead==0)
			{
				break;
			}

			DWORD pageCount = 0;
			if(dwBytesRead%SSD_PAGE_SIZE==0)
				pageCount = dwBytesRead/SSD_PAGE_SIZE;
			else
				pageCount = dwBytesRead/SSD_PAGE_SIZE + 1;

			m_InBuffer.currentSize+=dwBytesRead;
			m_InBuffer.freeLocation+=dwBytesRead;  
			m_InBuffer.pageCount += pageCount;

			for(UINT pageIndex=0; pageIndex < pageCount; pageIndex++)
			{
				pageHeader=(PageHeader*)(m_InBuffer.data + pageIndex * SSD_PAGE_SIZE);
				tupleCount+=pageHeader->totalTuple;
			} 
		}	
		m_InBuffer.tupleCount+=tupleCount;

		//初始化散列表信息
		hashTable.startLocation = bufferPool->currentSize;
		hashTable.data = bufferPool->data + hashTable.startLocation;

		if(tupleCount%2==0)
			hashTable.hashFn=tupleCount+1;
		else
			hashTable.hashFn=tupleCount;

		hashTable.size = hashTable.hashFn * sizeof(HashTuple);

		//构建散列表
		HashBuild(&m_InBuffer, &hashTable);
		bufferPool->currentSize+=hashTable.size;

		//为大表建立读取缓存
		m_ProbeBuffer.startLocation = bufferPool->currentSize;
		m_ProbeBuffer.freeLocation = m_ProbeBuffer.startLocation;
		m_ProbeBuffer.data = bufferPool->data + m_ProbeBuffer.startLocation;
		DWORD probeBufferSize = chROUNDDOWN((bufferPool->size - bufferPool->currentSize), SSD_PAGE_SIZE) / SSD_PAGE_SIZE; 
		m_ProbeBuffer.size = probeBufferSize * SSD_PAGE_SIZE; 	
		m_ProbeBuffer.currentSize = 0;
		m_ProbeBuffer.pageCount = 0;
		m_ProbeBuffer.tupleCount = 0; 
		bufferPool->currentSize += m_ProbeBuffer.size;

		if(m_ProbeBuffer.size==0)
		{ 
			ShowMB(L"Exceeds available memory limit");
			return ERR_NOT_ENOUGH_MEMORY;
		}

		PagePtr probePage;
		while(TRUE)
		{	
			DWORD dwBytesRead = 0; 
			ReadFile(hBucketS,
				m_ProbeBuffer.data, 
				m_ProbeBuffer.size, 
				&dwBytesRead,
				NULL);

			if(dwBytesRead==0)
			{
				break;
			}

			DWORD pageCount = 0;
			if(dwBytesRead%SSD_PAGE_SIZE==0)
				pageCount = dwBytesRead/SSD_PAGE_SIZE;
			else
				pageCount = dwBytesRead/SSD_PAGE_SIZE + 1;

			for(UINT pageIndex=0; pageIndex < pageCount; pageIndex++)
			{
				probePage.page = m_ProbeBuffer.data + pageIndex*SSD_PAGE_SIZE;
				HashProbe(&probePage, &hashTable, &m_InBuffer);
			}
		}

		CloseHandle(hBucketR);
		CloseHandle(hBucketS); 

		ResetBuffer(&m_InBuffer);
	} 

	if(m_OutBuffer.currentSize > 0)
	{
		DWORD dwBytesWritten = 0; 
		WriteFile(m_hOutFile, 
			m_OutBuffer.data, 
			m_OutBuffer.currentSize,
			&dwBytesWritten,
			NULL); 
	}

	CloseHandle(m_hOutFile);

	delete outputFileName; 

	return SUCCESS;
}
Пример #2
0
/*
 *******************************************************************************
 *                                                                             *
 *   Ponder() is the driver for "pondering" (thinking on the opponent's time.) *
 *   its operation is simple:  Find a predicted move by (a) taking the second  *
 *   move from the principal variation, or (b) call lookup to see if it finds  *
 *   a suggested move from the transposition table.  Then, make this move and  *
 *   do a search from the resulting position.  While pondering, one of three   *
 *   things can happen:  (1) A move is entered, and it matches the predicted   *
 *   move.  We then switch from pondering to thinking and search as normal;    *
 *   (2) A move is entered, but it does not match the predicted move.  We then *
 *   abort the search, unmake the pondered move, and then restart with the     *
 *   move entered.  (3) A command is entered.  If it is a simple command, it   *
 *   can be done without aborting the search or losing time.  If not, we abort *
 *   the search, execute the command, and then attempt to restart pondering if *
 *   the command didn't make that impossible.                                  *
 *                                                                             *
 *******************************************************************************
 */
int Ponder(int wtm) {
  TREE *const tree = block[0];
  int dalpha = -999999, dbeta = 999999, i;
  unsigned *n_ponder_moves, *mv;
  int save_move_number, tlom, value;

/*
 ************************************************************
 *                                                          *
 *  First, let's check to see if pondering is allowed, or   *
 *  if we should avoid pondering on this move since it is   *
 *  the first move of a game, or if the game is over, or    *
 *  "force" mode is active, or there is input in the queue  *
 *  that needs to be read and processed.                    *
 *                                                          *
 ************************************************************
 */
  if (!ponder || force || over || CheckInput())
    return 0;
  save_move_number = move_number;
/*
 ************************************************************
 *                                                          *
 *  Check the ponder move for legality.  If it is not a     *
 *  legal move, we have to take action to find something to *
 *  ponder.                                                 *
 *                                                          *
 ************************************************************
 */
  strcpy(ponder_text, "none");
  if (ponder_move) {
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
      ponder_move = 0;
      Print(4095, "ERROR.  ponder_move is illegal (1).\n");
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
      Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
    }
  }
/*
 ************************************************************
 *                                                          *
 *  First attempt, do a hash probe.  However, since a hash  *
 *  collision is remotely possible, we still need to verify *
 *  that the transposition/refutation best move is actually *
 *  legal.                                                  *
 *                                                          *
 ************************************************************
 */
  if (!ponder_move) {
    HashProbe(tree, 0, 0, wtm, dalpha, dbeta, &value);
    if (tree->hash_move[0])
      ponder_move = tree->hash_move[0];
    if (ponder_move) {
      if (!VerifyMove(tree, 1, wtm, ponder_move)) {
        Print(4095, "ERROR.  ponder_move is illegal (2).\n");
        Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
        ponder_move = 0;
      }
    }
  }
/*
 ************************************************************
 *                                                          *
 *  Second attempt.  If that didn't work, then we try what  *
 *  I call a "puzzling" search.  Which is simply a shorter  *
 *  time-limit search for the other side, to find something *
 *  to ponder.                                              *
 *                                                          *
 ************************************************************
 */
  if (!ponder_move) {
    TimeSet(puzzle);
    if (time_limit < 20)
      return 0;
    puzzling = 1;
    tree->status[1] = tree->status[0];
    Print(32, "              puzzling over a move to ponder.\n");
    last_pv.pathl = 0;
    last_pv.pathd = 0;
    for (i = 0; i < MAXPLY; i++) {
      tree->killers[i].move1 = 0;
      tree->killers[i].move2 = 0;
    }
    Iterate(wtm, puzzle, 0);
    for (i = 0; i < MAXPLY; i++) {
      tree->killers[i].move1 = 0;
      tree->killers[i].move2 = 0;
    }
    puzzling = 0;
    if (tree->pv[0].pathl)
      ponder_move = tree->pv[0].path[1];
    if (!ponder_move)
      return 0;
    for (i = 1; i < (int) tree->pv[0].pathl; i++)
      last_pv.path[i] = tree->pv[0].path[i + 1];
    last_pv.pathl = tree->pv[0].pathl - 1;
    last_pv.pathd = 0;
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
      ponder_move = 0;
      Print(4095, "ERROR.  ponder_move is illegal (3).\n");
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
      return 0;
    }
  }
/*
 ************************************************************
 *                                                          *
 *  Display the move we are going to "ponder".              *
 *                                                          *
 ************************************************************
 */
  if (wtm)
    Print(32, "White(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
            wtm, ponder_move));
  else
    Print(32, "Black(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
            wtm, ponder_move));
  sprintf(ponder_text, "%s", OutputMove(tree, 0, wtm, ponder_move));
  if (post)
    printf("Hint: %s\n", ponder_text);
/*
 ************************************************************
 *                                                          *
 *  Set the ponder move list and eliminate illegal moves.   *
 *  This list is used to test the move entered while we are *
 *  pondering, since we need a move list for the input      *
 *  screening process.                                      *
 *                                                          *
 ************************************************************
 */
  n_ponder_moves = GenerateCaptures(tree, 0, wtm, ponder_moves);
  num_ponder_moves =
      GenerateNoncaptures(tree, 0, wtm, n_ponder_moves) - ponder_moves;
  for (mv = ponder_moves; mv < ponder_moves + num_ponder_moves; mv++) {
    MakeMove(tree, 0, wtm, *mv);
    if (Check(wtm)) {
      UnmakeMove(tree, 0, wtm, *mv);
      *mv = 0;
    } else
      UnmakeMove(tree, 0, wtm, *mv);
  }
/*
 ************************************************************
 *                                                          *
 *  Now, perform an iterated search, but with the special   *
 *  "pondering" flag set which changes the time controls    *
 *  since there is no need to stop searching until the      *
 *  opponent makes a move.                                  *
 *                                                          *
 ************************************************************
 */
  MakeMove(tree, 0, wtm, ponder_move);
  tree->curmv[0] = ponder_move;
  tree->rep_list[++rep_index] = HashKey;
  tlom = last_opponent_move;
  last_opponent_move = ponder_move;
  if (kibitz)
    strcpy(kibitz_text, "n/a");
  thinking = 0;
  pondering = 1;
  if (!wtm)
    move_number++;
  ponder_value = Iterate(Flip(wtm), think, 0);
  rep_index--;
  move_number = save_move_number;
  pondering = 0;
  thinking = 0;
  last_opponent_move = tlom;
  UnmakeMove(tree, 0, wtm, ponder_move);
/*
 ************************************************************
 *                                                          *
 *  Search completed. the possible return values are:       *
 *                                                          *
 *  (0) No pondering was done, period.                      *
 *                                                          *
 *  (1) Pondering was done, opponent made the predicted     *
 *      move, and we searched until time ran out in a       *
 *      normal manner.                                      *
 *                                                          *
 *  (2) Pondering was done, but the ponder search           *
 *      terminated due to either finding a mate, or the     *
 *      maximum search depth was reached.  The result of    *
 *      this ponder search are valid, but only if the       *
 *      opponent makes the correct (predicted) move.        *
 *                                                          *
 *  (3) Pondering was done, but the opponent either made a  *
 *      different move, or entered a command that has to    *
 *      interrupt the pondering search before the command   *
 *      (or move) can be processed.  This forces Main() to  *
 *      avoid reading in a move/command since one has been  *
 *      read into the command buffer already.               *
 *                                                          *
 ************************************************************
 */
  if (input_status == 1)
    return 1;
  if (input_status == 2)
    return 3;
  return 2;
}