Ejemplo n.º 1
0
VOID
WINAPI
WriteLoop(
    ULARGE_INTEGER FileSize
    )
{
    BOOL Success;
    DWORD_PTR Key;
    LPOVERLAPPED CompletedOverlapped;
    PCOPY_CHUNK Chunk;
    DWORD NumberBytes;
    ULARGE_INTEGER TotalBytesWritten;

    TotalBytesWritten.QuadPart = 0;

    for (;;) {
        Success = GetQueuedCompletionStatus(ReadPort,
                                            &NumberBytes,
                                            &Key,
                                            &CompletedOverlapped,
                                            INFINITE);

        if (!Success) {
            //
            // Either the function failed to dequeue a completion packet
            // (CompletedOverlapped is not NULL) or it dequeued a completion
            // packet of a failed I/O operation (CompletedOverlapped is NULL).  
            //
            fprintf(stderr,
                    "GetQueuedCompletionStatus on the IoPort failed, error %d\n",
                    GetLastError());
            exit(1);
        }

        //
        // Update the total number of bytes written.
        //
        TotalBytesWritten.QuadPart += NumberBytes;

        //
        // Issue the next write using the buffer that has just been read into.
        //
        Chunk = (PCOPY_CHUNK)CompletedOverlapped;

        //
        // Round the number of bytes to write up to a sector boundary
        //
        NumberBytes = (NumberBytes + PageSize - 1) & ~(PageSize-1);

        Success = WriteFile(DestFile,
                            Chunk->Buffer,
                            NumberBytes,
                            &NumberBytes,
                            &Chunk->Overlapped);

        if (!Success && (GetLastError() != ERROR_IO_PENDING)) {
            fprintf(stderr,
                    "WriteFile at %lx failed, error %d\n",
                    Chunk->Overlapped.Offset,
                    GetLastError());
            exit(1);
        }

        //
        //Check to see if we've copied the complete file, if so return
        //
        if (TotalBytesWritten.QuadPart >= FileSize.QuadPart)
            return;
    }
}
Ejemplo n.º 2
0
unsigned int WINAPI Proactor::WorkerThread(LPVOID lpParam)
{
	BOOL bSuccess = TRUE;
	SOCKETINFO* pOverlappedEx;
	DWORD               dwIoSize = 0;
	LPOVERLAPPED	 pOverlap = NULL;
#if 0
	int writen;
#endif
	int readn;
	int flags;
	Proactor *p_Pa = (Proactor*)lpParam;
	network *p_Net;
	SOCKETINFO *sInfo;

//16.05.31
	PPER_SOCKET_CONTEXT lpPerSocketContext = NULL;
	PPER_IO_CONTEXT     lpIOContext = NULL;
//16.05.31

	/* initialize networking */
	p_Net = Singleton<network>::getInstancePtr();


	while (p_Pa->bWorkerRun) {
		/*****************************/
		/* GetQueuedCompletionStatus */
		/*****************************/
		//bSuccess = GetQueuedCompletionStatus(p_Pa->g_hIOCP, &dwIoSize, (LPDWORD)&sInfo, &pOverlap, INFINITE); //win32
		bSuccess = GetQueuedCompletionStatus(p_Pa->g_hIOCP, &dwIoSize, (PULONG_PTR)&sInfo, &pOverlap, INFINITE); //X64

		if (bSuccess == FALSE || dwIoSize == 0) {
			printf("Disconnected..[fd:%d]\n", sInfo->fd);
			shutdown(sInfo->fd, SD_BOTH);
			closesocket(sInfo->fd);

			pClientManager->send_client_closed(sInfo->fd);

			sInfo->fd = INVALID_SOCKET;
			continue;
		}

		if (bSuccess == TRUE && dwIoSize == 0 && pOverlap == NULL) {
			p_Pa->bWorkerRun = FALSE;
			continue;
		}

		pOverlappedEx = (SOCKETINFO*)pOverlap;

		if (sInfo->readn == 0) {
			sInfo->readn = dwIoSize;
			sInfo->writen = 0;
			//printf("Client[%d] size[%d]: %s", sInfo->fd, dwIoSize, pOverlappedEx->dataBuf.buf);
			//printf("Exec Thread Num [%d] \n", p->cur_thread_num);
			printf("Exec fd [%d] \n", sInfo->fd);
		}
		else {
			sInfo->writen += dwIoSize;
		}

		//by lsy 16.05.31
		lpIOContext = (PPER_IO_CONTEXT)pOverlap;
		//by lsy 16.05.31

		//switch(lpIOContext->IOOperation)
		switch (sInfo->IOOperation)
		{
		case ClientIoRead:
			sInfo->IOOperation = ClientIoWrite;
			if (sInfo->readn > sInfo->writen) {
				memset(&(sInfo->overlapped), 0x00, sizeof(WSAOVERLAPPED));
				sInfo->fd = pOverlappedEx->fd;
				sInfo->dataBuf.buf = pOverlappedEx->dataBuf.buf;
				sInfo->dataBuf.len = dwIoSize;

#if 1
				//ObjectUser::User* pOvluser = (ObjectUser::User*)pOverlappedEx->dataBuf.buf;
				//pOvluser->id = sInfo->fd;

				BYTE test_byte[30];
				memcpy(test_byte, pOverlappedEx->dataBuf.buf, dwIoSize);

				pClientManager->Recv_Client_Packet(sInfo, test_byte);
#endif

#if 0
				/* return message by send socket */
				if (WSASend(sInfo->fd, 
					&(sInfo->dataBuf), 
					1, 
					(DWORD *)&writen, 
					0, 
					&(sInfo->overlapped), 
					NULL) == SOCKET_ERROR) {
					if (WSAGetLastError() != WSA_IO_PENDING) {
						printf("WSASend Error\n");
					}
				}
#endif
			}
			break;
		case ClientIoWrite:
			flags = 0;
			memset(&(sInfo->overlapped), 0x00, sizeof(WSAOVERLAPPED));
			memset(&(sInfo->buf), 0, MAX_BUFF);
			sInfo->readn = 0;
			sInfo->fd = pOverlappedEx->fd;
			sInfo->dataBuf.len = MAX_BUFF;
			sInfo->dataBuf.buf = pOverlappedEx->dataBuf.buf;
			sInfo->IOOperation = ClientIoRead;

#if 1
			if (WSARecv(sInfo->fd, &sInfo->dataBuf, 1, (DWORD *)&readn, (DWORD *)&flags, &(sInfo->overlapped), NULL) == SOCKET_ERROR) {
				if (WSAGetLastError() != WSA_IO_PENDING) {
					printf("wsarecv error %d\n", WSAGetLastError());
				}
			}
#endif
			break;
		default:
			break;

		}
	}
	return 1;
}
Ejemplo n.º 3
0
Archivo: apby.cpp Proyecto: yngccc/apby
DWORD game_loop_main(LPVOID thread_input) {
  struct common_vars common_vars = *(struct common_vars *)thread_input;
  profiler profiler = {};
  profiler_create(&profiler);
  LARGE_INTEGER performance_frequency = {};
  QueryPerformanceFrequency(&performance_frequency);
  memory_arena memory_arena = {};
  if (!virtual_alloc_memory_arena(m_megabytes(16), common_vars.system_info.dwPageSize, &memory_arena)) {
    m_die("call to \"virtual_alloc_memory_arena\" failed(event_render_loop_thread memory arena)");
  }
  vulkan vulkan = {};
  {
    m_memory_arena_undo_allocations_at_scope_exit(&memory_arena);
    string info_string = { memory_arena_allocate<char>(&memory_arena, m_kilobytes(4)), 0, m_kilobytes(2) };
    string err_string = { memory_arena_allocate<char>(&memory_arena, m_kilobytes(1)), 0, m_kilobytes(1) };
    vulkan_create_info vulkan_create_info = {};
    vulkan_create_info.win32_instance = common_vars.instance;
    vulkan_create_info.win32_window = common_vars.window;
    const char *shader_file_paths[] = { "shaders\\swap_chain_pipeline_image.vert.spv", "shaders\\swap_chain_pipeline_image.frag.spv" };
    if (!read_file_into_memory_arena(shader_file_paths[0], &memory_arena, &vulkan_create_info.swap_chain_pipeline_image_code[0], &vulkan_create_info.swap_chain_pipeline_image_code_sizes[0]) ||
        !read_file_into_memory_arena(shader_file_paths[1], &memory_arena, &vulkan_create_info.swap_chain_pipeline_image_code[1], &vulkan_create_info.swap_chain_pipeline_image_code_sizes[1])) {
      m_die("call to \"read_file_into_memory_arena\" failed(swap_chain_pipeline_image shaders)");
    }
    if (!vulkan_create(vulkan_create_info, &memory_arena, &info_string, &err_string, &vulkan)) {
      m_die("%s", err_string.buf);
    }
    else {
      m_printf("%s", info_string.buf);
    }
  }
  game_buffer game_buffer = {};
  vec4 game_buffer_viewport = {};
  HANDLE game_buffer_gpk_file_handle = nullptr;
  HANDLE game_buffer_gpk_file_mapping = nullptr;
  void *game_buffer_gpk_file_mapping_ptr = nullptr;
  HANDLE game_buffer_mpk_import_shared_memory_mapping = nullptr;
  void *game_buffer_mpk_import_shared_memory_mapping_ptr = nullptr;
  HANDLE game_buffer_mpk_import_shared_memory_semaphore = nullptr;
  {
    game_buffer_create_info game_buffer_create_info = {};
    if (!virtual_alloc_memory_arena(m_megabytes(512), common_vars.system_info.dwPageSize, &game_buffer_create_info.memory_arena)) {
      m_die("call to \"virtual_alloc_memory_arena\" failed(game buffer memory arena)");
    }
    game_buffer_create_info.vulkan = &vulkan;
    game_buffer_create_info.vulkan_framebuffer_width = 1920;
    game_buffer_create_info.vulkan_framebuffer_height = 1080;
    if (!game_buffer_create(game_buffer_create_info, &game_buffer)) {
      m_die("call to \"game_buffer_create\" failed");
    }
#ifdef EDITOR_ENABLE
    game_buffer_editor_create_info game_buffer_editor_create_info = {};
    game_buffer_editor_create_info.game_buffer = &game_buffer;
    game_buffer_editor_create_info.vulkan = &vulkan;
    game_buffer_editor_create_info.imgui_init_file = "assets\\gpks\\example.gpk.imgui.ini";
    game_buffer_editor_create_info.imgui_font_file = "assets\\fonts\\OpenSans-Regular.ttf";
    game_buffer_editor_create_info.imgui_font_size = GetSystemMetrics(SM_CXSCREEN) / 150;
    game_buffer_editor_create_info.set_imgui_keymap = [] (ImGuiIO *imgui_io) {
      imgui_io->KeyMap[ImGuiKey_Tab] = VK_TAB;
      imgui_io->KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
      imgui_io->KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
      imgui_io->KeyMap[ImGuiKey_UpArrow] = VK_UP;
      imgui_io->KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
      imgui_io->KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
      imgui_io->KeyMap[ImGuiKey_PageDown] = VK_NEXT;
      imgui_io->KeyMap[ImGuiKey_Home] = VK_HOME;
      imgui_io->KeyMap[ImGuiKey_End] = VK_END;
      imgui_io->KeyMap[ImGuiKey_Backspace] = VK_BACK;
      imgui_io->KeyMap[ImGuiKey_Enter] = VK_RETURN;
      imgui_io->KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
      imgui_io->KeyMap[ImGuiKey_A] = 'A';
      imgui_io->KeyMap[ImGuiKey_C] = 'C';
      imgui_io->KeyMap[ImGuiKey_V] = 'V';
      imgui_io->KeyMap[ImGuiKey_X] = 'X';
      imgui_io->KeyMap[ImGuiKey_Y] = 'Y';
      imgui_io->KeyMap[ImGuiKey_Z] = 'Z';
    };
    {
      m_memory_arena_undo_allocations_at_scope_exit(&memory_arena);
      const char *file_paths[] = { "shaders\\imgui.vert.spv", "shaders\\imgui.frag.spv" };
      VkShaderModule shader_modules[m_countof(file_paths)] = {};
      for (uint i = 0; i < m_countof(file_paths); i += 1) {
        void *file_data;
        uint file_size;
        if (!read_file_into_memory_arena(file_paths[i], &memory_arena, &file_data, &file_size)) {
          m_die("call to \"read_file_into_memory_arena\" failed(game buffer shader files)");
        }
        VkShaderModuleCreateInfo shader_module_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
        shader_module_info.codeSize = file_size;
        shader_module_info.pCode = (const uint32_t *)file_data;
        if(vkCreateShaderModule(vulkan.device, &shader_module_info, nullptr, &shader_modules[i]) != VK_SUCCESS) {
          m_die("game buffer creation failed\ncall to \"vkCreateShaderModule\" failed for shader file %s", file_paths[i]);
        }
      }
      game_buffer_editor_create_info.imgui_vulkan_shaders[0] = shader_modules[0];
      game_buffer_editor_create_info.imgui_vulkan_shaders[1] = shader_modules[1];
    }
    game_buffer.editor = memory_arena_allocate<game_buffer_editor>(&game_buffer.memory_arena, 1);
    *game_buffer.editor = {};
    if (!game_buffer_editor_create(&game_buffer_editor_create_info, game_buffer.editor)) {
      m_die("call to \"game_buffer_editor_create\" failed");
    }
    {
      uint shared_memory_size = m_megabytes(32);
      HANDLE shared_memory_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE | SEC_COMMIT, 0, shared_memory_size, m_mpk_import_shared_memory_name);
      if (!shared_memory_mapping) {
        m_last_error_str(err_str);
        m_die("call to \"CreateFileMappingA\" failed\nfile: %s\nerr: %s", m_mpk_import_shared_memory_name, err_str);
      }
      void *shared_memory_mapping_ptr = MapViewOfFile(shared_memory_mapping, FILE_MAP_WRITE, 0, 0, shared_memory_size);
      if (!shared_memory_mapping_ptr) {
        m_last_error_str(err_str);
        m_die("call to \"MapViewOfFile\" failed\nfile: %s\nerr: %s", m_mpk_import_shared_memory_name, err_str);
      }
      ((mpk_import_shared_memory_header *)shared_memory_mapping_ptr)->total_size = shared_memory_size;
      ((mpk_import_shared_memory_header *)shared_memory_mapping_ptr)->mpk_size = shared_memory_size - sizeof(struct mpk_import_shared_memory_header);
      SetLastError(ERROR_SUCCESS);
      HANDLE shared_memory_semaphore = CreateSemaphore(nullptr, 1, 1, m_mpk_import_shared_memory_semaphore_name);
      if (!shared_memory_semaphore) {
        m_last_error_str(err_str);
        m_die("call to \"CreateSemaphore\" failed\nsemaphore: %s\nerr: %s", m_mpk_import_shared_memory_semaphore_name, err_str);
      }
      if (GetLastError() == ERROR_ALREADY_EXISTS) {
        m_die("call to \"CreateSemaphore\" failed\nsemaphore: %s\nerr: %s", m_mpk_import_shared_memory_semaphore_name, "named semaphore already exist");
      }
      game_buffer_mpk_import_shared_memory_mapping = shared_memory_mapping;
      game_buffer_mpk_import_shared_memory_mapping_ptr = shared_memory_mapping_ptr;
      game_buffer_mpk_import_shared_memory_semaphore = shared_memory_semaphore;
    }
    {
      game_buffer_editor_job *new_job = nullptr;
      if (game_buffer_editor_add_mpk_job(&game_buffer, &new_job)) {
        mpk_import_command_line cmdl = m_mpk_import_command_line_default;
        cmdl.job_id = new_job->id;
        cmdl.import_type = mpk_import_type_fbx;
        strcpy(cmdl.fbx_file_path, "assets\\models\\simple_man\\simple_man.fbx");
        mpk_import_create_process(&cmdl, common_vars.process_group, &memory_arena);
      }
    }
#endif // EDITOR_ENABLE
    {
      char gpk_file_name[] = "assets\\gpks\\example.gpk";
      HANDLE gpk_file_handle = CreateFileA(gpk_file_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
      if (gpk_file_handle == INVALID_HANDLE_VALUE) {
        m_last_error_str(err_str);
        m_die("call to \"CreateFile\" failed\nfile: %s\nerr: %s", gpk_file_name, err_str);
      }
      uint file_size = m_megabytes(32);
      SetFilePointer(gpk_file_handle, file_size, nullptr, FILE_BEGIN);
      if (!SetEndOfFile(gpk_file_handle)) {
        m_last_error_str(err_str);
        m_die("call to \"SetEndOfFile\" failed\nfile: %s\nsize: %d\nerr: %s", gpk_file_name, file_size, err_str);
      }
      HANDLE gpk_file_mapping = CreateFileMappingA(gpk_file_handle, nullptr, PAGE_READWRITE, 0, 0, nullptr);
      if (!gpk_file_mapping) {
        m_last_error_str(err_str);
        m_die("call to \"CreateFileMappingA\" failed\nfile: %s\nerr: %s", gpk_file_name, err_str);
      }
      void *gpk_file_mapping_ptr = MapViewOfFile(gpk_file_mapping, FILE_MAP_WRITE, 0, 0, file_size);
      if (!gpk_file_mapping_ptr) {
        m_last_error_str(err_str);
        m_die("call to \"MapViewOfFile\" failed\nfile: %s\nerr: %s", gpk_file_name, err_str);
      }
      uint gpk_file_initial_state_size = 0;
      if (!gpk_write_initial_state(gpk_file_mapping_ptr, file_size, &gpk_file_initial_state_size)) {
        m_die("call to \"gpk_write_initial_state\" failed");
      }
      if (!FlushViewOfFile(gpk_file_mapping_ptr, gpk_file_initial_state_size)) {
        m_last_error_str(err_str);
        m_die("call to \"FlushViewOfFile\" failed\nfile: %s\nerr: %s", gpk_file_name, err_str);
      }
      game_buffer_gpk_file_handle = gpk_file_handle;
      game_buffer_gpk_file_mapping = gpk_file_mapping;
      game_buffer_gpk_file_mapping_ptr = gpk_file_mapping_ptr;
    }
    {
      game_buffer_update_vulkan_swap_chain_image(&game_buffer, &vulkan);
      game_buffer_viewport = rectangle_fit_into_viewport((float)vulkan.swap_chain_info.imageExtent.width, (float)vulkan.swap_chain_info.imageExtent.height, (float)game_buffer.vulkan_framebuffer_image_width, (float)game_buffer.vulkan_framebuffer_image_height);
    }
  }
  uint64 last_frame_time_microsecs = 0;
  bool mouse_down_up_same_frame[3] = {};
  for (;;) {
    LARGE_INTEGER frame_begin_performance_count;
    QueryPerformanceCounter(&frame_begin_performance_count);
    m_scope_exit(
      LARGE_INTEGER frame_end_performance_count;
      QueryPerformanceCounter(&frame_end_performance_count);
      last_frame_time_microsecs = (frame_end_performance_count.QuadPart - frame_begin_performance_count.QuadPart) * 1000000 / performance_frequency.QuadPart;
    );
    {
      bool mouse_down_this_frame[3] = {};
      for (uint i = 0; i < 3; i += 1) {
        if (mouse_down_up_same_frame[i]) {
          mouse_down_up_same_frame[i] = false;
#ifdef EDITOR_ENABLE
          game_buffer_editor_handle_mouse_up(&game_buffer, i);
#endif
        }
      }
      HANDLE iocp = common_vars.io_completion_port;
      DWORD iocp_num_bytes = 0;
      ULONG_PTR iocp_completion_key = 0;
      LPOVERLAPPED iocp_overlapped = nullptr;
      DWORD iocp_time_out = 0;
      while (GetQueuedCompletionStatus(iocp, &iocp_num_bytes, &iocp_completion_key, &iocp_overlapped, iocp_time_out) == TRUE) {
        switch (iocp_completion_key) {
          case quit_win_main_event : {
#ifdef EDITOR_ENABLE
            ImGui::Shutdown();
#endif
            ExitThread(0);
          } break;
          case window_resize_event : {
            uint32 new_width = LOWORD((LPARAM)iocp_overlapped);
            uint32 new_height = HIWORD((LPARAM)iocp_overlapped);
            if (vulkan.swap_chain_info.imageExtent.width != new_width || vulkan.swap_chain_info.imageExtent.height != new_height) {
              if (!vulkan_resize_swap_chain_images(&vulkan, new_width, new_height)) {
                m_die("call to \"vulkan_resize_swap_chain_images\" failed");
              }
              game_buffer_viewport = rectangle_fit_into_viewport((float)vulkan.swap_chain_info.imageExtent.width, (float)vulkan.swap_chain_info.imageExtent.height, (float)game_buffer.vulkan_framebuffer_image_width, (float)game_buffer.vulkan_framebuffer_image_height);
            }
          } break;
          case key_down_event : {
          } break;
          case key_up_event : {
          } break;
          case mouse_move_event : {
#ifdef EDITOR_ENABLE
            game_buffer_editor_handle_mouse_move(&game_buffer, game_buffer_viewport, LOWORD((LPARAM)iocp_overlapped), HIWORD((LPARAM)iocp_overlapped));
#endif
          } break;
          case mouse_lbutton_down_event : {
            mouse_down_this_frame[0] = true;
#ifdef EDITOR_ENABLE
            game_buffer_editor_handle_mouse_down(&game_buffer, 0);
#endif
          } break;
          case mouse_lbutton_up_event : {
            if (mouse_down_this_frame[0]) {
              mouse_down_up_same_frame[0] = true;
            }
            else {
#ifdef EDITOR_ENABLE
              game_buffer_editor_handle_mouse_up(&game_buffer, 0);
#endif
            }
          } break;
          case mouse_rbutton_down_event : {
            mouse_down_this_frame[1] = true;
#ifdef EDITOR_ENABLE
            game_buffer_editor_handle_mouse_down(&game_buffer, 1);
#endif
          } break;
          case mouse_rbutton_up_event : {
            if (mouse_down_this_frame[1]) {
              mouse_down_up_same_frame[1] = true;
            }
            else {
#ifdef EDITOR_ENABLE
              game_buffer_editor_handle_mouse_up(&game_buffer, 1);
#endif
            }
          } break;
          case mpk_import_named_pipe_event : {
#ifdef EDITOR_ENABLE
            mpk_import_named_pipe_instance *named_pipe_instance = (mpk_import_named_pipe_instance *)iocp_overlapped;
            if (named_pipe_instance->connected) {
              m_printf("got message %d bytes: %s\n", iocp_num_bytes, named_pipe_instance->message.msg);
              game_buffer_editor_handle_mpk_import_message(&game_buffer, &named_pipe_instance->message);
              if (named_pipe_instance->message.type == mpk_import_named_pipe_message_type_done) {
                void *mpk_ptr = ((struct mpk_import_shared_memory_header *)game_buffer_mpk_import_shared_memory_mapping_ptr) + 1;
                struct mpk_header *mpk_header_ptr = (struct mpk_header *)mpk_ptr;
                ReleaseSemaphore(game_buffer_mpk_import_shared_memory_semaphore, 1, nullptr);
              }
              ReadFile(named_pipe_instance->handle, &named_pipe_instance->message, sizeof(named_pipe_instance->message), nullptr, &named_pipe_instance->overlapped);
            }
            else {
              m_printf("new named pipe instance connected\n");
              named_pipe_instance->connected = true;
              ReadFile(named_pipe_instance->handle, &named_pipe_instance->message, sizeof(named_pipe_instance->message), nullptr, &named_pipe_instance->overlapped);
              mpk_import_add_named_pipe_instance(&common_vars);
            }
#else
            m_die("game loop main: received event \"mpk_import_named_pipe_event\", but editor is not enabled");
#endif
          } break;
          default : {
            m_die("game loop main: call to \"GetQueuedCompletionStatus\" returned an invalid event");
          } break;
        }
      }
    }
#ifdef EDITOR_ENABLE
    game_buffer.editor->imgui_io->DeltaTime = (float)(last_frame_time_microsecs / 1000000.0);
    ImGui::NewFrame();
    game_buffer_editor_imgui_new_frame(&game_buffer, &vulkan);
#endif
    {
      VkResult vk_result = {};
      vkWaitForFences(vulkan.device, 1, &vulkan.swap_chain_fence, VK_TRUE, UINT64_MAX);
      vkResetFences(vulkan.device, 1, &vulkan.swap_chain_fence);
      uint swap_chain_image_index = 0;
      if ((vk_result = vkAcquireNextImageKHR(vulkan.device, vulkan.swap_chain, UINT64_MAX, vulkan.swap_chain_image_semaphore, VK_NULL_HANDLE, &swap_chain_image_index)) != VK_SUCCESS) {
        m_die("call to \"vkAcquireNextImageKHR\" failed");
      }
      VkCommandBufferBeginInfo cmd_buffer_begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
      cmd_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
      vkBeginCommandBuffer(vulkan.swap_chain_cmd_buffer, &cmd_buffer_begin_info);
      game_buffer_record_vulkan_commands(&game_buffer, &vulkan);
      vulkan_record_swap_chain_commands(&vulkan, swap_chain_image_index, game_buffer_viewport);
      vkEndCommandBuffer(vulkan.swap_chain_cmd_buffer);
      VkSubmitInfo queue_submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
      queue_submit_info.waitSemaphoreCount = 1;
      queue_submit_info.pWaitSemaphores = &vulkan.swap_chain_image_semaphore;
      VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
      queue_submit_info.pWaitDstStageMask = &wait_dst_stage_mask;
      queue_submit_info.commandBufferCount = 1;
      queue_submit_info.pCommandBuffers = &vulkan.swap_chain_cmd_buffer;
      queue_submit_info.signalSemaphoreCount = 1;
      queue_submit_info.pSignalSemaphores = &vulkan.swap_chain_queue_semaphore;
      if ((vk_result = vkQueueSubmit(vulkan.device_queue, 1, &queue_submit_info, vulkan.swap_chain_fence)) != VK_SUCCESS) {
        m_die("call to \"vkQueueSubmit\" failed");
      }
      VkPresentInfoKHR device_queue_present_info = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
      device_queue_present_info.waitSemaphoreCount = 1;
      device_queue_present_info.pWaitSemaphores = &vulkan.swap_chain_queue_semaphore;
      device_queue_present_info.swapchainCount = 1;
      device_queue_present_info.pSwapchains = &vulkan.swap_chain;
      device_queue_present_info.pImageIndices = &swap_chain_image_index;
      if ((vk_result = vkQueuePresentKHR(vulkan.device_queue, &device_queue_present_info)) != VK_SUCCESS) {
        m_die("call to \"vkQueuePresentKHR\" failed");
      }
    }
  }
Ejemplo n.º 4
0
unsigned int __stdcall WINAPI CIOCP::_work_thread_(LPVOID pVoid)
{
	CIOCP* This = (CIOCP*)pVoid;

	CConnection*	pCon;
	LPOVERLAPPED	lpOverlapped;
	DWORD			dwTransferred;	

	long			RestBytes;

	char*			pPacket;
	long			PacketSize;

	long			ErrorCode = 0;

	while(TRUE)
	{
WORKER:
			if(GetQueuedCompletionStatus(This->GetCompletionHandle(),&dwTransferred,(DWORD*)&pCon,&lpOverlapped,INFINITE) ==0)
			{
				if( lpOverlapped != NULL )
				{
					This->ConnectionError( pCon );
				}
				else
					LOG("GetQueuedCompletionStatus Error! : code %d",GetLastError());

				continue;
			}

			if ( ((long)pCon) == WORKER_DESTROY_KEY )
			{
				This->SetWorkerEvent() ;
				return 0;
			}

			if ( pCon == NULL || lpOverlapped == NULL )
			{
				This->ConnectionError( pCon );
				continue ;
			}

			/// Disconnection
			if ( dwTransferred == 0)
			{
				This->ConnectionError( pCon );
				continue ;
			}

			if (  pCon->GetOverState() == GOOD	&& lpOverlapped == pCon->GetRecvOverLapped() )
			{
				RestBytes = (int)dwTransferred + pCon->m_SaveRecvBytes;
				// 组包,可能一个条消息包括几条数据包
				for ( ;; )
				{
					/// 是否得到一个数据包
					pPacket = pCon->GetSamplePacket( RestBytes,&PacketSize,&ErrorCode);
					if ( pPacket == NULL )
					{
						if ( ErrorCode )
						{
							if(ErrorCode == PACKET_SAMPLING_OK)				LOG("Packet Error. IP:%s",pCon->GetIP());
		
							ErrorCode = 0 ;
							This->ConnectionError( pCon );
							goto WORKER;
						}

						pCon->SaveRecvBuffer( RestBytes );
						break; 
					}
					if(!This->PacketManager.WritePacket(pPacket,PacketSize,pCon))
					{
						// 写包失败,然后关闭套接字
						pCon->m_ReadIndex -= PacketSize;
						pCon->SaveRecvBuffer(RestBytes);

						LOG("Fail WritePacket. IP:%s",pCon->GetIP());

						ErrorCode = 0;
						This->ConnectionError(pCon);
						goto WORKER;
					}

					if((RestBytes -= PacketSize) <= 0) 
					{
						pCon->m_SaveRecvBytes = 0; 
						break;
					}
				}
				This->PacketManager.SetPacketEvent();
				pCon->RecvPacket() ;
			}
	}

	return 0;
}
Ejemplo n.º 5
0
void CPathWatcher::WorkerThread()
{
	DWORD numBytes;
	CDirWatchInfo * pdi = NULL;
	LPOVERLAPPED lpOverlapped;
	WCHAR buf[MAX_PATH*4] = {0};
	while (m_bRunning)
	{
		if (watchedPaths.GetCount())
		{
			if (!GetQueuedCompletionStatus(m_hCompPort,
											&numBytes,
											(PULONG_PTR) &pdi,
											&lpOverlapped,
											INFINITE))
			{
				// Error retrieving changes
				// Clear the list of watched objects and recreate that list
				if (!m_bRunning)
					return;
				{
					AutoLocker lock(m_critSec);
					ClearInfoMap();
				}
				DWORD lasterr = GetLastError();
				if ((m_hCompPort != INVALID_HANDLE_VALUE)&&(lasterr!=ERROR_SUCCESS)&&(lasterr!=ERROR_INVALID_HANDLE))
				{
					CloseHandle(m_hCompPort);
					m_hCompPort = INVALID_HANDLE_VALUE;
				}
				// Since we pass m_hCompPort to CreateIoCompletionPort, we
				// have to set this to NULL to have that API create a new
				// handle.
				m_hCompPort = NULL;
				for (int i=0; i<watchedPaths.GetCount(); ++i)
				{
					HANDLE hDir = CreateFile(watchedPaths[i].GetWinPath(),
											FILE_LIST_DIRECTORY,
											FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
											NULL, //security attributes
											OPEN_EXISTING,
											FILE_FLAG_BACKUP_SEMANTICS | //required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME.
											FILE_FLAG_OVERLAPPED,
											NULL);
					if (hDir == INVALID_HANDLE_VALUE)
					{
						// this could happen if a watched folder has been removed/renamed
						CloseHandle(m_hCompPort);
						m_hCompPort = INVALID_HANDLE_VALUE;
						AutoLocker lock(m_critSec);
						watchedPaths.RemovePath(watchedPaths[i]);
						i--; if (i<0) i=0;
						break;
					}

					CDirWatchInfo * pDirInfo = new CDirWatchInfo(hDir, watchedPaths[i]);
					m_hCompPort = CreateIoCompletionPort(hDir, m_hCompPort, (ULONG_PTR)pDirInfo, 0);
					if (m_hCompPort == NULL)
					{
						AutoLocker lock(m_critSec);
						ClearInfoMap();
						delete pDirInfo;
						pDirInfo = NULL;
						watchedPaths.RemovePath(watchedPaths[i]);
						i--; if (i<0) i=0;
						break;
					}
					if (!ReadDirectoryChangesW(pDirInfo->m_hDir,
												pDirInfo->m_Buffer,
												READ_DIR_CHANGE_BUFFER_SIZE,
												TRUE,
												FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
												&numBytes,// not used
												&pDirInfo->m_Overlapped,
												NULL))	//no completion routine!
					{
						AutoLocker lock(m_critSec);
						ClearInfoMap();
						delete pDirInfo;
						pDirInfo = NULL;
						watchedPaths.RemovePath(watchedPaths[i]);
						i--; if (i<0) i=0;
						break;
					}
					AutoLocker lock(m_critSec);
					watchInfoMap[pDirInfo->m_hDir] = pDirInfo;
					ATLTRACE(_T("watching path %s\n"), pDirInfo->m_DirName.GetWinPath());
				}
			}
			else
			{
				if (!m_bRunning)
					return;
				// NOTE: the longer this code takes to execute until ReadDirectoryChangesW
				// is called again, the higher the chance that we miss some
				// changes in the file system!
				if (pdi)
				{
					if (numBytes == 0)
					{
						goto continuewatching;
					}
					PFILE_NOTIFY_INFORMATION pnotify = (PFILE_NOTIFY_INFORMATION)pdi->m_Buffer;
					if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
						goto continuewatching;
					DWORD nOffset = pnotify->NextEntryOffset;
					do
					{
						nOffset = pnotify->NextEntryOffset;
						SecureZeroMemory(buf, MAX_PATH*4*sizeof(TCHAR));
						_tcsncpy_s(buf, MAX_PATH*4, pdi->m_DirPath, MAX_PATH*4);
						errno_t err = _tcsncat_s(buf+pdi->m_DirPath.GetLength(), (MAX_PATH*4)-pdi->m_DirPath.GetLength(), pnotify->FileName, _TRUNCATE);
						if (err == STRUNCATE)
						{
							pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset);
							continue;
						}
						buf[min(MAX_PATH*4-1, pdi->m_DirPath.GetLength()+(pnotify->FileNameLength/sizeof(WCHAR)))] = 0;
						pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset);
						ATLTRACE(_T("change notification: %s\n"), buf);
						m_changedPaths.AddPath(CTGitPath(buf));
						if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
							break;
					} while (nOffset);
continuewatching:
					SecureZeroMemory(pdi->m_Buffer, sizeof(pdi->m_Buffer));
					SecureZeroMemory(&pdi->m_Overlapped, sizeof(OVERLAPPED));
					if (!ReadDirectoryChangesW(pdi->m_hDir,
												pdi->m_Buffer,
												READ_DIR_CHANGE_BUFFER_SIZE,
												TRUE,
												FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
												&numBytes,// not used
												&pdi->m_Overlapped,
												NULL))	//no completion routine!
					{
						// Since the call to ReadDirectoryChangesW failed, just
						// wait a while. We don't want to have this thread
						// running using 100% CPU if something goes completely
						// wrong.
						Sleep(200);
					}
				}
			}
		}// if (watchedPaths.GetCount())
		else
			Sleep(200);
	}// while (m_bRunning)
}
Ejemplo n.º 6
0
void IOThread::DoIocpJob()
{
	DWORD dwTransferred = 0;
	LPOVERLAPPED overlapped = nullptr;
	
	ULONG_PTR completionKey = 0;

	int ret = GetQueuedCompletionStatus(mCompletionPort, &dwTransferred, (PULONG_PTR)&completionKey, &overlapped, GQCS_TIMEOUT);

	/// general I/O processing

	OverlappedIOContext* context = reinterpret_cast<OverlappedIOContext*>(overlapped);
	
	SessionPtr remote = context ? context->mSessionObject : nullptr;

	if (ret == 0 || dwTransferred == 0)
	{
		/// check time out first 
		if ( context == nullptr && GetLastError() == WAIT_TIMEOUT)
			return;

	
		if (context->mIoType == IO_RECV || context->mIoType == IO_SEND)
		{
			CRASH_ASSERT(nullptr != remote);

			/// In most cases in here: ERROR_NETNAME_DELETED(64)

			remote->Disconnect(DR_COMPLETION_ERROR);

			DeleteIoContext(context);

			return;
		}
	}

	CRASH_ASSERT(nullptr != remote);

	bool completionOk = false;
	switch (context->mIoType)
	{
	case IO_RECV_ZERO:
		completionOk = remote->PostRecv();
		break;

	case IO_SEND:
		remote->SendCompletion(dwTransferred);

		if (context->mWsaBuf.len != dwTransferred)
			GConsoleLog->PrintOut(true, "Partial SendCompletion requested [%d], sent [%d]\n", context->mWsaBuf.len, dwTransferred);
		else
			completionOk = true;
		
		break;

	case IO_RECV:
		remote->RecvCompletion(dwTransferred);
		
		completionOk = remote->PreRecv();

		break;

	default:
		GConsoleLog->PrintOut(true, "Unknown I/O Type: %d\n", context->mIoType);
		CRASH_ASSERT(false);
		break;
	}

	if (!completionOk)
	{
		/// connection closing
		remote->Disconnect(DR_IO_REQUEST_ERROR);
	}

	DeleteIoContext(context);
	
}
Ejemplo n.º 7
0
// 完成端口的工作线程
unsigned int _stdcall CLCompletionThread(void * lpParam)
{
	SOCKET_OBJ  *sockobj=NULL;	// Per socket object for completed I/O
	BUFFER_OBJ  *bufobj=NULL;	// Per I/O object for completed I/O
	OVERLAPPED  *lpOverlapped=NULL;	// Pointer to overlapped structure for completed I/O
	HANDLE	CompletionPort;		// Completion port handle
	DWORD	BytesTransfered,	// Number of bytes transfered
		Flags;			// Flags for completed I/O
	int	rc, 
		error;

	bool isclient = true;

	CIocpServer * gIocp = (CIocpServer *)lpParam;
	CompletionPort = gIocp->CLCompletionPort;
	ADOConn *pAdo = NULL; 

	if(gIocp->m_bAdo & 2)
	{
		pAdo = new ADOConn();
		pAdo->OpenDatabase(gIocp->m_szAdo);
	}

	while (1)
	{
		error = NO_ERROR;
		lpOverlapped = NULL;
		rc = GetQueuedCompletionStatus(
			CompletionPort,
			&BytesTransfered,
			(PULONG_PTR)&sockobj,
			&lpOverlapped,
			INFINITE
			);

		if(lpOverlapped == NULL)	
		{
#ifdef LOG_LEVEL2
			Log_Server.Write("CLCompletionThread: GetQueuedCompletionStatus failed(lpOverlapped == NULL): %d",GetLastError());
#endif
			continue;
		}
		bufobj = CONTAINING_RECORD(lpOverlapped, BUFFER_OBJ, ol);

		if (rc == FALSE)
		{ //出错时读取错误代码
			rc = WSAGetOverlappedResult(
				sockobj->s,
				&bufobj->ol,
				&BytesTransfered,
				FALSE,
				&Flags
				);
			if (rc == FALSE)
				error = WSAGetLastError();
			
		}

		gIocp->HandleIo(sockobj, bufobj, CompletionPort, BytesTransfered, error,pAdo,isclient);
	}

	if(pAdo)
		delete pAdo;

	_endthreadex(0);
	return 0;
}
Ejemplo n.º 8
0
BOOLEAN
CreateTestFile(
    VOID
    )
{
    PUCHAR     buffer;
    HANDLE     port,fileHandle;
    OVERLAPPED overlapped,*overlapped2;
    DWORD      bytesTransferred,bytesTransferred2,key;
    ULONG      numberWrites;
    BOOLEAN    status;
    ULONG      i;

    DeleteFile(FileName);

    buffer = VirtualAlloc(NULL,
                          BufferSize,
                          MEM_COMMIT,
                          PAGE_READWRITE);

    if ( !buffer ) {
        printf("Error allocating buffer %x\n",GetLastError());
        return FALSE;
    }

    fileHandle = CreateFile(FileName,
                            GENERIC_READ | GENERIC_WRITE,
                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                            NULL,
                            OPEN_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
                            NULL );

    if ( fileHandle == INVALID_HANDLE_VALUE ) {
        printf("Error opening file %s %d\n",FileName,GetLastError());
        return FALSE;
    }

    port = CreateIoCompletionPort(fileHandle,
                                  NULL,
                                  (DWORD)fileHandle,
                                  0);
    if ( !port ) {
        printf("Error creating completion port %d\n",FileName,GetLastError());
        return FALSE;
    }

    Log(1,"Creating test file %s",FileName);

    memset(&overlapped,0,sizeof(overlapped));

    numberWrites = FileSize / BufferSize;

    for (i = 0; i < numberWrites; i++) {

retryWrite:
        status = WriteFile(fileHandle,
                           buffer,
                           BufferSize,
                           &bytesTransferred,
                           &overlapped);

        if ( !status && GetLastError() != ERROR_IO_PENDING ) {
            if (GetLastError() == ERROR_INVALID_USER_BUFFER ||
                GetLastError() == ERROR_NOT_ENOUGH_QUOTA  ||
                GetLastError() == ERROR_WORKING_SET_QUOTA ||
                GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {

                goto retryWrite;
            }
            printf("Error creating test file %x\n",GetLastError());
            return FALSE;
        }

        Log(2,".");
        overlapped.Offset += BufferSize;
    }

    for (i = 0; i < numberWrites; i++ ) {
        status = GetQueuedCompletionStatus(port,
                                           &bytesTransferred2,
                                           &key,
                                           &overlapped2,
                                           (DWORD)-1);
        if ( !status ) {
            printf("Error on completion during test file create %x\n",GetLastError());
            return FALSE;
        }
    }

    Log(1,".. Complete.\n\n");
    CloseHandle(port);
    CloseHandle(fileHandle);

    VirtualFree(buffer,
                BufferSize,
                MEM_DECOMMIT);

    return TRUE;
}
Ejemplo n.º 9
0
BOOLEAN
WriteRandom(
    ULONG Iterations
    )
{
    ULONG      j,
               outstandingRequests,
               remaining = Iterations;
    ULONG      start,end;
    DOUBLE     testTime,thruPut = 0.0,seconds = 0;
    HANDLE     file,
               port;
    OVERLAPPED overlapped,
               *overlapped2;
    DWORD      bytesWritten,
               bytesWritten2,
               completionKey,
               errCode,
               version;
    BOOLEAN    status;
    PUCHAR     buffer;
    ULONG      min = FileSize,max = 0;

    printf("Starting Random Writes of %d Meg file, using %d K I/O size\n", FileSize / 1024*1024, BufferSize / 1024);

    version = GetVersion() >> 16;

    buffer = VirtualAlloc(NULL,
                          BufferSize + SectorSize - 1,
                          MEM_COMMIT | MEM_RESERVE,
                          PAGE_READWRITE);

    (ULONG)buffer &= ~(SectorSize - 1);

    if ( !buffer ) {
        Log(0,"Error allocating buffer: %x\n",GetLastError());
        return FALSE;
    }

    file = CreateFile(FileName,
                      GENERIC_READ | GENERIC_WRITE,
                      FILE_SHARE_READ | FILE_SHARE_WRITE,
                      NULL,
                      OPEN_ALWAYS,
                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
                      NULL );

    if ( file == INVALID_HANDLE_VALUE ) {
        Log(0,"Error opening Target file: %x\n",GetLastError());
        VirtualFree(buffer,
                    BufferSize + SectorSize - 1,
                    MEM_DECOMMIT);
        return FALSE;
    }

    port = CreateIoCompletionPort(file,
                                  NULL,
                                  (DWORD)file,
                                  0);
    if ( !port ) {
        Log(0,"Error creating completion port: %x\n",GetLastError());
        VirtualFree(buffer,
                    BufferSize + SectorSize - 1,
                    MEM_DECOMMIT);
        return FALSE;
    }

    while (remaining--) {

        start = GetTickCount();

        memset(&overlapped,0,sizeof(overlapped));

        outstandingRequests = 0;

        for (j = 0; j < FileSize / BufferSize; j++) {
            do {

                status = WriteFile(file,
                                  buffer,
                                  BufferSize,
                                  &bytesWritten,
                                  &overlapped);

                errCode = GetLastError();

                if (!status) {
                    if (errCode == ERROR_IO_PENDING) {
                        break;
                    } else if (errCode == ERROR_NOT_ENOUGH_QUOTA ||
                               errCode == ERROR_INVALID_USER_BUFFER ||
                               errCode == ERROR_WORKING_SET_QUOTA ||
                               errCode == ERROR_NOT_ENOUGH_MEMORY) {
                        //
                        // Allow this to retry.
                        //

                    } else {
                        Log(0,"Error in WriteFile: %x\n",errCode);
                        VirtualFree(buffer,
                                    BufferSize + SectorSize - 1,
                                    MEM_DECOMMIT);
                        return FALSE;
                    }

                }

            } while (!status);

            outstandingRequests++;
            overlapped.Offset = GetRandomOffset(0,FileSize - BufferSize);
            if (overlapped.Offset > max) {
                max = overlapped.Offset;
            }
            if (overlapped.Offset < min) {
                min = overlapped.Offset;
            }
        }

        for (j = 0; j < outstandingRequests; j++) {

            status = GetQueuedCompletionStatus(port,
                                               &bytesWritten2,
                                               &completionKey,
                                               &overlapped2,
                                               (DWORD)-1);

            if (!status) {
                Log(0,"GetQueuedCompletionStatus error: %x\n",GetLastError());
                VirtualFree(buffer,
                            BufferSize + SectorSize - 1,
                            MEM_DECOMMIT);
                return FALSE;
            }

        }

        end = GetTickCount();
        testTime = end - start;
        testTime /= 1000.0;
        seconds += testTime;
        Log(1,"Iteration %2d -> %4.3f MB/S\n",Iterations - remaining,(FileSize / testTime)/(1024*1024));

    }

    CloseHandle(port);
    CloseHandle(file);

    thruPut = FileSize * Iterations / seconds;
    printf("\nAverage Throughput %4.3f MB/S\n",thruPut/(1024*1024));
    Log(2,"Min = %Lu, Max = %Lu, FileSize = %Lu\n",min,max,FileSize);

    VirtualFree(buffer,
                BufferSize + SectorSize - 1,
                MEM_DECOMMIT);

    return TRUE;
}
Ejemplo n.º 10
0
NET_API int
net_wait(struct net_service* service, int timeout)
{
    int ret;
    int err;
    struct iocp_data* ov_data;
    PULONG_PTR data;
    DWORD bytes;
    int cnt;

#if _WIN32_WINNT >= 0x0600
    ULONG ulCount;
    ULONG ulNR;
    ULONG i;
    OVERLAPPED_ENTRY entries[32];

    cnt = 0;

    ulCount = sizeof(entries) / sizeof(OVERLAPPED_ENTRY);
    ulNR = 0;

    ov_data = 0;
    data = 0;
    bytes = 0;
    err = 0;
    while(1)
    {
        ret = GetQueuedCompletionStatusEx(service->net_service_fd, entries, ulCount, &ulNR, timeout, 0);
        err = net_get_error();
        if (err == WAIT_TIMEOUT)
        {
            err = 0;
        }
        if (!ret)
        {
            if (err)
            {
                return -err;
            }
            return cnt;
        }

        for (i = 0; i < ulNR; ++i)
        {
            ov_data = (struct iocp_data*)entries[i].lpOverlapped;
            bytes = entries[i].dwNumberOfBytesTransferred;
            if (ov_data)
            {
                switch(ov_data->op_type)
                {
                case OP_NET_ACCEPT:
                    handle_accept(service, ret, err, (struct accept_session*)ov_data);
                    break;
                case OP_NET_READ:
                    handle_read(service, ret, err, (struct read_session*)ov_data, bytes);
                    break;
                case OP_NET_WRITE:
                    handle_write(service, ret, err, (struct write_session*)ov_data, bytes);
                    break;
                case OP_NET_CONNECT:
                    handle_connect(service, ret, err, (struct connect_session *)ov_data, bytes);
                    break;
                }
            }
        }
        cnt += (int)ulNR;
    }
    return cnt;

#else
    cnt = 0;

    while(1)
    {
        ret = GetQueuedCompletionStatus(service->net_service_fd, &bytes, (PULONG_PTR) &data, (LPOVERLAPPED*)&ov_data, timeout);
        err = 0;
        if (!ret)
        {
            err = net_get_error();
        }

        if (err == WAIT_TIMEOUT)
        {
            err = 0;
        }
        if(!ov_data)
        {
            if(err)
            {
                return -err;
            }
            return cnt;
        }
        else
        {
            switch(ov_data->op_type)
            {
            case OP_NET_ACCEPT:
                handle_accept(service, ret, err, (struct accept_session*)ov_data);
                break;
            case OP_NET_READ:
                handle_read(service, ret, err, (struct read_session*)ov_data, bytes);
                break;
            case OP_NET_WRITE:
                handle_write(service, ret, err, (struct write_session*)ov_data, bytes);
                break;
            case OP_NET_CONNECT:
                handle_connect(service, ret, err, (struct connect_session *)ov_data, bytes);
                break;
            }
        }
        cnt += 1;
    }
    return cnt;
#endif
}
Ejemplo n.º 11
0
void CDirectoryWatcher::WorkerThread()
{
    DWORD numBytes;
    CDirWatchInfo * pdi = NULL;
    LPOVERLAPPED lpOverlapped;
    WCHAR buf[READ_DIR_CHANGE_BUFFER_SIZE] = {0};
    WCHAR * pFound = NULL;
    while (m_bRunning)
    {
        CleanupWatchInfo();
        if (watchedPaths.GetCount())
        {
            // Any incoming notifications?

            pdi = NULL;
            numBytes = 0;
            InterlockedExchange(&m_bCleaned, FALSE);
            if (   (!m_hCompPort)
                || !GetQueuedCompletionStatus(m_hCompPort,
                                              &numBytes,
                                              (PULONG_PTR) &pdi,
                                              &lpOverlapped,
                                              600000 /*10 minutes*/))
            {
                // No. Still trying?

                if (!m_bRunning)
                    return;

                CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": restarting watcher\n");
                m_hCompPort.CloseHandle();

                // We must sync the whole section because other threads may
                // receive "AddPath" calls that will delete the completion
                // port *while* we are adding references to it .

                AutoLocker lock(m_critSec);

                // Clear the list of watched objects and recreate that list.
                // This will also delete the old completion port

                ClearInfoMap();
                CleanupWatchInfo();

                for (int i=0; i<watchedPaths.GetCount(); ++i)
                {
                    CTSVNPath watchedPath = watchedPaths[i];

                    CAutoFile hDir = CreateFile(watchedPath.GetWinPath(),
                                            FILE_LIST_DIRECTORY,
                                            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                            NULL, //security attributes
                                            OPEN_EXISTING,
                                            FILE_FLAG_BACKUP_SEMANTICS | //required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME.
                                            FILE_FLAG_OVERLAPPED,
                                            NULL);
                    if (!hDir)
                    {
                        // this could happen if a watched folder has been removed/renamed
                        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": CreateFile failed. Can't watch directory %s\n", watchedPaths[i].GetWinPath());
                        watchedPaths.RemovePath(watchedPath);
                        break;
                    }

                    DEV_BROADCAST_HANDLE NotificationFilter;
                    SecureZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
                    NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
                    NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
                    NotificationFilter.dbch_handle = hDir;
                    // RegisterDeviceNotification sends a message to the UI thread:
                    // make sure we *can* send it and that the UI thread isn't waiting on a lock
                    int numPaths = watchedPaths.GetCount();
                    size_t numWatch = watchInfoMap.size();
                    lock.Unlock();
                    NotificationFilter.dbch_hdevnotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
                    lock.Lock();
                    // since we released the lock to prevent a deadlock with the UI thread,
                    // it could happen that new paths were added to watch, or another thread
                    // could have cleared our info map.
                    // if that happened, we have to restart watching all paths again.
                    if ((numPaths != watchedPaths.GetCount()) || (numWatch != watchInfoMap.size()))
                    {
                        ClearInfoMap();
                        CleanupWatchInfo();
                        Sleep(200);
                        break;
                    }

                    CDirWatchInfo * pDirInfo = new CDirWatchInfo(hDir, watchedPath);
                    hDir.Detach();  // the new CDirWatchInfo object owns the handle now
                    pDirInfo->m_hDevNotify = NotificationFilter.dbch_hdevnotify;


                    HANDLE port = CreateIoCompletionPort(pDirInfo->m_hDir, m_hCompPort, (ULONG_PTR)pDirInfo, 0);
                    if (port == NULL)
                    {
                        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": CreateIoCompletionPort failed. Can't watch directory %s\n", watchedPath.GetWinPath());

                        // we must close the directory handle to allow ClearInfoMap()
                        // to close the completion port properly
                        pDirInfo->CloseDirectoryHandle();

                        ClearInfoMap();
                        CleanupWatchInfo();
                        delete pDirInfo;
                        pDirInfo = NULL;

                        watchedPaths.RemovePath(watchedPath);
                        break;
                    }
                    m_hCompPort = port;

                    if (!ReadDirectoryChangesW(pDirInfo->m_hDir,
                                                pDirInfo->m_Buffer,
                                                READ_DIR_CHANGE_BUFFER_SIZE,
                                                TRUE,
                                                FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
                                                &numBytes,// not used
                                                &pDirInfo->m_Overlapped,
                                                NULL))  //no completion routine!
                    {
                        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": ReadDirectoryChangesW failed. Can't watch directory %s\n", watchedPath.GetWinPath());

                        // we must close the directory handle to allow ClearInfoMap()
                        // to close the completion port properly
                        pDirInfo->CloseDirectoryHandle();

                        ClearInfoMap();
                        CleanupWatchInfo();
                        delete pDirInfo;
                        pDirInfo = NULL;
                        watchedPaths.RemovePath(watchedPath);
                        break;
                    }

                    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": watching path %s\n", pDirInfo->m_DirName.GetWinPath());
                    watchInfoMap[pDirInfo->m_hDir] = pDirInfo;
                }
            }
            else
            {
                if (!m_bRunning)
                    return;
                if (watchInfoMap.empty())
                    continue;

                // NOTE: the longer this code takes to execute until ReadDirectoryChangesW
                // is called again, the higher the chance that we miss some
                // changes in the file system!
                if (pdi)
                {
                    BOOL bRet = false;
                    std::list<CTSVNPath> notifyPaths;
                    {
                        AutoLocker lock(m_critSec);
                        // in case the CDirectoryWatcher objects have been cleaned,
                        // the m_bCleaned variable will be set to true here. If the
                        // objects haven't been cleared, we can access them here.
                        if (InterlockedExchange(&m_bCleaned, FALSE))
                            continue;
                        if (   (!pdi->m_hDir) || watchInfoMap.empty()
                            || (watchInfoMap.find(pdi->m_hDir) == watchInfoMap.end()))
                        {
                            continue;
                        }
                        PFILE_NOTIFY_INFORMATION pnotify = (PFILE_NOTIFY_INFORMATION)pdi->m_Buffer;
                        DWORD nOffset = 0;

                        do
                        {
                            pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset);

                            if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
                                break;

                            nOffset = pnotify->NextEntryOffset;

                            if (pnotify->FileNameLength >= (READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR)))
                                continue;

                            SecureZeroMemory(buf, READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR));
                            wcsncpy_s(buf, pdi->m_DirPath, _countof(buf)-1);
                            errno_t err = wcsncat_s(buf+pdi->m_DirPath.GetLength(), READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), pnotify->FileName, min(READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), int(pnotify->FileNameLength/sizeof(TCHAR))));
                            if (err == STRUNCATE)
                            {
                                continue;
                            }
                            buf[(pnotify->FileNameLength/sizeof(TCHAR))+pdi->m_DirPath.GetLength()] = 0;

                            if (m_FolderCrawler)
                            {
                                if ((pFound = StrStrI(buf, L"\\tmp"))!=NULL)
                                {
                                    pFound += 4;
                                    if (((*pFound)=='\\')||((*pFound)=='\0'))
                                    {
                                        continue;
                                    }
                                }
                                if ((pFound = StrStrI(buf, L":\\RECYCLER"))!=NULL)
                                {
                                    if ((*(pFound + 10) == '\0') || (*(pFound + 10) == '\\'))
                                        continue;
                                }
                                if ((pFound = StrStrI(buf, L":\\$Recycle.Bin"))!=NULL)
                                {
                                    if ((*(pFound + 14) == '\0') || (*(pFound + 14) == '\\'))
                                        continue;
                                }

                                if (StrStrI(buf, L".tmp")!=NULL)
                                {
                                    // assume files with a .tmp extension are not versioned and interesting,
                                    // so ignore them.
                                    continue;
                                }
                                CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": change notification for %s\n", buf);
                                notifyPaths.push_back(CTSVNPath(buf));
                            }
                        } while ((nOffset > 0)&&(nOffset < READ_DIR_CHANGE_BUFFER_SIZE));

                        // setup next notification cycle

                        SecureZeroMemory (pdi->m_Buffer, sizeof(pdi->m_Buffer));
                        SecureZeroMemory (&pdi->m_Overlapped, sizeof(OVERLAPPED));
                        bRet = ReadDirectoryChangesW (pdi->m_hDir,
                            pdi->m_Buffer,
                            READ_DIR_CHANGE_BUFFER_SIZE,
                            TRUE,
                            FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
                            &numBytes,// not used
                            &pdi->m_Overlapped,
                            NULL);  //no completion routine!
                    }
                    if (!notifyPaths.empty())
                    {
                        for (auto nit = notifyPaths.cbegin(); nit != notifyPaths.cend(); ++nit)
                        {
                            m_FolderCrawler->AddPathForUpdate(*nit);
                        }
                    }

                    // any clean-up to do?

                    CleanupWatchInfo();

                    if (!bRet)
                    {
                        // Since the call to ReadDirectoryChangesW failed, just
                        // wait a while. We don't want to have this thread
                        // running using 100% CPU if something goes completely
                        // wrong.
                        Sleep(200);
                    }
                }
            }
        }// if (watchedPaths.GetCount())
        else
            Sleep(200);
    }// while (m_bRunning)
}
Ejemplo n.º 12
0
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
    DWORD					dwBytesTransferred = 0;
    CGateInfo*				pGateInfo = NULL;
    LPOVERLAPPED			lpOverlapped = NULL;
    char					szTmp[DATA_BUFSIZE];

    while (TRUE)
    {
        if ( GetQueuedCompletionStatus(
                    (HANDLE)CompletionPortID,
                    &dwBytesTransferred,
                    (LPDWORD)&pGateInfo,
                    (LPOVERLAPPED *)&lpOverlapped,
                    INFINITE) == 0 )
        {
            return 0;
        }

        if (g_fTerminated)
        {
            PLISTNODE		pListNode;

            if (g_xGateList.GetCount())
            {
                pListNode = g_xGateList.GetHead();

                while (pListNode)
                {
                    pGateInfo = g_xGateList.GetData(pListNode);

                    if (pGateInfo)
                        pGateInfo->Close();

                    delete pGateInfo;
                    pGateInfo = NULL;

                    pListNode = g_xGateList.RemoveNode(pListNode);
                }
            }

            return 0;
        }

        if ( dwBytesTransferred == 0 )
        {
            pGateInfo->Close();
            continue;
        }

        pGateInfo->bufLen += dwBytesTransferred;

        while ( pGateInfo->HasCompletionPacket() )
        {
            *(pGateInfo->ExtractPacket( szTmp ) - 1) = '\0';

            switch ( szTmp[1] )
            {
            case '-':
                pGateInfo->SendKeepAlivePacket();
                break;
            case 'A':
                pGateInfo->ReceiveSendUser(&szTmp[2]);
                break;
            case 'O':
                pGateInfo->ReceiveOpenUser(&szTmp[2]);
                break;
            case 'X':
                pGateInfo->ReceiveCloseUser(&szTmp[2]);
                break;
            case 'S':
                pGateInfo->ReceiveServerMsg(&szTmp[2]);
                break;
            case 'M':
                pGateInfo->MakeNewUser(&szTmp[2]);
                break;
            }
        }

        if ( pGateInfo->Recv() == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING )
        {
            InsertLogMsg(_TEXT("WSARecv() failed"));
            continue;
        }
    }

    return 0;
}
Ejemplo n.º 13
0
unsigned int WINAPI IocpManager::IoWorkerThread(LPVOID lpParam)
{
	LThreadType = THREAD_IO_WORKER;

	LIoThreadId = reinterpret_cast<int>(lpParam);
	HANDLE hComletionPort = GIocpManager->GetComletionPort();

	while (true)
	{
		DWORD dwTransferred = 0;
		OverlappedIOContext* context = nullptr;
		ULONG_PTR completionKey = 0;

		int ret = GetQueuedCompletionStatus(hComletionPort, &dwTransferred, (PULONG_PTR)&completionKey, (LPOVERLAPPED*)&context, GQCS_TIMEOUT);

		ClientSession* theClient = context ? context->mSessionObject : nullptr ;
		
		if (ret == 0 || dwTransferred == 0)
		{
			int gle = GetLastError();

			/// check time out first 
			if (gle == WAIT_TIMEOUT)
				continue;
		
			if (context->mIoType == IO_RECV || context->mIoType == IO_SEND )
			{
				CRASH_ASSERT(nullptr != theClient);

				/// In most cases in here: ERROR_NETNAME_DELETED(64)

				theClient->DisconnectRequest(DR_COMPLETION_ERROR);

				DeleteIoContext(context);

				continue;
			}
		}

		CRASH_ASSERT(nullptr != theClient);
	
		bool completionOk = false;
		switch (context->mIoType)
		{
		case IO_DISCONNECT:
			theClient->DisconnectCompletion(static_cast<OverlappedDisconnectContext*>(context)->mDisconnectReason);
			completionOk = true;
			break;

		case IO_ACCEPT:
			theClient->AcceptCompletion();
			completionOk = true;
			break;

		case IO_RECV_ZERO:
			completionOk = PreReceiveCompletion(theClient, static_cast<OverlappedPreRecvContext*>(context), dwTransferred);
			break;

		case IO_SEND:
			completionOk = SendCompletion(theClient, static_cast<OverlappedSendContext*>(context), dwTransferred);
			break;

		case IO_RECV:
			completionOk = ReceiveCompletion(theClient, static_cast<OverlappedRecvContext*>(context), dwTransferred);
			break;

		default:
			printf_s("Unknown I/O Type: %d\n", context->mIoType);
			CRASH_ASSERT(false);
			break;
		}

		if ( !completionOk )
		{
			/// connection closing
			theClient->DisconnectRequest(DR_IO_REQUEST_ERROR);
		}

		DeleteIoContext(context);
	}

	return 0;
}
Ejemplo n.º 14
0
void CZQWorkThread::Execute()
{
	DWORD dwBytestransferred;
	HANDLE  hIOCP = (HANDLE)m_parentsocket->m_hCompletionPort;
	SOCKET tsocket = INVALID_SOCKET;
	pBlock block = NULL;

	while (!Terminated())
	{
		DWORD NumberOfBytesRevced = 0;
		DWORD flag = 0;
		CZQCustomClient * client = NULL;

		BOOL ret = GetQueuedCompletionStatus(hIOCP, &dwBytestransferred, (PULONG_PTR)&client, (LPOVERLAPPED*)&block, INFINITE);

		if ((DWORD)block == SHUTDOWN_FLAG)
		{
			Terminate();
		}
		if (Terminated())
		{
			if (client != NULL)
				client->ForceClose();
			break;
		}
		if ((!ret) && dwBytestransferred == 0)
		{
			if (client != NULL)
				client->ForceClose();
			continue;
		}
// 		if ((DWORD)block == DISCONNECT_FLAG)
// 		{
// 			client->ForceClose();
// 			delete(client);
// 		}
		if (((DWORD)block == DISCONNECT_FLAG) && (client != NULL))
		{
			//释放这个客户端
			m_parentsocket->FreeClient(client);
			continue;
		}

		if ((dwBytestransferred != 0) && (ret))
		{
			switch (block->OperatorType)
			{
			case ioRead:
				client->DoRevice(block,dwBytestransferred);
				break;
			case ioWrite:
				client->DoSend(block, dwBytestransferred);
				break;
			default:
				break;
			}
		}
	}

	PostQueuedCompletionStatus(m_parentsocket->m_hCompletionPort, 0, 0, LPOVERLAPPED(SHUTDOWN_FLAG));
}
Ejemplo n.º 15
0
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
	DWORD				dwBytesTransferred;
	CGateInfo*			pGateInfo;
	LPOVERLAPPEDEX		lpOverlapped;
	_LPTMSGHEADER		pMsgHeader;
	char				completionPacket[DATA_BUFSIZE];

	while (TRUE)
	{
		GetQueuedCompletionStatus((HANDLE)CompletionPortID, &dwBytesTransferred, (LPDWORD)&pGateInfo, (LPOVERLAPPED *)&lpOverlapped, INFINITE);
		
		if (g_fTerminated) return 0L;

		if (dwBytesTransferred == 0)
		{
			if (g_xUserInfoList.GetCount())
			{
				PLISTNODE pListNode = g_xUserInfoList.GetHead();

				while (pListNode)
				{
					CUserInfo *pUserInfo = g_xUserInfoList.GetData(pListNode);

					if (pUserInfo->m_pGateInfo == pGateInfo)
					{
						pUserInfo->Lock();
						pUserInfo->m_bEmpty = true;
						pUserInfo->Unlock();
						
						// °íÃÄ¾ß µÊ
						if (pUserInfo->m_pxPlayerObject)
							pUserInfo->m_pxPlayerObject->m_pMap->RemoveObject(pUserInfo->m_pxPlayerObject->m_nCurrX,
																				pUserInfo->m_pxPlayerObject->m_nCurrY,
																				OS_MOVINGOBJECT,
																				pUserInfo->m_pxPlayerObject);
						
						pListNode = g_xUserInfoList.RemoveNode(pListNode);

						UpdateStatusBarUsers(FALSE);
					}
					else
						pListNode = g_xUserInfoList.GetNext(pListNode);
				}
			}

			closesocket(pGateInfo->m_sock);
			g_xGateList.RemoveNodeByData(pGateInfo);

			if (pGateInfo) delete pGateInfo;
			
			continue;
		}

		if (lpOverlapped->nOvFlag == OVERLAPPED_RECV)
		{
			static DWORD nLastTick = GetTickCount();
			static DWORD nBytes = 0;

			nBytes += dwBytesTransferred;

			if ( GetTickCount() - nLastTick >= 1000)
			{
				TCHAR buf[256];
				wsprintf( buf, _T("R: %d bytes/sec"), nBytes );

				nLastTick = GetTickCount();
				nBytes = 0;

				SendMessage(g_hStatusBar, SB_SETTEXT, MAKEWORD(3, 0), (LPARAM)buf);
			}	

			pGateInfo->OverlappedEx[0].bufLen += dwBytesTransferred;

			while ( pGateInfo->HasCompletionPacket() )
			{
				*(pGateInfo->ExtractPacket( completionPacket )) = '\0';

				pMsgHeader = (_LPTMSGHEADER) completionPacket;

				if ( pMsgHeader->nCode != 0xAA55AA55 )
					continue;

				switch ( pMsgHeader->wIdent )
				{
					case GM_OPEN:
					{
						pGateInfo->OpenNewUser( completionPacket );
						break;
					}
					case GM_CLOSE:
					{
						CUserInfo *pUserInfo = &g_xUserInfoArr[ pMsgHeader->wUserListIndex ];

						if (pUserInfo)
						{
							pUserInfo->m_btCurrentMode = USERMODE_LOGOFF;
							g_xLoginOutUserInfo.AddNewNode(pUserInfo);
						}

						break;
					}
					case GM_CHECKCLIENT:
					{
						pGateInfo->SendGateCheck();
						break;
					}
					case GM_RECEIVE_OK:
					{
						break;
					}
					case GM_DATA:
					{
						CUserInfo *pUserInfo = &g_xUserInfoArr[ pMsgHeader->wUserListIndex ];

						if ( !pUserInfo->IsEmpty() )
						{
							if ( pUserInfo->m_btCurrentMode == USERMODE_PLAYGAME)
							{
								if ( pMsgHeader->nSocket == pUserInfo->m_sock )
									pUserInfo->ProcessUserMessage(completionPacket + sizeof( _TMSGHEADER ) );
							}
							else
							{
								pUserInfo->Lock();
								pUserInfo->DoClientCertification( completionPacket + sizeof( _TMSGHEADER ) + sizeof(_TDEFAULTMESSAGE) );
								pUserInfo->Unlock();
							}
						}

						break;
					}
				} // switch
			} // while
	
			if ( pGateInfo->Recv() == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING )
				InsertLogMsg( _T("WSARecv() failed") );
		} // if (OVERLAPPED_RECV)
		else if (lpOverlapped->nOvFlag == OVERLAPPED_SEND)
		{
			static DWORD nLastTick = GetTickCount();
			static DWORD nBytes = 0;

			nBytes += dwBytesTransferred;

			if ( GetTickCount() - nLastTick >= 1000)
			{
				TCHAR buf[256];
				wsprintf( buf, _T("S: %d bytes/sec"), nBytes );

				nLastTick = GetTickCount();
				nBytes = 0;

				SendMessage(g_hStatusBar, SB_SETTEXT, MAKEWORD(4, 0), (LPARAM)buf);
			}	
/*			fprintf( fp, "sended\r\n" );

			pGateInfo->m_fDoSending = FALSE;
			
			if ( pGateInfo->Send( NULL ) == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING )
				InsertLogMsg( _T("WSASend() failed") );	*/
		}
	}

	return 0;
}
Ejemplo n.º 16
0
void IOThread::DoIocpJob()
{
	DWORD dwTransferred = 0;
	LPOVERLAPPED overlapped = nullptr;
	
	ULONG_PTR completionKey = 0;

	int ret = GetQueuedCompletionStatus(mCompletionPort, &dwTransferred, (PULONG_PTR)&completionKey, &overlapped, GQCS_TIMEOUT);

	if (CK_DB_RESULT == completionKey)
	{
		//-todo: DB 처리 결과가 담겨오는 경우 처리
		DatabaseJobContext* dbContext = reinterpret_cast<DatabaseJobContext*>(overlapped);
		dbContext->OnResult();



		// make switch deleter? like OverlappedIOContext in deleter...
		delete dbContext;

		return;
	}

	/// 아래로는 일반적인 I/O 처리

	OverlappedIOContext* context = reinterpret_cast<OverlappedIOContext*>(overlapped);
	
	Session* remote = context ? context->mSessionObject : nullptr;

	if (ret == 0 || dwTransferred == 0)
	{
		/// check time out first 
		if ( context == nullptr && GetLastError() == WAIT_TIMEOUT)
			return;

	
		if (context->mIoType == IO_RECV || context->mIoType == IO_SEND)
		{
			CRASH_ASSERT(nullptr != remote);

			/// In most cases in here: ERROR_NETNAME_DELETED(64)

			remote->DisconnectRequest(DR_COMPLETION_ERROR);

			DeleteIoContext(context);

			return;
		}
	}

	CRASH_ASSERT(nullptr != remote);

	bool completionOk = false;
	switch (context->mIoType)
	{
	case IO_CONNECT:
		dynamic_cast<ServerSession*>(remote)->ConnectCompletion();
		completionOk = true;
		break;

	case IO_DISCONNECT:
		remote->DisconnectCompletion(static_cast<OverlappedDisconnectContext*>(context)->mDisconnectReason);
		completionOk = true;
		break;

	case IO_ACCEPT:
		dynamic_cast<ClientSession*>(remote)->AcceptCompletion();
		completionOk = true;
		break;

	case IO_RECV_ZERO:
		completionOk = remote->PostRecv();
		break;

	case IO_SEND:
		remote->SendCompletion(dwTransferred);

		if (context->mWsaBuf.len != dwTransferred)
			printf_s("Partial SendCompletion requested [%d], sent [%d]\n", context->mWsaBuf.len, dwTransferred);
		else
			completionOk = true;
		
		break;

	case IO_RECV:
		remote->RecvCompletion(dwTransferred);
	
		/// for test
		//remote->EchoBack();
		remote->Handle_CS_MOVE(); // test

		completionOk = remote->PreRecv();

		break;

	default:
		printf_s("Unknown I/O Type: %d\n", context->mIoType);
		CRASH_ASSERT(false);
		break;
	}

	if (!completionOk)
	{
		/// connection closing
		remote->DisconnectRequest(DR_IO_REQUEST_ERROR);
	}

	DeleteIoContext(context);
	
}
Ejemplo n.º 17
0
static unsigned __stdcall IocpWorkThread(void *CompletionPortID)
{
	HANDLE CompletionPort = (HANDLE)CompletionPortID;

	while (TRUE) {
		BOOL FIsSuc;
		PIOCPOverlapped FIocpOverlapped;
		CSocketBase *SockBase;
		CSocketObj *SockObj = NULL;
		CSocketLst *SockLst = NULL;
		BOOL _IsSockObj = FALSE;
		DWORD BytesTransferred;
		INT resuInt;

		FIsSuc = GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
			(PULONG_PTR)&SockBase, (LPOVERLAPPED*)&FIocpOverlapped, INFINITE);
		if (SockBase != NULL) {
			assert(SockBase == FIocpOverlapped->AssignedSockObj);
			_IsSockObj = SockBase->mSocketType == STObj;
			if (_IsSockObj) {
				SockObj = static_cast<CSocketObj*>(SockBase);
			} else {
				SockLst = static_cast<CSocketLst*>(SockBase);
			}
		} else {
			// IOCP 线程退出指令
			// 退出
			OutputDebugStr(_T("获得退出命令,退出并命令下一线程退出。\n"));
			// 通知下一个工作线程退出
			PostQueuedCompletionStatus(CompletionPort, 0, 0, NULL);
			break;
		}
		if (FIsSuc) {
			// 如果是退出线程消息,则退出
			BOOL _NeedContinue = FALSE;
			SOCKET tmpSock;
			PCSocketObj _NewSockObj;

			switch (FIocpOverlapped->OverlappedType) {
			case otRecv:case otSend:
				if (BytesTransferred == 0) {
					assert(FIocpOverlapped == SockObj->GetAssignedOverlapped());
					OutputDebugStr(_T("socket(%d)已关闭:%d\n"), SockObj->GetSocket(), WSAGetLastError());
					// 减少引用
					SockObj->InternalDecRefCount();
					// 继续
					_NeedContinue = TRUE;
					break;
				}
				// socket事件
				switch (FIocpOverlapped->OverlappedType){
				case otRecv:
					assert(FIocpOverlapped == SockObj->GetAssignedOverlapped());
					// 移动当前接受的指针
					FIocpOverlapped->RecvDataLen = BytesTransferred;
					FIocpOverlapped->RecvData = SockObj->GetRecvBuf();
					// 获取事件指针
					// 发送结果
					// 产生事件
					try{
						SockObj->GetOwner()->OnIOCPEvent(ieRecvAll, SockObj, FIocpOverlapped);
					}
					catch (...) {
						OutputDebugStr(_T("SockObj->GetOwner()->OnIOCPEvent ieRecvAll throw an exception\n"));
					}
					// 投递下一个WSARecv
					if (!SockObj->WSARecv()) {
						// 如果出错
						OutputDebugStr(_T("WSARecv函数出错socket=%d:%d\n"), SockObj->GetSocket(), WSAGetLastError());
						// 减少引用
						SockObj->InternalDecRefCount();
					}
					break;
				case otSend:
					// 获取事件指针
					// 数据指针后移
					FIocpOverlapped->CurSendData = (PVOID)((PBYTE)FIocpOverlapped->CurSendData + BytesTransferred);
					// 如果已全部发送完成,释放内存
					if ((ULONG_PTR)FIocpOverlapped->CurSendData -
						(ULONG_PTR)FIocpOverlapped->SendData == (ULONG_PTR)FIocpOverlapped->SendDataLen) {
						BOOL _NeedDecSockObj;

						// 触发事件
						try{
							SockObj->GetOwner()->OnIOCPEvent(ieSendAll, SockObj, FIocpOverlapped);
						}
						catch (...) {
							OutputDebugStr(_T("SockObj->GetOwner()->OnIOCPEvent ieSendAll throw an exception\n"));
						}
						SockObj->GetOwner()->GetOwner()->DelOverlapped(FIocpOverlapped);
						// 获取待发送的数据
						FIocpOverlapped = NULL;
						SockObj->GetOwner()->Lock();
						assert(SockObj->GetIsSending());
						if (SockObj->GetSendDataQueue().size() > 0) {
							FIocpOverlapped = SockObj->GetSendDataQueue().front();
							SockObj->GetSendDataQueue().pop();
							OutputDebugStr(_T("Socket(%d)取出待发送数据\n"), SockObj->GetSocket());
						} else {
							SockObj->SetIsSending(FALSE);
						}
						SockObj->GetOwner()->Unlock();
						// 默认减少Socket引用
						_NeedDecSockObj = TRUE;
						if (FIocpOverlapped != NULL) {
							if (!SockObj->WSASend(FIocpOverlapped)) {
								// 如果有错误
								OutputDebugStr(_T("IocpWorkThread:WSASend函数失败(socket=%d):%d\n"), SockObj->GetSocket(), WSAGetLastError());
								// 触发事件
								try{
									SockObj->GetOwner()->OnIOCPEvent(ieSendFailed, SockObj, FIocpOverlapped);
								}
								catch (...) {
									OutputDebugStr(_T("SockObj->GetOwner()->OnIOCPEvent ieSendFailed throw an exception\n"));
								}
								SockObj->GetOwner()->GetOwner()->DelOverlapped(FIocpOverlapped);
							} else {
								// 发送成功,不减少引用
								_NeedDecSockObj = FALSE;
							}
						}
						if (_NeedDecSockObj) {
							// 减少引用
							SockObj->InternalDecRefCount();
						}
					} else {
						// 没有全部发送完成
						FIocpOverlapped->DataBuf.len = FIocpOverlapped->SendDataLen +
							(ULONG)((ULONG_PTR)FIocpOverlapped->SendData -
							(ULONG_PTR)FIocpOverlapped->CurSendData);
						FIocpOverlapped->DataBuf.buf = (CHAR *)FIocpOverlapped->CurSendData;
						try{
							SockObj->GetOwner()->OnIOCPEvent(ieSendPart, SockObj, FIocpOverlapped);
						}
						catch (...) {
							OutputDebugStr(_T("SockObj->GetOwner()->OnIOCPEvent ieSendAll throw an exception\n"));
						}
						// 继续投递WSASend
						if (!SockObj->WSASend(FIocpOverlapped)) {
							// 如果有错误
							OutputDebugStr(_T("IocpWorkThread:WSASend函数失败(socket=%d):%d\n"), SockObj->GetSocket(), WSAGetLastError());
							// 触发事件
							try{
								SockObj->GetOwner()->OnIOCPEvent(ieSendFailed, SockObj, FIocpOverlapped);
							}
							catch (...) {
								OutputDebugStr(_T("SockObj->GetOwner()->OnIOCPEvent ieSendFailed throw an exception\n"));
							}
							SockObj->GetOwner()->GetOwner()->DelOverlapped(FIocpOverlapped);
							// 减少引用
							SockObj->InternalDecRefCount();
						}
					}
					break;


				default:
					break;
				}
				break;
			case otListen:
				assert(FIocpOverlapped == SockLst->GetAssignedOverlapped());
				/*
				GetAcceptExSockaddrs(SockLst->mLstBuf, 0, sizeof(SOCKADDR_IN) + 16,
				sizeof(SOCKADDR_IN) + 16, local, localLen, remote, remoteLen);
				*/
				tmpSock = SockLst->GetSocket();
				// 更新上下文
				resuInt = setsockopt(FIocpOverlapped->AcceptSocket, SOL_SOCKET,
					SO_UPDATE_ACCEPT_CONTEXT, (char *)&tmpSock, sizeof(tmpSock));
				if (resuInt != 0) {
					OutputDebugStr(_T("socket(%d)设置setsockopt失败:%d\n"),
						FIocpOverlapped->AcceptSocket, WSAGetLastError());
				}
				// 监听
				// 产生事件,添加SockObj,如果失败,则close之
				_NewSockObj = NULL;
				// 创建新的SocketObj类
				SockLst->CreateSockObj(_NewSockObj);
				// 填充Socket句柄
				_NewSockObj->mSock = FIocpOverlapped->AcceptSocket;
				// 设置为服务socket
				_NewSockObj->mIsSerSocket = TRUE;
				// 添加到Socket列表中
				SockLst->GetOwner()->AddSockBase(_NewSockObj);
				// 投递下一个Accept端口
				if (!SockLst->Accept()){
					OutputDebugStr(_T("AcceptEx函数失败: %d\n"), WSAGetLastError());
					SockLst->InternalDecRefCount();
				}
				break;
			}
			if (_NeedContinue) {
				continue;
			}
		} else {
			if (FIocpOverlapped != NULL) {
				OutputDebugStr(_T("GetQueuedCompletionStatus函数失败(socket=%d): %d\n"),
					SockBase->GetSocket(), GetLastError());
				// 关闭
				if (FIocpOverlapped != SockBase->GetAssignedOverlapped()) {
					// 只有otSend的FIocpOverlapped
					assert(FIocpOverlapped->OverlappedType == otSend);
					SockBase->GetOwner()->GetOwner()->DelOverlapped(FIocpOverlapped);
				}
				// 减少引用
				SockBase->InternalDecRefCount();
			} else {
				OutputDebugStr(_T("GetQueuedCompletionStatus函数失败: %d\n"), GetLastError());
			}
		}
	}
	_endthreadex(0);
	return 0;
}
Ejemplo n.º 18
0
int
MPIU_ExProcessCompletions(
    MPIU_ExSetHandle_t Set,
    BOOL *fWaitForEventAndStatus
    )
{
    DWORD Timeout;

    MPIU_Assert(fWaitForEventAndStatus != NULL);
    MPIU_Assert(IsValidSet(Set));

    Timeout =  (*fWaitForEventAndStatus) ? INFINITE : 0;

    for (;;)
    {
        BOOL fSucc;
        DWORD BytesTransfered = 0;
        ULONG_PTR Key;
        OVERLAPPED* pOverlapped = NULL;

        fSucc = GetQueuedCompletionStatus(
                    Set,
                    &BytesTransfered,
                    &Key,
                    &pOverlapped,
                    Timeout
                    );

        if(!fSucc){
            /* Could be a timeout or an error */
            *fWaitForEventAndStatus = FALSE;
        }
        else{
            /* An Event completed */
            *fWaitForEventAndStatus = TRUE;
        }
        if(!fSucc && pOverlapped == NULL)
        {
            //
            // Return success on timeout per caller request. The Executive progress
            // engine will not wait for the async processing to complete
            //
            DWORD gle = GetLastError();
            if (gle == WAIT_TIMEOUT)
                return MPI_SUCCESS;

            /* FIXME: Should'nt there be a retry count ? */
            //
            // Io Completion port internal error, try again
            //
            continue;
        }
        
        MPIU_Assert(Key < _countof(s_processors));
        MPIU_Assert(s_processors[Key] != NULL);


        //
        // Call the completion processor and return the result.
        //
        return s_processors[Key](BytesTransfered, pOverlapped);
    }
}
Ejemplo n.º 19
0
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
	DWORD					dwBytesTransferred = 0;

	CSessionInfo*			pSessionInfo = NULL;
	_LPTCOMPLETIONPORT		lpPerIoData = NULL;

	char					szPacket[DATA_BUFSIZE * 2];
	char					szMsg[32];
	char					*pszPos;

	while (TRUE)
	{
		if ( GetQueuedCompletionStatus( 
										(HANDLE)CompletionPortID, 
										&dwBytesTransferred, 
										(LPDWORD)&pSessionInfo, 										
										(LPOVERLAPPED *)&lpPerIoData, 
										INFINITE) == 0)
		{
			if (g_fTerminated)
				return 0;

			if (pSessionInfo)
			{
				szMsg[0] = '%';
				szMsg[1] = 'X';

				char *pszPos = ValToAnsiStr((int)pSessionInfo->sock, &szMsg[2]);

				*pszPos++	= '$';
				*pszPos		= '\0';

				SendExToServer(szMsg); 

				g_xSessionList.RemoveNodeByData(pSessionInfo);

				closesocket(pSessionInfo->sock);
				pSessionInfo->sock = INVALID_SOCKET;

				UpdateStatusBar(FALSE);

				GlobalFree(pSessionInfo);
			}

			continue;
		}

		if (g_fTerminated)
			return 0;

		if (dwBytesTransferred == 0)
		{
			szMsg[0] = '%';
			szMsg[1] = 'X';

			char *pszPos = ValToAnsiStr((int)pSessionInfo->sock, &szMsg[2]);

			*pszPos++	= '$';
			*pszPos		= '\0';

			SendExToServer(szMsg); 

			g_xSessionList.RemoveNodeByData(pSessionInfo);

			closesocket(pSessionInfo->sock);
			pSessionInfo->sock = INVALID_SOCKET;

			UpdateStatusBar(FALSE);

			GlobalFree(pSessionInfo);

			continue;
		}


		// ORZ:
		pSessionInfo->bufLen += dwBytesTransferred;

		while ( pSessionInfo->HasCompletionPacket() )
		{
			szPacket[0]	= '%';
			szPacket[1]	= 'A';
			pszPos		= ValToAnsiStr( (int) pSessionInfo->sock, &szPacket[2] );
			*pszPos++	= '/';
			pszPos		= pSessionInfo->ExtractPacket( pszPos );
			*pszPos++	= '$';
			*pszPos		= '\0';

			SendExToServer( szPacket );
		}

		// ORZ:
		if ( pSessionInfo->Recv() == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING )
		{
				InsertLogMsg(_TEXT("WSARecv() failed"));
			
				CloseSession(pSessionInfo->sock);
				continue;
		}
	}

	return 0;
}
Ejemplo n.º 20
0
DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{

	HANDLE                  CompletionPort=(HANDLE)CompletionPortID;
	DWORD                   dwBytesTransferred;
	SOCKET                  sClient;
	LPPER_IO_OPERATION_DATA lpPerIOData = NULL;

	while (TRUE)
	{

		GetQueuedCompletionStatus(
			CompletionPort,
			&dwBytesTransferred,
			 (ULONG_PTR *)&sClient,
			(LPOVERLAPPED *)&lpPerIOData,
			INFINITE
		);

		if (dwBytesTransferred == 0xFFFFFFFF)
		{
			return 0;
		}

		if (lpPerIOData->OperationType == RECV_POSTED)
		{
			if (dwBytesTransferred == 0)
			{
				// Connection was closed by client
				printf("client close\r\n");
				closesocket(sClient);
				HeapFree(GetProcessHeap(), 0, lpPerIOData);
			}
			else
			{
				printf("%s\r\n",lpPerIOData->szMessage);

			lpPerIOData->szMessage[dwBytesTransferred] = '\0';
			send(sClient, lpPerIOData->szMessage, dwBytesTransferred, 0);

			// Launch another asynchronous operation for sClient
			memset(lpPerIOData, 0, sizeof(PER_IO_OPERATION_DATA));

			lpPerIOData->Buffer.len = MSGSIZE;
			lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
			lpPerIOData->OperationType = RECV_POSTED;

			WSARecv(
				sClient,
				&lpPerIOData->Buffer,
				1,
				&lpPerIOData->NumberOfBytesRecvd,
				&lpPerIOData->Flags,
				&lpPerIOData->overlap,
				NULL
			);

			}

		}

	}

	return 0;

}
Ejemplo n.º 21
0
void XEWinSocketSvr::WorkThread()
{
	unsigned long readbytes;
	unsigned long dwCompKey;
//	OVERLAPPED * pOverlap;
	XE::xOVERLAPPED* pOverlap = nullptr;
	while( 1 ) {
		// 클라이언트로부터 데이타가 오길 기다림
		BOOL bRet = GetQueuedCompletionStatus( m_hIOCP, &readbytes, &dwCompKey, (LPOVERLAPPED*)&pOverlap, INFINITE );
		// TODO:
#pragma message("리턴값처리 제대로 할것. ")
		if( bRet == FALSE ) {
			auto err = GetLastError();
			TCHAR* szMsg = nullptr;
			FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER
									, nullptr
									, err
									, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT)
									, (TCHAR*)&szMsg
									, 0
									, nullptr );
			if( pOverlap == nullptr )	{
				return;
			} else {
				if( readbytes ) {
					// 패킷을 dequeue했지만 실패한I/O에 대한 dequeue였다.
				} else {
					// 클라이언트 소켓 close
				}
			}
		} else {
			if( pOverlap == nullptr )
				return;
		}
		const auto typeEvent = pOverlap->typeEvent;
		if( bRet == FALSE && pOverlap == nullptr ) {
			return;
		}
		// 어떤 커넥션으로부터 데이타가 도착함.
		// 어떤 클라이언트 연결로부터 왔는지 알아냄
		ID idConnect = (ID)dwCompKey;
		// 해당 커넥션객체를 찾음.
		auto spConnect = FindspConnect( idConnect );	// 스레드안전
		//
		if( spConnect ) {
			XAUTO_LOCK3( spConnect );
			//
			if( readbytes != 0 ) {
#if _DEV_LEVEL <= DLV_DEV_EXTERNAL
				if( spConnect->IsDisconnected() ) {
					CONSOLE( "connect", "끊어진 소켓에서 IOCP발생" );
				}
#endif
				// 받은 데이터를 큐에 밀어넣음
				// 접속되고 곧바로 recv가 온다면 커넥션객체에 채 XUser가 붙기도 전에 이게 호출될수도 있음.
				// 그러므로 그런패킷은 일단 커넥션 큐안에 쌓아둬야 한다.
				if( !spConnect->IsDisconnected() && !spConnect->IsbDestroy() ) {
					if( typeEvent == 1 ) {		// send의 완료는 따로 처리할것이 없음.
						// send
						continue;
// 						spConnect->SendData( )
					}
					else {
						// recv
						spConnect->tRecvData( readbytes );
#if _DEV_LEVEL <= DLV_OPEN_BETA
						const int sizeQ = spConnect->GetSizeQueue();
						// 최대 큐크기 표시용
						if( sizeQ > m_sizeMaxQ )
							m_sizeMaxQ = sizeQ;
#endif
						// 비동기 recv를 큐에 올림
						spConnect->tWSARecv();
					}
				}
			} else 	{
				// 접속 끊김
				// 서버의 다른데서 소켓닫으면 여기로 들어오나?
				spConnect->Set_bConnected( FALSE );		// 연결해제 플래그만 켜고 실제 삭제처리는 메인스레드에서.
				if( bRet && pOverlap == nullptr ) {
					spConnect->DoDisconnect();
					return;
				}
				BTRACE( "disconnected:%s", GetszName() );
				continue;		// 끊긴 커넥션이므로 더이상 처리안해도 된다.
			} // if( readbytes == 0 )	{	// 접속 끊김
		} else {
#if (_DEV_LEVEL <= DLV_DEV_EXTERNAL) && !defined(_XBOT)
			CONSOLE( "이미 삭제되거나 없는 연결에서 데이타가 도착했습니다." );
#endif
		} // if( pConn ) {
		Sleep( m_msecSleepRecv );
	} // while(1)
} // WorkThread()
Ejemplo n.º 22
0
	void run()
	{
		while(isActive())
		{
		//	printf("wait at iocp work thread...\n");
			OVERLAPPED *pOverlapped = NULL;
			SocketContent		 *pSocketContext = NULL;
			DWORD                dwBytesTransfered = 0;
			BOOL bReturn = GetQueuedCompletionStatus(
				pool->m_hIOCompletionPort,
				&dwBytesTransfered,
				(PULONG_PTR)&pSocketContext,
				&pOverlapped,
				INFINITE
			);
			// 如果收到的是退出标志,则直接退出
			if ( EXIT_CODE==(DWORD)pSocketContext )
			{
				break;
			}
			
			// 判断是否出现了错误
			if( !bReturn )  
			{  
				DWORD dwErr = GetLastError();
		//		printf("do error\n");
				// 显示一下提示信息
				if( !pool->HandleError( pSocketContext,dwErr ) )
				{
					continue;
				}

				continue;  
			}  
			else  
			{
				// 读取传入的参数
				IoContent* pIoContext = CONTAINING_RECORD(pOverlapped, IoContent, overlapped);  

				// 判断是否有客户端断开了
				if((0 == dwBytesTransfered) && ( RECV_POSTED==pIoContext->optype || SEND_POSTED==pIoContext->optype))  
				{  
			//		pool->_ShowMessage( _T("客户端 %s:%d 断开连接."),inet_ntoa(pSocketContext->m_ClientAddr.sin_addr), ntohs(pSocketContext->m_ClientAddr.sin_port) );

					// 释放掉对应的资源
					if (pool->closedelegate)
							pool->closedelegate->handleClose(pSocketContext);
					pool->_RemoveContext( pSocketContext );
			//		printf("do error\n");
 					continue;  
				}  
				else
				{
					if (!pSocketContext->checkValid())
					{
						pSocketContext->getHandle().close();
						if (pool->closedelegate)
							pool->closedelegate->handleClose(pSocketContext);
						pool->_RemoveContext( pSocketContext );
						continue;
					}
					switch( pIoContext->optype )  
					{  
						 // Accept  
						case ACCEPT_POSTED:
						{ 
							// 为了增加代码可读性,这里用专门的_DoAccept函数进行处理连入请求
			//				printf("do post\n");
							pool->_DoAccpet( pSocketContext, pIoContext );						
						}
						break;

						// RECV
						case RECV_POSTED:
						{
							// 为了增加代码可读性,这里用专门的_DoRecv函数进行处理接收请求
			//				printf("do recv\n");
							pool->_DoRecv( pSocketContext,pIoContext ,dwBytesTransfered);
						}
						break;

						// SEND
						// 这里略过不写了,要不代码太多了,不容易理解,Send操作相对来讲简单一些
						case SEND_POSTED:
						{
				//			printf("do send\n");
							pool->_DoSend(pSocketContext,pIoContext,dwBytesTransfered);
						}
						break;
						default:
							break;
					} //switch

					
				}
			}
		}
		printf("work thread over\n");
	}
