//=========================================================================== void * AsyncThreadCreate ( FAsyncThreadProc threadProc, void * argument, const wchar_t name[] ) { AsyncThread * thread = new AsyncThread; thread->proc = threadProc; thread->handle = nil; thread->argument = argument; thread->workTimeMs = kAsyncTimeInfinite; StrCopy(thread->name, name, arrsize(thread->name)); // Create thread suspended unsigned threadId; HANDLE handle = (HANDLE) _beginthreadex( (LPSECURITY_ATTRIBUTES) 0, 0, // stack size CreateThreadProc, thread, // argument 0, // initFlag &threadId ); if (!handle) { LogMsg(kLogFatal, "%s (%u)", __FILE__, GetLastError()); ErrorAssert(__LINE__, __FILE__, "_beginthreadex failed"); } thread->handle = handle; return handle; }
//=========================================================================== void NtInitialize () { // ensure initialization only occurs once if (s_running) return; s_running = true; // create a cleanup event s_waitEvent = CreateEvent( (LPSECURITY_ATTRIBUTES) 0, true, // manual reset false, // initial state off (LPCTSTR) nil // name ); if (!s_waitEvent) ErrorAssert(__LINE__, __FILE__, "CreateEvent %#x", GetLastError()); // create IO completion port if (0 == (s_ioPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0))) ErrorAssert(__LINE__, __FILE__, "CreateIoCompletionPort %#x", GetLastError()); // calculate number of IO worker threads to create if (!s_pageSizeMask) { SYSTEM_INFO si; GetSystemInfo(&si); s_pageSizeMask = si.dwPageSize - 1; // Set worker thread count s_ioThreadCount = si.dwNumberOfProcessors * 2; if (s_ioThreadCount > kMaxWorkerThreads) { s_ioThreadCount = kMaxWorkerThreads; LogMsg(kLogError, "kMaxWorkerThreads too small!"); } } // create IO worker threads for (long thread = 0; thread < s_ioThreadCount; thread++) { s_ioThreadHandles[thread] = (HANDLE) AsyncThreadCreate( NtWorkerThreadProc, (void *) thread, L"NtWorkerThread" ); } INtSocketInitialize(); }
//============================================================================ static void ManifestCallback ( ENetError result, void * param, const wchar_t group[], const NetCliFileManifestEntry manifest[], unsigned entryCount ) { if(IS_NET_ERROR(result)) { switch (result) { case kNetErrTimeout: NetCliFileManifestRequest(ManifestCallback, nil, s_manifest); break; default: plString msg = plString::Format("Error getting patcher manifest: %S", NetErrorToString(result)); plStatusLog::AddLineS("patcher.log", msg.c_str()); if (IS_NET_SUCCESS(s_patchResult)) s_patchResult = result; break; } return; } #ifndef PLASMA_EXTERNAL_RELEASE if (entryCount == 0) { // dataserver does not contain a patcher s_downloadComplete = true; return; } #endif char ansi[MAX_PATH]; // MD5 check current patcher against value in manifest ASSERT(entryCount == 1); wchar_t curPatcherFile[MAX_PATH]; PathGetProgramName(curPatcherFile, arrsize(curPatcherFile)); StrToAnsi(ansi, curPatcherFile, arrsize(ansi)); if (!MD5Check(ansi, manifest[0].md5)) { // MessageBox(GetTopWindow(nil), "MD5 failed", "Msg", MB_OK); SelfPatcherStream::totalBytes += manifest[0].zipSize; AtomicAdd(&s_numFiles, 1); SetText("Downloading new patcher..."); StrToAnsi(ansi, s_newPatcherFile, arrsize(ansi)); SelfPatcherStream * stream = new SelfPatcherStream; if (!stream->Open(ansi, "wb")) ErrorAssert(__LINE__, __FILE__, "Failed to create file: %s, errno: %u", ansi, errno); NetCliFileDownloadRequest(manifest[0].downloadName, stream, DownloadCallback, nil); } else { s_downloadComplete = true; } }
bool plAgeLoader::ILoadAge(const plString& ageName) { plNetClientApp* nc = plNetClientApp::GetInstance(); ASSERT(!nc->GetFlagsBit(plNetClientApp::kPlayingGame)); fAgeName = ageName; nc->DebugMsg( "Net: Loading age {}", fAgeName); if ((fFlags & kLoadMask) != 0) ErrorAssert(__LINE__, __FILE__, "Fatal Error:\nAlready loading or unloading an age.\n%s will now exit.", plProduct::ShortName().c_str()); fFlags |= kLoadingAge; plAgeBeginLoadingMsg* ageBeginLoading = new plAgeBeginLoadingMsg(); ageBeginLoading->Send(); /////////////////////////////////////////////////////// /// Step 1: Update all of the dat files for this age /* UpdateAge(fAgeName); */ /// Step 2: Load the keys for this age, so we can find sceneNodes for them // exec age .fni file when data is done loading fPendingAgeFniFiles.emplace_back(plFormat("dat\\{}.fni", fAgeName)); fPendingAgeCsvFiles.emplace_back(plFormat("dat\\{}.csv", fAgeName)); plSynchEnabler p( false ); // turn off dirty tracking while in this function hsStream* stream=GetAgeDescFileStream(fAgeName); if (!stream) { nc->ErrorMsg("Failed loading age. Age desc file {} has nil stream", fAgeName); fFlags &= ~kLoadingAge; return false; } plAgeDescription ad; ad.Read(stream); ad.SetAgeName(fAgeName); stream->Close(); delete stream; ad.SeekFirstPage(); plAgePage *page; plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY ); // Copy, exclude pages we want excluded, and collect our scene nodes fCurAgeDescription.CopyFrom(ad); while( ( page = ad.GetNextPage() ) != nil ) { if( IsPageExcluded( page, fAgeName) ) continue; plKey roomKey = plKeyFinder::Instance().FindSceneNodeKey( fAgeName, page->GetName() ); if( roomKey != nil ) AddPendingPageInRoomKey( roomKey ); } ad.SeekFirstPage(); // Tell the client to load-and-hold all the keys for this age, to make the loading process work better plClientMsg *loadAgeKeysMsg = new plClientMsg( plClientMsg::kLoadAgeKeys ); loadAgeKeysMsg->SetAgeName( fAgeName); loadAgeKeysMsg->Send( clientKey ); // // Load the Age's SDL Hook object (and it's python modifier) // plUoid oid=nc->GetAgeSDLObjectUoid(fAgeName); plKey ageSDLObjectKey = hsgResMgr::ResMgr()->FindKey(oid); if (ageSDLObjectKey) hsgResMgr::ResMgr()->AddViaNotify(ageSDLObjectKey, new plGenRefMsg(nc->GetKey(), plRefMsg::kOnCreate, -1, plNetClientMgr::kAgeSDLHook), plRefFlags::kActiveRef); int nPages = 0; plClientMsg* pMsg1 = new plClientMsg(plClientMsg::kLoadRoom); pMsg1->SetAgeName(fAgeName); // Loop and ref! while( ( page = ad.GetNextPage() ) != nil ) { if( IsPageExcluded( page, fAgeName) ) { nc->DebugMsg("\tExcluding page {}\n", page->GetName()); continue; } nPages++; pMsg1->AddRoomLoc(ad.CalcPageLocation(page->GetName())); nc->DebugMsg("\tPaging in room {}\n", page->GetName()); } pMsg1->Send(clientKey); // Send the client a message to let go of the extra keys it was holding on to plClientMsg *dumpAgeKeys = new plClientMsg( plClientMsg::kReleaseAgeKeys ); dumpAgeKeys->SetAgeName( fAgeName); dumpAgeKeys->Send( clientKey ); if ( nPages==0 ) { // age is done loading because it has no pages? fFlags &= ~kLoadingAge; } return true; }