void CacheEntry::InvokeCallbacks() { LOG(("CacheEntry::InvokeCallbacks BEGIN [this=%p]", this)); mLock.AssertCurrentThreadOwns(); do { if (mPreventCallbacks) { LOG(("CacheEntry::InvokeCallbacks END [this=%p] callbacks prevented!", this)); return; } if (!mCallbacks.Count()) { LOG((" no r/w callbacks")); break; } if (mHasMainThreadOnlyCallback && !NS_IsMainThread()) { nsRefPtr<nsRunnableMethod<CacheEntry> > event = NS_NewRunnableMethod(this, &CacheEntry::InvokeCallbacksMainThread); NS_DispatchToMainThread(event); LOG(("CacheEntry::InvokeCallbacks END [this=%p] dispatching to maintread", this)); return; } nsCOMPtr<nsICacheEntryOpenCallback> callback = mCallbacks[0]; mCallbacks.RemoveElementAt(0); if (!InvokeCallback(callback, false)) { mCallbacks.InsertElementAt(0, callback); LOG(("CacheEntry::InvokeCallbacks END [this=%p] callback bypassed", this)); return; } } while (true); while (mReadOnlyCallbacks.Count()) { if (mHasMainThreadOnlyCallback && !NS_IsMainThread()) { nsRefPtr<nsRunnableMethod<CacheEntry> > event = NS_NewRunnableMethod(this, &CacheEntry::InvokeCallbacksMainThread); NS_DispatchToMainThread(event); LOG(("CacheEntry::InvokeCallbacks END [this=%p] dispatching to maintread", this)); return; } nsCOMPtr<nsICacheEntryOpenCallback> callback = mReadOnlyCallbacks[0]; mReadOnlyCallbacks.RemoveElementAt(0); if (!InvokeCallback(callback, true)) { // Didn't trigger, so we must stop mReadOnlyCallbacks.InsertElementAt(0, callback); break; } } if (!mCallbacks.Count() && !mReadOnlyCallbacks.Count()) mHasMainThreadOnlyCallback = false; LOG(("CacheEntry::InvokeCallbacks END [this=%p]", this)); }
// if void FileWatchImpl::OnDirectoryChangeNotification() { FILETIME fileLastWriteTime = GetFileLastWriteTime(m_filename.GetString()); if (fileLastWriteTime.dwHighDateTime != m_fileLastWriteTime.dwHighDateTime || fileLastWriteTime.dwLowDateTime != m_fileLastWriteTime.dwLowDateTime) { InvokeCallback(); m_fileLastWriteTime = fileLastWriteTime; } }
bool CacheEntry::InvokeCallbacks(bool aReadOnly) { mLock.AssertCurrentThreadOwns(); uint32_t i = 0; while (i < mCallbacks.Length()) { if (mPreventCallbacks) { LOG((" callbacks prevented!")); return false; } if (!mIsDoomed && (mState == WRITING || mState == REVALIDATING)) { LOG((" entry is being written/revalidated")); return false; } if (mCallbacks[i].mReadOnly != aReadOnly) { // Callback is not r/w or r/o, go to another one in line ++i; continue; } bool onCheckThread; nsresult rv = mCallbacks[i].OnCheckThread(&onCheckThread); if (NS_SUCCEEDED(rv) && !onCheckThread) { // Redispatch to the target thread nsRefPtr<nsRunnableMethod<CacheEntry> > event = NS_NewRunnableMethod(this, &CacheEntry::InvokeCallbacksLock); rv = mCallbacks[i].mTargetThread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL); if (NS_SUCCEEDED(rv)) { LOG((" re-dispatching to target thread")); return false; } } Callback callback = mCallbacks[i]; mCallbacks.RemoveElementAt(i); if (NS_SUCCEEDED(rv) && !InvokeCallback(callback)) { // Callback didn't fire, put it back and go to another one in line. // Only reason InvokeCallback returns false is that onCacheEntryCheck // returns RECHECK_AFTER_WRITE_FINISHED. If we would stop the loop, other // readers or potential writers would be unnecessarily kept from being // invoked. size_t pos = std::min(mCallbacks.Length(), static_cast<size_t>(i)); mCallbacks.InsertElementAt(pos, callback); ++i; } } return true; }
void CoreClrFuncInvokeContext::TaskCompleteSynchronous(void* result, int resultType, int taskState, Handle<v8::Value> callback) { DBG("CoreClrFuncInvokeContext::TaskCompleteSynchronous"); CoreClrFuncInvokeContext* context = new CoreClrFuncInvokeContext(callback, NULL); context->resultData = result; context->resultType = resultType; context->taskState = taskState; InvokeCallback(context); }
PLUGIN_EXPORT bool PLUGIN_CALL OnPublicCall(AMX *amx, const char *name, cell *params, cell *retval) { bool foundFunction = false; auto result = InvokeCallback(amx, name, params, foundFunction); if (foundFunction) { if (retval) *retval = result; if (ShouldCancelCallback(name, result)) { return false; } } bool success = false; auto hook = CallHookedCallback(amx, name, params, success); if (success) { if (retval) *retval = hook[0]; if (hook[1]) return false; } return true; }
bool CacheEntry::InvokeCallback(Callback & aCallback) { LOG(("CacheEntry::InvokeCallback [this=%p, state=%s, cb=%p]", this, StateString(mState), aCallback.mCallback.get())); mLock.AssertCurrentThreadOwns(); // When this entry is doomed we want to notify the callback any time if (!mIsDoomed) { // When we are here, the entry must be loaded from disk MOZ_ASSERT(mState > LOADING); if (mState == WRITING || mState == REVALIDATING) { // Prevent invoking other callbacks since one of them is now writing // or revalidating this entry. No consumers should get this entry // until metadata are filled with values downloaded from the server // or the entry revalidated and output stream has been opened. LOG((" entry is being written/revalidated, callback bypassed")); return false; } // mRecheckAfterWrite flag already set means the callback has already passed // the onCacheEntryCheck call. Until the current write is not finished this // callback will be bypassed. if (!aCallback.mRecheckAfterWrite) { if (!aCallback.mReadOnly) { if (mState == EMPTY) { // Advance to writing state, we expect to invoke the callback and let // it fill content of this entry. Must set and check the state here // to prevent more then one mState = WRITING; LOG((" advancing to WRITING state")); } if (!aCallback.mCallback) { // We can be given no callback only in case of recreate, it is ok // to advance to WRITING state since the caller of recreate is expected // to write this entry now. return true; } } if (mState == READY) { // Metadata present, validate the entry uint32_t checkResult; { // mayhemer: TODO check and solve any potential races of concurent OnCacheEntryCheck mozilla::MutexAutoUnlock unlock(mLock); nsresult rv = aCallback.mCallback->OnCacheEntryCheck( this, nullptr, &checkResult); LOG((" OnCacheEntryCheck: rv=0x%08x, result=%d", rv, checkResult)); if (NS_FAILED(rv)) checkResult = ENTRY_NOT_WANTED; } aCallback.mRevalidating = checkResult == ENTRY_NEEDS_REVALIDATION; switch (checkResult) { case ENTRY_WANTED: // Nothing more to do here, the consumer is responsible to handle // the result of OnCacheEntryCheck it self. // Proceed to callback... break; case RECHECK_AFTER_WRITE_FINISHED: LOG((" consumer will check on the entry again after write is done")); // The consumer wants the entry to complete first. aCallback.mRecheckAfterWrite = true; break; case ENTRY_NEEDS_REVALIDATION: LOG((" will be holding callbacks until entry is revalidated")); // State is READY now and from that state entry cannot transit to any other // state then REVALIDATING for which cocurrency is not an issue. Potentially // no need to lock here. mState = REVALIDATING; break; case ENTRY_NOT_WANTED: LOG((" consumer not interested in the entry")); // Do not give this entry to the consumer, it is not interested in us. aCallback.mNotWanted = true; break; } } } } if (aCallback.mCallback) { if (!mIsDoomed && aCallback.mRecheckAfterWrite) { // If we don't have data and the callback wants a complete entry, // don't invoke now. bool bypass = !mHasData; if (!bypass && NS_SUCCEEDED(mFileStatus)) { int64_t _unused; bypass = !mFile->DataSize(&_unused); } if (bypass) { LOG((" bypassing, entry data still being written")); return false; } // Entry is complete now, do the check+avail call again aCallback.mRecheckAfterWrite = false; return InvokeCallback(aCallback); } mozilla::MutexAutoUnlock unlock(mLock); InvokeAvailableCallback(aCallback); } return true; }
void PerformSearch(JNIEnv *env, jobject obj, jobject callback, std::wstring searchText, std::list<std::wstring>& patterns,int maximumResults, jobject monitor) { ADODB::_ConnectionPtr connection = NULL; ADODB::_RecordsetPtr recordset = NULL; try { HRESULT hr = ::CoInitialize(NULL); if (!SUCCEEDED(hr)) return; hr = connection.CreateInstance(__uuidof(ADODB::Connection)); if (!SUCCEEDED(hr)) return; hr = recordset.CreateInstance(__uuidof(ADODB::Recordset)); if (!SUCCEEDED(hr)) return; connection->CursorLocation = ADODB::adUseClient; hr = connection->Open(L"Provider=Search.CollatorDSO;Extended Properties='Application=Windows';", L"", L"", ADODB::adConnectUnspecified); if (!SUCCEEDED(hr)) return; searchText = ReplaceCharWithString(searchText, '\'', L"''"); std::wstring filenameMatcher = searchText; filenameMatcher = ReplaceCharWithString(filenameMatcher, '%', L"\\%"); filenameMatcher = ReplaceCharWithString(filenameMatcher, '*', L"%"); // see FREETEXT http://msdn.microsoft.com/en-us/library/bb231268(v=vs.85).aspx // see CONTAINS http://msdn.microsoft.com/en-us/library/bb231270(v=vs.85).aspx std::wstring query = L"SELECT TOP "; query += IntToString(maximumResults); query += L" System.ItemPathDisplay from SystemIndex WHERE "; // limit to documents, pictures and video query += L"(System.Kind = 'document' or System.Kind = 'picture' or System.Kind = 'video' or System.Kind is null) AND "; // content search query += L"(FREETEXT('\""; query += searchText; query += L"\"') OR "; // filename search query += L"(System.ItemName LIKE '%"; query += filenameMatcher; query += L"%'))"; if (patterns.size() > 0) { bool hasFilenameSearch = true; std::wstring anyFile(L"*"); for(std::list<std::wstring>::iterator iterator = patterns.begin(); iterator != patterns.end(); iterator++) { std::wstring pattern = *iterator; if (pattern == anyFile) { hasFilenameSearch = false; break; } } if (hasFilenameSearch) { query += L" AND ("; for(std::list<std::wstring>::iterator iterator = patterns.begin(); iterator != patterns.end(); iterator++) { std::wstring pattern = *iterator; if (pattern.size() == 0) { continue; } pattern = ReplaceCharWithString(pattern, '*', L"%"); if (iterator != patterns.begin()) { query += L" OR "; } query += L"(System.ItemName LIKE '"; if (pattern[0] != '%') { query += L"%"; } query += pattern; query += L"')"; } query += L")"; } } //std::cout << "Query:\n"; //std::cout << query; //std::cout << "\n"; //std::cout << std::flush; hr = recordset->Open(query.c_str(), connection.GetInterfacePtr(), ADODB::adOpenForwardOnly, ADODB::adLockReadOnly, ADODB::adCmdText); if (!SUCCEEDED(hr)) { std::cout << "Open Failed\n" << std::flush; return; } int count = maximumResults; while(!recordset->ADOEOF) { _variant_t var = recordset->Fields->GetItem(L"System.ItemPathDisplay")->GetValue(); std::wstring filename = (const wchar_t*)_bstr_t(var.bstrVal); InvokeCallback(env, obj, callback, filename); if (IsProgressMonitorCancelled(env,monitor)) { break; } if (--count < 0) { break; } hr = recordset->MoveNext(); if (!SUCCEEDED(hr)) { std::cout << "Move Next Failed\n" << std::flush; break; } } } catch (_com_error &e) { _tprintf(_T("\tCOM Error code = %08lx\n"), e.Error()); } if (recordset != NULL && recordset->State == ADODB::adStateOpen) recordset->Close(); if (connection != NULL && connection->State == ADODB::adStateOpen) connection->Close(); ::CoUninitialize(); }