📄 sbinethttpcachestream.cpp
字号:
// Set the absolute URL property VXIMapSetProperty(streamInfo, INET_INFO_ABSOLUTE_NAME, (VXIValue*)VXIStringCreate(absoluteURL)); // Set the document size property VXIMapSetProperty(streamInfo, INET_INFO_SIZE_BYTES, (VXIValue*)VXIIntegerCreate(validator.getSize())); // Set the MIME type property VXIMapSetProperty(streamInfo, INET_INFO_MIME_TYPE, (VXIValue*)VXIStringCreate(mimeType)); SBinetUtils::setValidatorInfo(streamInfo, &validator); // We leave the cache stream open until Read() or Close() is called rc = VXIcache_RESULT_SUCCESS; goto cleanup; failure: if (_cacheStream) { VXIcacheResult rcc = _cache->CloseEx(_cache, keepEntry, &_cacheStream); if (rcc != VXIcache_RESULT_SUCCESS) Error(239, L"%s%s%s%i", L"URL", absoluteURL, L"rc", rcc); } _cacheStream = NULL; cleanup: delete ultimateURL; delete [] mimeType; return rc; } // Write the document to cache. This method only stores the validator // and MIME type in the cache. The real document (message body) is // written later in Read(). VXIinetResult SBinetHttpCacheStream::openCacheWrite(const VXIMap* streamInfo, const SBinetValidator& validator, const SBinetURL* ultimateURL) { // No caching. if (_cache == NULL) return VXIinet_RESULT_SUCCESS; const VXIchar* absoluteURL = _url->getAbsolute(); VXIulong bytesWritten = 0; VXIulong dataSize = 0; VXIulong dataSizeBytes = 0; const VXIchar* mimeType = NULL; // Write the validator to cache VXIcacheResult rc = openCacheWrite(absoluteURL, validator); if (rc != VXIcache_RESULT_SUCCESS) { goto failure; } // Take care of redirection. if (*_url != *ultimateURL) { Diag(MODULE_SBINET_CACHE_TAGID, L"SBinetHttpCacheStream::OpenCacheWrite", L"Redirection detected, from %s to %s", absoluteURL, ultimateURL->getAbsolute()); if (_cacheStream) { VXIcacheResult rcc = _cache->CloseEx(_cache, TRUE, &_cacheStream); if (rcc != VXIcache_RESULT_SUCCESS) Error(239, L"%s%s%s%i", L"URL", absoluteURL, L"rc", rcc); } _cacheStream = NULL; absoluteURL = ultimateURL->getAbsolute(); // Write the validator to cache if ((rc = openCacheWrite(absoluteURL, validator)) != VXIcache_RESULT_SUCCESS) goto failure; } // Write the size of the of the mime-type (number of VXIchar). mimeType = SBinetUtils::getString(streamInfo, INET_INFO_MIME_TYPE); dataSize = mimeType == NULL ? 0 : ::wcslen(mimeType); bytesWritten = 0; rc = _cache->Write(_cache, (VXIbyte *) &dataSize, sizeof(dataSize), &bytesWritten, _cacheStream); if ((rc != VXIcache_RESULT_SUCCESS) || (bytesWritten != sizeof(dataSize))) { Error(232, L"%s%s%s%i%s%i%s%i", L"URL", absoluteURL, L"rc", rc, L"written", bytesWritten, L"expected", sizeof(dataSize)); goto failure; } // Now write the mime-type. bytesWritten = 0; dataSizeBytes = dataSize * sizeof(VXIchar); rc = _cache->Write(_cache, (const VXIbyte *) mimeType, dataSizeBytes, &bytesWritten, _cacheStream); if ((rc != VXIcache_RESULT_SUCCESS) || (bytesWritten != dataSizeBytes)) { Error(232, L"%s%s%s%i%s%i%s%i", L"URL", absoluteURL, L"rc", rc, L"written", bytesWritten, L"expected", dataSizeBytes); goto failure; } goto end; failure: if (_cacheStream) { VXIcacheResult rcc = _cache->CloseEx(_cache, FALSE, &_cacheStream); if (rcc != VXIcache_RESULT_SUCCESS) Error(239, L"%s%s%s%i", L"URL", absoluteURL, L"rc", rcc); } _cacheStream = NULL; end: if (rc == VXIcache_RESULT_ENTRY_LOCKED) { // This is because of a timeout on trying to lock the cache entry. We just // return a a fetch timeout to cause our calling function to fail. Error(235, L"%s%s", L"URL", absoluteURL); return VXIinet_RESULT_FETCH_TIMEOUT; } else { // Something wrong occured while trying to write data to the cache entry. // We will assume success, but there will be no caching. return VXIinet_RESULT_SUCCESS; } } void SBinetHttpCacheStream::setTimeOut(const SWITimeStamp *timeOfDay) { if (_httpStream != NULL) { _httpStream->setTimeOut(timeOfDay); } SBinetStoppableStream::setTimeOut(timeOfDay); } VXIcacheResult SBinetHttpCacheStream::openCacheEntry(const VXIchar *absoluteURL, VXIcacheOpenMode mode, VXIMap *cacheStreamInfo) { VXIcacheResult rc; long delay; const long maxSleepTime = 20; static const VXIchar *moduleName = L"swi:" MODULE_SBINET; SBinetString cacheKey = moduleName; cacheKey += L':'; cacheKey += absoluteURL; VXIMapHolder cacheProp; // will destroy the map for us VXIMapSetProperty(cacheProp.GetValue(), CACHE_CREATION_COST, (VXIValue *) VXIIntegerCreate(CACHE_CREATION_COST_FETCH)); while ((rc = _cache->Open(_cache, MODULE_SBINET, cacheKey.c_str(), mode, CACHE_FLAG_NULL, cacheProp.GetValue(), cacheStreamInfo, &_cacheStream)) == VXIcache_RESULT_ENTRY_LOCKED) { //VXItrdThreadYield(); delay = getDelay(); if (delay == 0) break; else if (delay < 0 || delay > maxSleepTime) delay = maxSleepTime; SBinetHttpUtils::usleep(delay * 1000); } if (rc != VXIcache_RESULT_SUCCESS) { if (rc == VXIcache_RESULT_NOT_FOUND) Diag(MODULE_SBINET_CACHE_TAGID, L"SBinetHttpCacheStream", L"Not found in cache: %s", absoluteURL); else Error(230, L"%s%s%s%i", L"URL", absoluteURL, L"rc", rc); } return rc; } VXIcacheResult SBinetHttpCacheStream::openCacheRead(SBinetValidator& validator, VXIbool& keepEntry, SBinetURL *&ultimateURL) { VXIMap *cacheStreamInfo = VXIMapCreate(); VXIbyte *validatorData = NULL; VXIcacheResult rc; VXIulong maxDataSize = 0; VXIulong bytesRead = 0; VXIint32 entrySizeBytes = 0; VXIulong dataSize = 0; SBinetURL *tmpURL = NULL; const VXIchar *absoluteURL = NULL; ultimateURL = new SBinetURL(*_url); for (;;) { absoluteURL = ultimateURL->getAbsolute(); rc = openCacheEntry(absoluteURL, CACHE_MODE_READ, cacheStreamInfo); if (rc != VXIcache_RESULT_SUCCESS) break; // The document is in cache. Diag(MODULE_SBINET_CACHE_TAGID, L"SBinetHttpCacheStream", L"Found in cache: %s", absoluteURL); // Retrieve the total size of the cache entry if (!SBinetUtils::getInteger(cacheStreamInfo, CACHE_INFO_SIZE_BYTES, entrySizeBytes)) { Error(233, L"%s%s%", L"URL", absoluteURL); rc = VXIcache_RESULT_FAILURE; break; } // Read the size of the validator info. rc = _cache->Read(_cache, (VXIbyte *) &dataSize, sizeof(dataSize), &bytesRead, _cacheStream); if (rc != VXIcache_RESULT_SUCCESS || bytesRead != sizeof(dataSize)) { Error(231, L"%s%s%s%i%s%i%s%i", L"URL", absoluteURL, L"rc", rc, L"read", bytesRead, L"expected", sizeof(dataSize)); rc = VXIcache_RESULT_FAILURE; break; } if (dataSize > maxDataSize) { delete [] validatorData; validatorData = new VXIbyte[dataSize]; maxDataSize = dataSize; } if (validatorData == NULL) { Error(103, NULL); rc = VXIcache_RESULT_FAILURE; break; } rc = _cache->Read(_cache, validatorData, dataSize, &bytesRead, _cacheStream); if (rc != VXIcache_RESULT_SUCCESS || bytesRead != dataSize) { Error(231, L"%s%s%s%i%s%i%s%i", L"URL", absoluteURL, L"rc", rc, L"read", bytesRead, L"expected", dataSize); rc = VXIcache_RESULT_FAILURE; break; } if (validator.Create(validatorData, dataSize) != VXIinet_RESULT_SUCCESS) { Error(215, L"%s%s", NULL); rc = VXIcache_RESULT_FAILURE; break; } if (validator.isExpired(_maxAge, _maxStale)) { rc = VXIcache_RESULT_FAILURE; Diag(MODULE_SBINET_CACHE_TAGID, L"SBinetHttpCacheStream", L"Validator expired: %s", absoluteURL); // If the validator has expired, invalidate the cache entry. if (validator.isExpired()) keepEntry = FALSE; break; } // If the validator's URL is not equals to the current ultimate URL, then // this is a redirect. absoluteURL = validator.getURL(); if (tmpURL == NULL) { if (SBinetURL::create(absoluteURL, NULL, tmpURL) != VXIinet_RESULT_SUCCESS) rc = VXIcache_RESULT_FAILURE; } else { if (tmpURL->parse(absoluteURL, NULL) != VXIinet_RESULT_SUCCESS) rc = VXIcache_RESULT_FAILURE; } if (rc != VXIcache_RESULT_SUCCESS) { Diag(MODULE_SBINET_CACHE_TAGID, L"SBinetHttpCacheStream::OpenCacheRead", L"Invalid URL: <%s>", absoluteURL); break; } // Compare URLs. if (*ultimateURL == *tmpURL) { // No redirection. break; } // Redirection, close current stream and continue. Diag(MODULE_SBINET_CACHE_TAGID, L"SBinetHttpCacheStream::OpenCacheRead", L"Redirection detected, from %s to %s", ultimateURL->getAbsolute(), absoluteURL); *ultimateURL = *tmpURL; VXIcacheResult rcc = _cache->CloseEx(_cache, TRUE, &_cacheStream); if (rcc != VXIcache_RESULT_SUCCESS) Error(239, L"%s%s%s%i", L"URL", absoluteURL, L"rc", rcc); _cacheStream = NULL; } delete [] validatorData; delete tmpURL; if (cacheStreamInfo) VXIMapDestroy(&cacheStreamInfo); if (rc != VXIcache_RESULT_SUCCESS) { delete ultimateURL; ultimateURL = NULL; } return rc; } // This method writes the validator to the cache. VXIcacheResult SBinetHttpCacheStream::openCacheWrite(const VXIchar *absoluteURL, const SBinetValidator& validator) { // Check whether we already cached this URL. VXIcacheResult rc = openCacheEntry(absoluteURL, CACHE_MODE_WRITE, NULL); if (rc != VXIcache_RESULT_SUCCESS) return rc; VXIbyte *validatorData = NULL; VXIulong bytesWritten = 0; VXIulong dataSize = 0; if (!validator.serialize(validatorData, dataSize)) { Error(215, L"%s%s", L"URL", absoluteURL); rc = VXIcache_RESULT_FAILURE; goto failure; } // Write the size of the validator. rc = _cache->Write(_cache, (VXIbyte *) &dataSize, sizeof(dataSize), &bytesWritten, _cacheStream); if (rc != VXIcache_RESULT_SUCCESS || (bytesWritten != sizeof(dataSize))) { if (rc == VXIcache_RESULT_EXCEED_MAXSIZE) Error(305, L"%s%s", L"URL", absoluteURL); else Error(232, L"%s%s%s%i%s%i%s%i", L"URL", absoluteURL, L"rc", rc, L"written", bytesWritten, L"expected", sizeof(dataSize)); rc = VXIcache_RESULT_FAILURE; goto failure; } // Write the validator. bytesWritten = 0; rc = _cache->Write(_cache, validatorData, dataSize, &bytesWritten, _cacheStream); if (rc != VXIcache_RESULT_SUCCESS || bytesWritten != dataSize) { Error(232, L"%s%s%s%i%s%i%s%i", L"URL", absoluteURL, L"rc", rc, L"written", bytesWritten, L"expected", dataSize); rc = VXIcache_RESULT_FAILURE; } failure: delete [] validatorData; return rc; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -