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; } }
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; }
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"); } } }
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; }
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) }
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); }
// 完成端口的工作线程 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; }
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; }
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; }
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 }
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) }
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; }
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; }
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)); }
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; }
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); }
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; }
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); } }
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; }
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; }
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()
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"); }
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; }
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; }
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; }
/* * 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; }
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; }
/* 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; }
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; }
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. // }