/**
* GRANITE DATA SERVICES
* Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S.
*
* This file is part of the Granite Data Services Platform.
*
* Granite Data Services is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Granite Data Services is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA, or see <http://www.gnu.org/licenses/>.
*/
package org.granite.gravity.gae;
import org.granite.config.GraniteConfig;
import org.granite.config.flex.ServicesConfig;
import org.granite.gravity.Channel;
import org.granite.gravity.ChannelFactory;
import org.granite.gravity.DefaultGravity;
import org.granite.gravity.GravityConfig;
import org.granite.gravity.Subscription;
import org.granite.util.UUIDUtil;
import com.google.appengine.api.memcache.Expiration;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import flex.messaging.messages.Message;
/**
* @author William DRAI
* @author Franck WOLFF
*/
public class GAEGravity extends DefaultGravity {
///////////////////////////////////////////////////////////////////////////
// Fields.
static final String CHANNEL_PREFIX = "org.granite.gravity.gae.channel.";
private static MemcacheService gaeCache = MemcacheServiceFactory.getMemcacheService();
///////////////////////////////////////////////////////////////////////////
// Constructor.
public GAEGravity(GravityConfig gravityConfig, ServicesConfig servicesConfig, GraniteConfig graniteConfig) {
super(gravityConfig, servicesConfig, graniteConfig);
}
///////////////////////////////////////////////////////////////////////////
// Channel's operations.
@Override
protected <C extends Channel> C createChannel(ChannelFactory<C> channelFactory, String channelId) {
C channel = null;
if (channelId != null) {
channel = getChannel(channelFactory, channelId);
if (channel != null)
return channel;
}
channel = channelFactory.newChannel(UUIDUtil.randomUUID(), null);
Expiration expiration = Expiration.byDeltaMillis((int)getGravityConfig().getChannelIdleTimeoutMillis());
gaeCache.put(CHANNEL_PREFIX + channel.getId(), channel, expiration);
gaeCache.put(GAEChannel.MSG_COUNT_PREFIX + channel.getId(), 0L, expiration);
return channel;
}
@SuppressWarnings("unchecked")
@Override
public <C extends Channel> C getChannel(ChannelFactory<C> channelFactory, String channelId) {
if (channelId == null)
return null;
return (C)gaeCache.get(CHANNEL_PREFIX + channelId);
}
@Override
public Channel removeChannel(String channelId, boolean timeout) {
if (channelId == null)
return null;
Channel channel = (Channel)gaeCache.get(CHANNEL_PREFIX + channelId);
if (channel != null) {
for (Subscription subscription : channel.getSubscriptions()) {
Message message = subscription.getUnsubscribeMessage();
handleMessage(channel.getFactory(), message, true);
}
channel.destroy(timeout);
gaeCache.delete(CHANNEL_PREFIX + channelId);
gaeCache.delete(GAEChannel.MSG_COUNT_PREFIX + channelId);
}
return channel;
}
@Override
public boolean access(String channelId) {
return true;
}
@Override
public void internalStart() {
// Avoid starting thread pool
}
@Override
protected void postManage(Channel channel) {
Expiration expiration = Expiration.byDeltaMillis((int)getGravityConfig().getChannelIdleTimeoutMillis());
gaeCache.put(CHANNEL_PREFIX + channel.getId(), channel, expiration);
}
}