/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.usergrid.mq.cassandra.io;
import java.util.List;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.usergrid.mq.Message;
import org.apache.usergrid.mq.QueueQuery;
import org.apache.usergrid.mq.QueueResults;
import me.prettyprint.hector.api.Keyspace;
import static org.apache.usergrid.mq.cassandra.CassandraMQUtils.getConsumerId;
import static org.apache.usergrid.mq.cassandra.CassandraMQUtils.getQueueId;
/**
* Reads from the queue without starting transactions.
*
* @author tnine
*/
public class NoTransactionSearch extends AbstractSearch
{
private static final Logger logger = LoggerFactory.getLogger( NoTransactionSearch.class );
protected static final int DEFAULT_READ = 1;
/**
* @param ko
*/
public NoTransactionSearch( Keyspace ko )
{
super( ko );
}
/*
* (non-Javadoc)
*
* @see org.apache.usergrid.mq.cassandra.io.QueueSearch#getResults(java.lang.String,
* org.apache.usergrid.mq.QueueQuery)
*/
@Override
public QueueResults getResults( String queuePath, QueueQuery query )
{
UUID queueId = getQueueId( queuePath );
UUID consumerId = getConsumerId( queueId, query );
QueueBounds bounds = getQueueBounds( queueId );
SearchParam params = getParams( queueId, consumerId, query );
List<UUID> ids = getIds( queueId, consumerId, bounds, params );
List<Message> messages = loadMessages( ids, params.reversed );
QueueResults results = createResults( messages, queuePath, queueId, consumerId );
writeClientPointer( queueId, consumerId, results.getLast() );
return results;
}
/** Get information for reading no transactionally from the query. Subclasses can override this behavior */
protected SearchParam getParams( UUID queueId, UUID consumerId, QueueQuery query )
{
UUID lastReadMessageId = getConsumerQueuePosition( queueId, consumerId );
if ( logger.isDebugEnabled() )
{
logger.debug( "Last message id is '{}' for queueId '{}' and clientId '{}'",
lastReadMessageId, queueId, consumerId );
}
return new SearchParam( lastReadMessageId, false, lastReadMessageId != null, query.getLimit( DEFAULT_READ ) );
}
/** Get the list of ids we should load and return to the client. Message ids should be in order on return */
protected List<UUID> getIds( UUID queueId, UUID consumerId, QueueBounds bounds, SearchParam params )
{
return getQueueRange( queueId, bounds, params );
}
protected static class SearchParam
{
/** The uuid to start seeking from */
protected final UUID startId;
/** true if we should seek from high to low */
protected final boolean reversed;
/** The number of results to include */
protected final int limit;
/** true if the first result should be skipped. Useful for paging from a previous result */
protected final boolean skipFirst;
/**
* @param startId
* @param reversed
* @param count
*/
public SearchParam( UUID startId, boolean reversed, boolean skipFirst, int count )
{
this.startId = startId;
this.reversed = reversed;
this.skipFirst = skipFirst;
this.limit = count;
}
}
}