📄 sbinethttpcachestream.cpp
字号:
(VXIValue*)VXIIntegerCreate(SBinetHttpUtils::HTTP_NOT_MODIFIED));
// 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;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -