void ResourceHandleManager::cancel(ResourceHandle* job) { if (removeScheduledJob(job)) return; removeFromCurl(job); // FIXME: report an error? }
void CurlDownloadManager::updateHandleList() { MutexLocker locker(m_mutex); // Remove curl easy handles from multi list int size = m_removedHandleList.size(); for (int i = 0; i < size; i++) { removeFromCurl(m_removedHandleList[0]); m_removedHandleList.remove(0); } // Add pending curl easy handles to multi list size = m_pendingHandleList.size(); for (int i = 0; i < size; i++) { addToCurl(m_pendingHandleList[0]); m_pendingHandleList.remove(0); } }
void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>* timer) { startScheduledJobs(); fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd = 0; struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds // Temporarily disable timers since signals may interrupt select(), raising EINTR errors on some platforms setDeferringTimers(true); int rc = 0; do { FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); curl_multi_fdset(m_curlMultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd); // When the 3 file descriptors are empty, winsock will return -1 // and bail out, stopping the file download. So make sure we // have valid file descriptors before calling select. if (maxfd >= 0) rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); } while (rc == -1 && errno == EINTR); setDeferringTimers(false); if (-1 == rc) { #ifndef NDEBUG perror("bad: select() returned -1: "); #endif return; } int runningHandles = 0; while (curl_multi_perform(m_curlMultiHandle, &runningHandles) == CURLM_CALL_MULTI_PERFORM) { } // check the curl messages indicating completed transfers // and free their resources while (true) { int messagesInQueue; CURLMsg* msg = curl_multi_info_read(m_curlMultiHandle, &messagesInQueue); if (!msg) break; // find the node which has same d->m_handle as completed transfer CURL* handle = msg->easy_handle; ASSERT(handle); ResourceHandle* job = 0; CURLcode err = curl_easy_getinfo(handle, CURLINFO_PRIVATE, &job); ASSERT(CURLE_OK == err); ASSERT(job); if (!job) continue; ResourceHandleInternal* d = job->getInternal(); ASSERT(d->m_handle == handle); if (d->m_cancelled) { removeFromCurl(job); continue; } if (CURLMSG_DONE != msg->msg) continue; if (CURLE_OK == msg->data.result) { if (d->client()) d->client()->didFinishLoading(job); } else { #ifndef NDEBUG char* url = 0; curl_easy_getinfo(d->m_handle, CURLINFO_EFFECTIVE_URL, &url); printf("Curl ERROR for url='%s', error: '%s'\n", url, curl_easy_strerror(msg->data.result)); #endif if (d->client()) d->client()->didFail(job, ResourceError()); } removeFromCurl(job); } bool started = startScheduledJobs(); // new jobs might have been added in the meantime if (!m_downloadTimer.isActive() && (started || (runningHandles > 0))) m_downloadTimer.startOneShot(pollTimeSeconds); }
void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>* timer) { startScheduledJobs(); fd_set fdread; FD_ZERO(&fdread); fd_set fdwrite; FD_ZERO(&fdwrite); fd_set fdexcep; FD_ZERO(&fdexcep); int maxfd = 0; curl_multi_fdset(m_curlMultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd); struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds int rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); if (-1 == rc) { #ifndef NDEBUG printf("bad: select() returned -1\n"); #endif return; } int runningHandles = 0; CURLMcode curlCode = CURLM_CALL_MULTI_PERFORM; while (CURLM_CALL_MULTI_PERFORM == curlCode) { curlCode = curl_multi_perform(m_curlMultiHandle, &runningHandles); } // check the curl messages indicating completed transfers // and free their resources while (true) { int messagesInQueue; CURLMsg* msg = curl_multi_info_read(m_curlMultiHandle, &messagesInQueue); if (!msg) break; if (CURLMSG_DONE != msg->msg) continue; // find the node which has same d->m_handle as completed transfer CURL* handle = msg->easy_handle; ASSERT(handle); ResourceHandle* job = 0; CURLcode err = curl_easy_getinfo(handle, CURLINFO_PRIVATE, &job); ASSERT(CURLE_OK == err); ASSERT(job); if (!job) continue; ResourceHandleInternal* d = job->getInternal(); ASSERT(d->m_handle == handle); if (CURLE_OK == msg->data.result) { if (d->client()) d->client()->didFinishLoading(job); } else { #ifndef NDEBUG char* url = 0; curl_easy_getinfo(d->m_handle, CURLINFO_EFFECTIVE_URL, &url); printf("Curl ERROR for url='%s', error: '%s'\n", url, curl_easy_strerror(msg->data.result)); #endif if (d->client()) d->client()->didFail(job, ResourceError()); } removeFromCurl(job); } bool started = startScheduledJobs(); // new jobs might have been added in the meantime if (!m_downloadTimer.isActive() && (started || (runningHandles > 0))) m_downloadTimer.startOneShot(pollTimeSeconds); }
void ResourceHandleManager::cancel(ResourceHandle* job) { removeFromCurl(job); // FIXME: report an error? }