Ejemplo n.º 23
0
unsigned int WINAPI IocpManager::IoWorkerThread(LPVOID lpParam)
{
	LThreadType = THREAD_IO_WORKER;

	LIoThreadId = reinterpret_cast<int>(lpParam);
	HANDLE hCompletionPort = GIocpManager->GetCompletionPort();

	printf_s("Started thread for completion port %d \n", hCompletionPort);

	while (true)
	{
		DWORD dwTransferred = 0;
		OverlappedIOContext* context = nullptr;
		ClientSession* asCompletionKey = nullptr;

		int ret = GetQueuedCompletionStatus(
				hCompletionPort,					//	_In_   HANDLE CompletionPort,
				&dwTransferred,					//	Out_  LPDWORD lpNumberOfBytes,
				(PULONG_PTR)&asCompletionKey,	//	_Out_  PULONG_PTR lpCompletionKey,
				(LPOVERLAPPED*)&context,			//	_Out_  LPOVERLAPPED *lpOverlapped,
				GQCS_TIMEOUT					//	_In_   DWORD dwMilliseconds
			); 
				

		/// check time out first 
		if (ret == 0 && GetLastError()==WAIT_TIMEOUT)
			continue;

		if (ret == 0 || dwTransferred == 0)
		{
			/// connection closing
			asCompletionKey->Disconnect(DR_RECV_ZERO);
			GSessionManager->DeleteClientSession(asCompletionKey);
			continue;
		}

		if (context == nullptr)
		{
			asCompletionKey->Disconnect(DR_RECV_ZERO);
			GSessionManager->DeleteClientSession(asCompletionKey);

		}

		bool completionOk = true;
		switch (context->mIoType)
		{
		case IO_SEND:
			completionOk = SendCompletion(asCompletionKey, context, dwTransferred);
			break;

		case IO_RECV:
			completionOk = ReceiveCompletion(asCompletionKey, context, dwTransferred);
			break;

		default:
			printf_s("Unknown I/O Type: %d\n", context->mIoType);
			break;
		}

		if ( !completionOk )
		{
			/// connection closing
			asCompletionKey->Disconnect(DR_COMPLETION_ERROR);
			GSessionManager->DeleteClientSession(asCompletionKey);
		}

	}

	return 0;
}
Ejemplo n.º 24
0
int api_loop_run_internal(api_loop_t* loop)
{
    BOOL status;
    DWORD transfered;
    ULONG_PTR key;
    OVERLAPPED* overlapped;
    DWORD error;
    BOOL failed;
    os_win_t* win;

    api_scheduler_init(&loop->base.scheduler);
    loop->base.scheduler.pool = &loop->base.pool;
	
    loop->base.now = api_time_current();
    loop->base.last_activity = loop->base.now;

    api_loop_ref(loop);

    do
    {
        if (0 < api_timer_process(&loop->base.sleeps, TIMER_Sleep, loop->base.now))
        {
            loop->base.now = api_time_current();
            loop->base.last_activity = loop->base.now;
        }

        failed = 0;
        error = 0;
        status = GetQueuedCompletionStatus(loop->iocp, &transfered, &key,
            &overlapped, (DWORD)api_loop_calculate_wait_timeout(&loop->base));

        loop->base.now = api_time_current();

        if (status == FALSE)
        {
            failed = 1;
            error = GetLastError();

            if (overlapped == NULL)
            {
                /*
                 * Completion port closed, propably by api_loop_stop
                 */
                if (error == ERROR_ABANDONED_WAIT_0)
                {
                    loop->iocp = NULL;
                    failed = 1;
                    break;
                }

                if (error == WAIT_TIMEOUT)
                {
                    failed = 0;
                    key = 0;

                    if (0 < api_timer_process(&loop->base.idles, TIMER_Idle,
                                        loop->base.now - loop->base.last_activity))
                    {
                        loop->base.now = api_time_current();
                        loop->base.last_activity = loop->base.now;
                    }
                }
            }

            if (overlapped != NULL)
            {
                /*
                 * Eof or Connection was closed
                 */
                if (transfered == 0)
                {
                    failed = 0;
                }
            }
        }

        if (!failed && key != 0)
        {
            win = (os_win_t*)key;
            win->processor(win, transfered, overlapped, loop, error);
            loop->base.now = api_time_current();
            loop->base.last_activity = loop->base.now;
        }

        api_timer_process(&loop->base.timeouts, TIMER_Timeout,
                loop->base.now - loop->base.last_activity);

        loop->base.now = api_time_current();
    }
    while (!failed);

    if (API__OK != api_loop_cleanup(loop))
    {
        /* handle error */
    }

    if (loop->iocp != NULL)
    {
        if (!CloseHandle(loop->iocp))
        {
            /* handle error when eopll not closed already */
        }
    }

    return API__OK;
}
Ejemplo n.º 25
0
DWORD CDirWatcher::WatchProc()
{
	DWORD dwNumBytes;
	CDirWatcher* p;
	LPOVERLAPPED lpOverlapped;
	DWORD cbOffset;
	PFILE_NOTIFY_INFORMATION pfni;
	WCHAR szBuf[MAX_PATH];

	do 
	{
		GetQueuedCompletionStatus(m_hCompPort,
			&dwNumBytes, (LPDWORD)&p, &lpOverlapped, INFINITE);

		if (p != NULL)
		{
			pfni = (PFILE_NOTIFY_INFORMATION)m_lpBuffer;
			do 
			{
				cbOffset = pfni->NextEntryOffset;
				
				switch (pfni->Action) 
				{
				case FILE_ACTION_ADDED:
					{
						CFileChangeInfo* pFileChangeInfo = new CFileChangeInfo;
						
						memcpy(szBuf, pfni->FileName, pfni->FileNameLength);
						*((WCHAR *)((BYTE *)szBuf + pfni->FileNameLength)) = 0;
						pFileChangeInfo->strName = szBuf;
						pFileChangeInfo->nType = FileChange_Add;

						PostMessage(m_hNotifyWnd, m_nWatchNotifyMsg, 0, LPARAM(pFileChangeInfo));
					}
					break;
				case FILE_ACTION_REMOVED:
					{
						CFileChangeInfo* pFileChangeInfo = new CFileChangeInfo;

						memcpy(szBuf, pfni->FileName, pfni->FileNameLength);
						*((WCHAR *)((BYTE *)szBuf + pfni->FileNameLength)) = 0;
						pFileChangeInfo->strName = szBuf;
						pFileChangeInfo->nType = FileChange_Remove;
						
						PostMessage(m_hNotifyWnd, m_nWatchNotifyMsg, 0, LPARAM(pFileChangeInfo));
					}
					break;
				case FILE_ACTION_RENAMED_OLD_NAME:
					{
						CFileChangeInfo* pFileChangeInfo = new CFileChangeInfo;

						memcpy(szBuf, pfni->FileName, pfni->FileNameLength);
						*((WCHAR *)((BYTE *)szBuf + pfni->FileNameLength)) = 0;
						pFileChangeInfo->strName = szBuf;

						pfni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pfni + cbOffset);
						ATLASSERT(pfni->Action == FILE_ACTION_RENAMED_NEW_NAME);

						memcpy(szBuf, pfni->FileName, pfni->FileNameLength);
						*((WCHAR *)((BYTE *)szBuf + pfni->FileNameLength)) = 0;
						pFileChangeInfo->strNewName = szBuf;

						pFileChangeInfo->nType = FileChange_Rename;

						PostMessage(m_hNotifyWnd, m_nWatchNotifyMsg, 0, LPARAM(pFileChangeInfo));

						cbOffset = pfni->NextEntryOffset;
					}
					break;
				default:
					break;
				}
						
				pfni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pfni + cbOffset); 
			} while (cbOffset); 

			ReadDirectoryChangesW(m_hFileHandle, m_lpBuffer, 4096,
				FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, &m_dwSize, &m_overlapped, NULL);
		}
		
	} while(p != NULL);

	return 0;
}
Ejemplo n.º 26
0
/*
 * Poll the I/O Completion Port, execute callback,
 * and return the key and bytes transfered of the last operation.
 */
