View of /trunk/AssetServer/Extensions/Memcached/MemcachedStorage.cs
Parent Directory
|
Revision Log
Revision 70 -
(download)
(annotate)
Tue Jan 13 22:42:48 2009 UTC (4 years, 4 months ago) by jhurliman
File size: 8400 byte(s)
Tue Jan 13 22:42:48 2009 UTC (4 years, 4 months ago) by jhurliman
File size: 8400 byte(s)
* Renamed StorageResponse to BackendResponse * Deleted old HttpServer cruft * Continued work on GridServer
/*
* Copyright (c) 2008 Intel Corporation
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* -- Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* -- Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* -- Neither the name of the Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using BeIT.MemCached;
using ExtensionLoader;
using ExtensionLoader.Config;
using OpenMetaverse;
namespace AssetServer.Extensions
{
public class MemcachedStorage : IExtension<AssetServer>, IStorageProvider
{
const string EXTENSION_NAME = "MemcachedStorage"; // Used in metrics reporting
AssetServer server;
MemcachedClient cacheClient;
IStorageProvider storageBackend;
public MemcachedStorage()
{
}
#region Required Interfaces
public void Start(AssetServer server)
{
this.server = server;
cacheClient = null;
try
{
IConfig memcacheConfig = server.ConfigFile.Configs["Memcached"];
if (memcacheConfig.Contains("Servers"))
{
string[] servers = memcacheConfig.GetString("Servers").Split(',');
try
{
MemcachedClient.Setup("AssetServer", servers);
cacheClient = MemcachedClient.GetInstance("AssetServer");
}
catch (Exception ex)
{
Logger.Log.Error("Failed to connect to memcached: " + ex.Message);
}
}
}
catch (Exception)
{
Logger.Log.Error("Failed to load [Memcached] section from config file " + AssetServer.CONFIG_FILE);
}
// Search through the loaded extensions for another IStorageProvider
// that will serve as the fallback for the cache
foreach (IExtension<AssetServer> extension in ExtensionLoader<AssetServer>.Extensions)
{
if (extension is IStorageProvider && extension != this)
storageBackend = extension as IStorageProvider;
}
if (storageBackend == null)
Logger.Log.Warn("Memcached caching storage provider loaded with no fallback storage provider");
}
public void Stop()
{
}
public BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata)
{
metadata = null;
BackendResponse ret;
string cacheID = assetID.ToString() + "-metadata";
if (cacheClient != null)
{
byte[] data = cacheClient.Get(cacheID) as byte[];
if (data != null)
{
metadata = new Metadata();
metadata.Deserialize(data);
}
}
if (metadata != null)
{
ret = BackendResponse.Success;
}
else if (storageBackend != null)
{
BackendResponse response = storageBackend.TryFetchMetadata(assetID, out metadata);
if (response == BackendResponse.Success && cacheClient != null)
{
if (cacheClient.Set(cacheID, metadata.SerializeToBytes()))
Logger.Log.Debug("Cached " + cacheID);
}
ret = response;
}
else
{
ret = BackendResponse.Failure;
}
server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now);
return ret;
}
public BackendResponse TryFetchData(UUID assetID, out byte[] assetData)
{
assetData = null;
BackendResponse ret;
string cacheID = assetID.ToString();
if (cacheClient != null)
assetData = cacheClient.Get(cacheID) as byte[];
if (assetData != null)
{
ret = BackendResponse.Success;
}
else if (storageBackend != null)
{
BackendResponse response = storageBackend.TryFetchData(assetID, out assetData);
if (response == BackendResponse.Success && cacheClient != null)
{
if (cacheClient.Set(cacheID, assetData))
Logger.Log.Debug("Cached " + cacheID);
}
ret = response;
}
else
{
ret = BackendResponse.Failure;
}
server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now);
return ret;
}
public BackendResponse TryFetchDataMetadata(UUID assetID, out Metadata metadata, out byte[] assetData)
{
metadata = null;
BackendResponse response = TryFetchData(assetID, out assetData);
if (response == BackendResponse.Success)
response = TryFetchMetadata(assetID, out metadata);
return response;
}
public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData, out UUID assetID)
{
assetID = metadata.ID = UUID.Random();
return TryCreateAsset(metadata, assetData);
}
public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData)
{
BackendResponse ret;
if (storageBackend != null)
{
BackendResponse response = storageBackend.TryCreateAsset(metadata, assetData);
if (response == BackendResponse.Success && cacheClient != null)
{
// There is a high likelihood that an asset that was just uploaded (or its metdata)
// will be fetched very soon. Call TryFetchDataMetadata to pre-emptively cache the
// final stored data
TryFetchDataMetadata(metadata.ID, out metadata, out assetData);
}
ret = response;
}
else
{
ret = BackendResponse.Failure;
}
// Don't log the storage to the metrics provider, the actual storage provider will do that
return ret;
}
public int ForEach(Action<Metadata> action, int start, int count)
{
// Can't iterate over memcached contents, pass this directly to the backend
if (storageBackend != null)
return storageBackend.ForEach(action, start, count);
else
return 0;
}
#endregion Required Interfaces
}
}
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