static pj_bool_t poll_iocp( HANDLE hIocp, DWORD dwTimeout,
                            pj_ssize_t *p_bytes, pj_ioqueue_key_t **p_key )
{
    DWORD dwBytesTransfered, dwKey;
    generic_overlapped *pOv;
    pj_ioqueue_key_t *key;
    pj_ssize_t size_status = -1;
    BOOL rcGetQueued;

    /* Poll for completion status. */
    rcGetQueued = GetQueuedCompletionStatus(hIocp, &dwBytesTransfered,
                                            &dwKey, (OVERLAPPED**)&pOv,
                                            dwTimeout);

    /* The return value is:
     * - nonzero if event was dequeued.
     * - zero and pOv==NULL if no event was dequeued.
     * - zero and pOv!=NULL if event for failed I/O was dequeued.
     */
    if (pOv) {
        pj_bool_t has_lock;

        /* Event was dequeued for either successfull or failed I/O */
        key = (pj_ioqueue_key_t*)dwKey;
        size_status = dwBytesTransfered;

        /* Report to caller regardless */
        if (p_bytes)
            *p_bytes = size_status;
        if (p_key)
            *p_key = key;

#if PJ_IOQUEUE_HAS_SAFE_UNREG
        /* We shouldn't call callbacks if key is quitting. */
        if (key->closing)
            return PJ_TRUE;

        /* If concurrency is disabled, lock the key
         * (and save the lock status to local var since app may change
         * concurrency setting while in the callback) */
        if (key->allow_concurrent == PJ_FALSE) {
            pj_mutex_lock(key->mutex);
            has_lock = PJ_TRUE;
        } else {
            has_lock = PJ_FALSE;
        }

        /* Now that we get the lock, check again that key is not closing */
        if (key->closing) {
            if (has_lock) {
                pj_mutex_unlock(key->mutex);
            }
            return PJ_TRUE;
        }

        /* Increment reference counter to prevent this key from being
         * deleted
         */
        pj_atomic_inc(key->ref_count);
#else
        PJ_UNUSED_ARG(has_lock);
#endif

        /* Carry out the callback */
        switch (pOv->operation) {
        case PJ_IOQUEUE_OP_READ:
        case PJ_IOQUEUE_OP_RECV:
        case PJ_IOQUEUE_OP_RECV_FROM:
            pOv->operation = 0;
            if (key->cb.on_read_complete)
                key->cb.on_read_complete(key, (pj_ioqueue_op_key_t*)pOv,
                                         size_status);
            break;
        case PJ_IOQUEUE_OP_WRITE:
        case PJ_IOQUEUE_OP_SEND:
        case PJ_IOQUEUE_OP_SEND_TO:
            pOv->operation = 0;
            if (key->cb.on_write_complete)
                key->cb.on_write_complete(key, (pj_ioqueue_op_key_t*)pOv,
                                          size_status);
            break;
#if PJ_HAS_TCP
        case PJ_IOQUEUE_OP_ACCEPT:
            /* special case for accept. */
            ioqueue_on_accept_complete(key, (ioqueue_accept_rec*)pOv);
            if (key->cb.on_accept_complete) {
                ioqueue_accept_rec *accept_rec = (ioqueue_accept_rec*)pOv;
                pj_status_t status = PJ_SUCCESS;
                pj_sock_t newsock;

                newsock = accept_rec->newsock;
                accept_rec->newsock = PJ_INVALID_SOCKET;

                if (newsock == PJ_INVALID_SOCKET) {
                    int dwError = WSAGetLastError();
                    if (dwError == 0) dwError = OSERR_ENOTCONN;
                    status = PJ_RETURN_OS_ERROR(dwError);
                }

                key->cb.on_accept_complete(key, (pj_ioqueue_op_key_t*)pOv,
                                           newsock, status);

            }
            break;
        case PJ_IOQUEUE_OP_CONNECT:
#endif
        case PJ_IOQUEUE_OP_NONE:
            pj_assert(0);
            break;
        }

#if PJ_IOQUEUE_HAS_SAFE_UNREG
        decrement_counter(key);
        if (has_lock)
            pj_mutex_unlock(key->mutex);
#endif

        return PJ_TRUE;
    }

    /* No event was queued. */
    return PJ_FALSE;
}
Ejemplo n.º 27
0
static void *
wt_monitor_job_win32 (void *vmonitor)
{
    SeafWTMonitor *monitor = vmonitor;
    SeafWTMonitorPriv *priv = monitor->priv;
    /* 2 * sizeof(inotify_event) + 256, should be large enough for one event.*/
    RepoWatchInfo *info;


    DWORD bytesRead = 0;
    ULONG_PTR key = 0;
    OVERLAPPED *ol = NULL;

    /* Use I/O Completion Port to watch asynchronous events on:

     * 1) dir watch handles(events created by ReadDirectoryChangesW)
     * 2) the cmd pipe (which is a socket indeed)
     
     */

    if (!add_all_to_iocp(monitor)) {
        seaf_warning("Failed to add all to iocp\n");
        return NULL;
    }
    
    while (1) {

        BOOL ret = GetQueuedCompletionStatus
            (priv->iocp_handle,           /* iocp handle */
             &bytesRead,                  /* length of info */
             &key,                        /* completion key */
             &ol,                         /* OVERLAPPED */
             INFINITE);                   /* timeout */

        static int retry;

        if (!ret) {
            seaf_warning ("GetQueuedCompletionStatus failed, "
                          "error code %lu", GetLastError());

            if (retry++ < 3)
                continue;
            else
                break;
        } else {
            /* clear the retry counter on success */
            retry = 0;
        }

        if (key == (ULONG_PTR)monitor->cmd_pipe[0]) {     
            /* Triggered by a cmd pipe event */

            if (bytesRead != sizeof(WatchCommand)) {
                seaf_warning ("broken cmd from pipe: get"
                              " %d(expected: %d) bytes\n",
                              (int)bytesRead, sizeof(WatchCommand));
                continue;
            }

            seaf_debug ("recevied a pipe cmd, type %d for repo %s\n",
                        priv->cmd.type, priv->cmd.repo_id);

            handle_watch_command (monitor, &priv->cmd);

            reset_overlapped(ol);
            start_watch_cmd_pipe (monitor, ol);

        } else {
            /* Trigger by one of the dir watch handles */

            HANDLE hTriggered = (HANDLE)key;
            info = (RepoWatchInfo *)g_hash_table_lookup
                (priv->info_hash, (gconstpointer)hTriggered); 

            if (info) {
                DirWatchAux *aux = g_hash_table_lookup (priv->buf_hash,
                                                        (gconstpointer)hTriggered);

                process_events (info->status->repo_id, info, aux->buf, bytesRead);

                reset_overlapped(ol);
                if (!start_watch_dir_change(priv, hTriggered)) {

                    seaf_warning ("start_watch_dir_change failed"
                                  "for repo %s, error code %lu\n",
                                  info->status->repo_id, GetLastError());
                }
            } else {
                /* A previously unwatched dir_handle's DirWatchAux buf was
                   scheduled to be freed. */
                DirWatchAux *aux = g_hash_table_lookup (priv->buf_hash, (gconstpointer)hTriggered);
                if (aux && aux->unused)
                    g_free (aux);
                g_hash_table_remove (priv->buf_hash, (gconstpointer)hTriggered);
            }
        }
    }
    return NULL;
}
Ejemplo n.º 28
0
/* Uninstall NSIS */
MSIDLLEXPORT UninstallNsisInstallation( MSIHANDLE hInstall )
{
	DWORD rv = ERROR_SUCCESS;
	// lookup the NSISUNINSTALL property value
	LPTSTR cNsisUninstall = _T("UPGRADENSIS");
	HANDLE hIo = NULL;
	DWORD dwSize = 0;
	LPTSTR strPathUninst = NULL;
	HANDLE hJob = NULL;
	STARTUPINFO sInfo;
	PROCESS_INFORMATION pInfo;

	pInfo.hProcess = NULL;
	pInfo.hThread = NULL;

	rv = MsiGetProperty( hInstall, cNsisUninstall, _T(""), &dwSize );
	if(rv != ERROR_MORE_DATA) goto _cleanup;

	strPathUninst = new TCHAR[ ++dwSize ];

	rv = MsiGetProperty( hInstall, cNsisUninstall, strPathUninst, &dwSize );
	if(rv != ERROR_SUCCESS) goto _cleanup;

	// Create a process for the uninstaller
	sInfo.cb = sizeof(sInfo);
	sInfo.lpReserved = NULL;
	sInfo.lpDesktop = _T("");
	sInfo.lpTitle = _T("NSIS Uninstaller for Kerberos for Windows");
	sInfo.dwX = 0;
	sInfo.dwY = 0;
	sInfo.dwXSize = 0;
	sInfo.dwYSize = 0;
	sInfo.dwXCountChars = 0;
	sInfo.dwYCountChars = 0;
	sInfo.dwFillAttribute = 0;
	sInfo.dwFlags = 0;
	sInfo.wShowWindow = 0;
	sInfo.cbReserved2 = 0;
	sInfo.lpReserved2 = 0;
	sInfo.hStdInput = 0;
	sInfo.hStdOutput = 0;
	sInfo.hStdError = 0;

	if(!CreateProcess( 
		strPathUninst,
		_T("Uninstall /S"),
		NULL,
		NULL,
		FALSE,
		CREATE_SUSPENDED,
		NULL,
		NULL,
		&sInfo,
		&pInfo)) {
            DWORD lastError = GetLastError();
            MSIHANDLE hRecord;

            hRecord = MsiCreateRecord(4);
            MsiRecordClearData(hRecord);
            MsiRecordSetInteger(hRecord, 1, ERR_NSS_FAILED_CP);
            MsiRecordSetString(hRecord, 2, strPathUninst);
            MsiRecordSetInteger(hRecord, 3, lastError);

            MsiProcessMessage( hInstall, INSTALLMESSAGE_ERROR, hRecord );
	
            MsiCloseHandle( hRecord );

            pInfo.hProcess = NULL;
            pInfo.hThread = NULL;
            rv = 40;
            goto _cleanup;
        };

	// Create a job object to contain the NSIS uninstall process tree

	JOBOBJECT_ASSOCIATE_COMPLETION_PORT acp;

	acp.CompletionKey = 0;

	hJob = CreateJobObject(NULL, _T("NSISUninstallObject"));
	if(!hJob) {
		rv = 41;
		goto _cleanup;
	}

	hIo = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
	if(!hIo) {
		rv = 42;
		goto _cleanup;
	}

	acp.CompletionPort = hIo;

	SetInformationJobObject( hJob, JobObjectAssociateCompletionPortInformation, &acp, sizeof(acp));

	AssignProcessToJobObject( hJob, pInfo.hProcess );

	ResumeThread( pInfo.hThread );

	DWORD a,b,c;
	for(;;) {
		if(!GetQueuedCompletionStatus(hIo, &a, (PULONG_PTR) &b, (LPOVERLAPPED *) &c, INFINITE)) {
			Sleep(1000);
			continue;
		}
		if(a == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {
			break;
		}
	}

	rv = ERROR_SUCCESS;
    
_cleanup:
	if(hIo) CloseHandle(hIo);
	if(pInfo.hProcess)	CloseHandle( pInfo.hProcess );
	if(pInfo.hThread) 	CloseHandle( pInfo.hThread );
	if(hJob) CloseHandle(hJob);
	if(strPathUninst) delete strPathUninst;

	if(rv != ERROR_SUCCESS && rv != 40) {
            ShowMsiError( hInstall, ERR_NSS_FAILED, rv );
	}
	return rv;
}
Ejemplo n.º 29
0
int acl_read_wait(ACL_SOCKET fd, int timeout)
{
	const char *myname = "acl_read_wait";
	OVERLAPPED *overlapped, *lpOverlapped;
	DWORD recvBytes;
	BOOL isSuccess;
	ACL_SOCKET fd2;
	DWORD bytesTransferred = 0;
	DWORD delay = timeout * 1000;
	HANDLE h2;

	if (__handle == NULL)
		__handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
				NULL, 0, 0);
	if (__handle == NULL) {
		acl_msg_error("CreateIoCompletionPort: %s",
			acl_last_serror());
		return -1;
	}

	overlapped = acl_mycalloc(1, sizeof(OVERLAPPED));

	h2  = CreateIoCompletionPort((HANDLE) fd, __handle,
		(DWORD) overlapped, 0);
	if (h2 == NULL)
		acl_myfree(overlapped);
	else if (h2 != __handle) {
		acl_msg_error("invalid h2 by CreateIoCompletionPort: %s",
			acl_last_serror());
		CloseHandle(h2);
		return -1;
	}

	if (ReadFile((HANDLE) fd, NULL, 0, &recvBytes, overlapped) == FALSE
		&& acl_last_error() != ERROR_IO_PENDING)
	{
		acl_msg_warn("%s(%d): ReadFile error(%s)",
			myname, __LINE__, acl_last_serror());
		return -1;
	}

	delay = 6000;

	while (1)
	{
		isSuccess = GetQueuedCompletionStatus(__handle,
				&bytesTransferred,
				(DWORD*) &fd2,
				(OVERLAPPED**) &lpOverlapped,
				delay);
		if (lpOverlapped == NULL)
			break;

		if (HasOverlappedIoCompleted(lpOverlapped))
			acl_myfree(lpOverlapped);

		if (isSuccess)
			return 0;
	}

	acl_msg_warn("timeout error: %s", acl_last_serror());
	return -1;
}
Ejemplo n.º 30
0
VOID
ReadLoop(
    ULARGE_INTEGER FileSize
    )
{
    ULARGE_INTEGER ReadPointer;
    BOOL Success;
    DWORD NumberBytes;
    LPOVERLAPPED CompletedOverlapped;
    DWORD_PTR Key;
    PCOPY_CHUNK Chunk;
    int PendingIO = 0;
    int i;

    //
    // Start reading the file. Kick off MAX_CONCURRENT_IO reads, then just
    // loop waiting for writes to complete.
    //
    ReadPointer.QuadPart = 0;

    for (i=0; i < MAX_CONCURRENT_IO; i++) {
        if (ReadPointer.QuadPart >= FileSize.QuadPart) {
            break;
        }
        //
        // Use VirtualAlloc so we get a page-aligned buffer suitable
        // for unbuffered I/O.
        //
        CopyChunk[i].Buffer = VirtualAlloc(NULL,
                                           BUFFER_SIZE,
                                           MEM_COMMIT,
                                           PAGE_READWRITE);
        if (CopyChunk[i].Buffer == NULL) {
            fprintf(stderr, "VirtualAlloc %d failed, error %d\n",i, GetLastError());
            exit(1);
        }
        CopyChunk[i].Overlapped.Offset = ReadPointer.LowPart;
        CopyChunk[i].Overlapped.OffsetHigh = ReadPointer.HighPart;
        CopyChunk[i].Overlapped.hEvent = NULL;     // not needed

        Success = ReadFile(SourceFile,
                           CopyChunk[i].Buffer,
                           BUFFER_SIZE,
                           &NumberBytes,
                           &CopyChunk[i].Overlapped);

        if (!Success && (GetLastError() != ERROR_IO_PENDING)) {
            fprintf(stderr,
                    "ReadFile at %lx failed, error %d\n",
                    ReadPointer.LowPart,
                    GetLastError());
            exit(1);
        } else {
            ReadPointer.QuadPart += BUFFER_SIZE;
            ++PendingIO;

        }
    }

    //
    // We have started the initial async. reads, enter the main loop.
    // This simply waits until a write completes, then issues the next
    // read.
    //
    while (PendingIO) {
        Success = GetQueuedCompletionStatus(WritePort,
                                            &NumberBytes,
                                            &Key,
                                            &CompletedOverlapped,
                                            INFINITE);
        if (!Success) {
            //
            // Either the function failed to dequeue a completion packet
            // (CompletedOverlapped is not NULL) or it dequeued a completion
            // packet of a failed I/O operation (CompletedOverlapped is NULL).  
            //
            fprintf(stderr,
                    "GetQueuedCompletionStatus on the IoPort failed, error %d\n",
                    GetLastError());
            exit(1);
        }
        //
        // Issue the next read using the buffer that has just completed.
        //
        if (ReadPointer.QuadPart < FileSize.QuadPart) {
            Chunk = (PCOPY_CHUNK)CompletedOverlapped;
            Chunk->Overlapped.Offset = ReadPointer.LowPart;
            Chunk->Overlapped.OffsetHigh = ReadPointer.HighPart;
            ReadPointer.QuadPart += BUFFER_SIZE;
            Success = ReadFile(SourceFile,
                               Chunk->Buffer,
                               BUFFER_SIZE,
                               &NumberBytes,
                               &Chunk->Overlapped);

            if (!Success && (GetLastError() != ERROR_IO_PENDING)) {
                fprintf(stderr,
                        "ReadFile at %lx failed, error %d\n",
                        Chunk->Overlapped.Offset,
                        GetLastError());
                exit(1);
            }
        }
        else {
            //
            // There are no more reads left to issue, just wait
            // for the pending writes to drain.
            //
            --PendingIO;

        }
    }
    //
    // All done. There is no need to call VirtualFree() to free CopyChunk 
    // buffers here. The buffers will be freed when this process exits.
    //
}