You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2014/01/28 23:21:59 UTC
[49/96] [abbrv] [partial] Change package namespace to
org.apache.usergrid
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/BatchSubmitter.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/BatchSubmitter.java b/stack/core/src/main/java/org/apache/usergrid/count/BatchSubmitter.java
new file mode 100644
index 0000000..0fd7965
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/BatchSubmitter.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import java.util.Collection;
+import java.util.concurrent.Future;
+
+import org.apache.usergrid.count.common.Count;
+
+
+/** @author zznate */
+public interface BatchSubmitter {
+ Future<?> submit( Collection<Count> counts );
+
+ void shutdown();
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/Batcher.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/Batcher.java b/stack/core/src/main/java/org/apache/usergrid/count/Batcher.java
new file mode 100644
index 0000000..bef03e1
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/Batcher.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import org.apache.usergrid.count.common.Count;
+
+
+/**
+ * Defines minimal set of batch submission operations
+ *
+ * @author zznate
+ */
+public interface Batcher {
+ void setBatchSubmitter( BatchSubmitter batchSubmitter );
+
+ void add( Count count );
+
+ long getOpCount();
+
+ long getBatchSubmissionCount();
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/CassandraCounterStore.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/CassandraCounterStore.java b/stack/core/src/main/java/org/apache/usergrid/count/CassandraCounterStore.java
new file mode 100644
index 0000000..26d610d
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/CassandraCounterStore.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.usergrid.count.common.Count;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import me.prettyprint.cassandra.model.HCounterColumnImpl;
+import me.prettyprint.cassandra.serializers.ByteBufferSerializer;
+import me.prettyprint.hector.api.Keyspace;
+import me.prettyprint.hector.api.factory.HFactory;
+import me.prettyprint.hector.api.mutation.Mutator;
+
+
+/**
+ * Encapsulate counter writes to Cassandra
+ *
+ * @author zznate
+ */
+public class CassandraCounterStore implements CounterStore {
+ private Logger log = LoggerFactory.getLogger( CassandraCounterStore.class );
+
+ // keep track of exceptions thrown in scheduler so we can reduce noise in logs
+ private Map<String, Integer> counterInsertFailures = new HashMap<String, Integer>();
+
+ private final Keyspace keyspace;
+
+
+ public CassandraCounterStore( Keyspace keyspace ) {
+ this.keyspace = keyspace;
+ }
+
+
+ public void save( Count count ) {
+ this.save( Arrays.asList( count ) );
+ }
+
+
+ public void save( Collection<Count> counts ) {
+ Map<String, Count> countHolder = new HashMap<String, Count>();
+ for ( Count count : counts ) {
+ Count c = countHolder.get( count.getCounterName() );
+ if ( c != null ) {
+ c.apply( count );
+ }
+ else {
+ countHolder.put( count.getCounterName(), count );
+ }
+ }
+ Mutator<ByteBuffer> mutator = HFactory.createMutator( keyspace, ByteBufferSerializer.get() );
+ for ( Count count : countHolder.values() ) {
+ mutator.addCounter( count.getKeyNameBytes(), count.getTableName(),
+ new HCounterColumnImpl( count.getColumnName(), count.getValue(),
+ count.getColumnNameSerializer() ) );
+ }
+ try {
+ mutator.execute();
+ }
+ catch ( Exception e ) {
+
+ // errors here happen a lot on shutdown, don't fill the logs with them
+ String error = e.getClass().getCanonicalName();
+ if (counterInsertFailures.get( error ) == null) {
+ log.error( "CounterStore insert failed, first instance", e);
+ counterInsertFailures.put( error, 1);
+
+ } else {
+ int count = counterInsertFailures.get(error) + 1;
+ counterInsertFailures.put(error, count);
+ if (log.isDebugEnabled()) {
+ log.debug( error + " caused CounterStore insert failure, count = " + count, e );
+ } else {
+ log.error( error + " caused CounterStore insert failure, count = " + count );
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/CassandraSubmitter.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/CassandraSubmitter.java b/stack/core/src/main/java/org/apache/usergrid/count/CassandraSubmitter.java
new file mode 100644
index 0000000..13f72c1
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/CassandraSubmitter.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import java.util.Collection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.usergrid.count.common.Count;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.yammer.metrics.Metrics;
+import com.yammer.metrics.core.Timer;
+import com.yammer.metrics.core.TimerContext;
+
+
+/**
+ * Submits directly to Cassandra for insertion
+ *
+ * @author zznate
+ */
+public class CassandraSubmitter implements BatchSubmitter {
+ private final Logger log = LoggerFactory.getLogger( CassandraSubmitter.class );
+
+ private final int threadCount = 3;
+ private final CassandraCounterStore cassandraCounterStore;
+
+ private final ExecutorService executor = Executors.newFixedThreadPool( threadCount );
+ private final Timer addTimer =
+ Metrics.newTimer( CassandraSubmitter.class, "submit_invocation", TimeUnit.MICROSECONDS, TimeUnit.SECONDS );
+
+
+ public CassandraSubmitter( CassandraCounterStore cassandraCounterStore ) {
+ this.cassandraCounterStore = cassandraCounterStore;
+ }
+
+
+ @Override
+ public Future submit( final Collection<Count> counts ) {
+ return executor.submit( new Callable<Object>() {
+ final TimerContext timer = addTimer.time();
+
+
+ @Override
+ public Object call() throws Exception {
+ cassandraCounterStore.save( counts );
+ timer.stop();
+ return true;
+ }
+ } );
+ }
+
+
+ @Override
+ public void shutdown() {
+ log.warn( "Shutting down CassandraSubmitter" );
+ executor.shutdown();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/CountProducer.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/CountProducer.java b/stack/core/src/main/java/org/apache/usergrid/count/CountProducer.java
new file mode 100644
index 0000000..6bbe3dc
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/CountProducer.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import org.apache.usergrid.count.common.Count;
+
+
+/** @author zznate */
+public interface CountProducer {
+ void send( Count count );
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/CounterProcessingUnavailableException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/CounterProcessingUnavailableException.java b/stack/core/src/main/java/org/apache/usergrid/count/CounterProcessingUnavailableException.java
new file mode 100644
index 0000000..50b9593
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/CounterProcessingUnavailableException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+/** @author zznate */
+public class CounterProcessingUnavailableException extends RuntimeException {
+
+ private static final String ERR_MSG = "Counter was not processed. Reason: ";
+
+
+ public CounterProcessingUnavailableException() {
+ super( ERR_MSG );
+ }
+
+
+ public CounterProcessingUnavailableException( String errMsg ) {
+ super( ERR_MSG + errMsg );
+ }
+
+
+ public CounterProcessingUnavailableException( String errMsg, Throwable t ) {
+ super( ERR_MSG + errMsg, t );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/CounterStore.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/CounterStore.java b/stack/core/src/main/java/org/apache/usergrid/count/CounterStore.java
new file mode 100644
index 0000000..595b55b
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/CounterStore.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import java.util.Collection;
+
+import org.apache.usergrid.count.common.Count;
+
+
+/** @author zznate */
+public interface CounterStore {
+ // TODO consider inforcing Async via Future<T> as return type
+ void save( Count count );
+
+ void save( Collection<Count> counts );
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/SimpleBatcher.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/SimpleBatcher.java b/stack/core/src/main/java/org/apache/usergrid/count/SimpleBatcher.java
new file mode 100644
index 0000000..6d685a9
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/SimpleBatcher.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import org.apache.usergrid.count.common.Count;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A simple Batcher implementation that keeps a sum of the number of {@link Count} operations which have been applied.
+ * Counters are aggregated by name.
+ *
+ * @author zznate
+ */
+public class SimpleBatcher extends AbstractBatcher {
+ private Logger log = LoggerFactory.getLogger( SimpleBatcher.class );
+
+ private boolean blockingSubmit = false;
+
+
+ public void setBlockingSubmit( boolean blockingSubmit ) {
+ this.blockingSubmit = blockingSubmit;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/Slf4JBatchSubmitter.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/Slf4JBatchSubmitter.java b/stack/core/src/main/java/org/apache/usergrid/count/Slf4JBatchSubmitter.java
new file mode 100644
index 0000000..bbfb5d1
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/Slf4JBatchSubmitter.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count;
+
+
+import java.util.Collection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.usergrid.count.common.Count;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.yammer.metrics.Metrics;
+import com.yammer.metrics.core.Timer;
+import com.yammer.metrics.core.TimerContext;
+
+
+/**
+ * A BatchSubmitter that prints contents to the configured slf4j logger logger
+ *
+ * @author zznate
+ */
+public class Slf4JBatchSubmitter implements BatchSubmitter {
+
+ // TODO custom logger for printing counts
+ // - should be configed programatically
+ private Logger log = LoggerFactory.getLogger( Slf4JBatchSubmitter.class );
+
+ private int threadCount = 3;
+
+ private ExecutorService executor = Executors.newFixedThreadPool( threadCount );
+ private final Timer addTimer =
+ Metrics.newTimer( Slf4JBatchSubmitter.class, "submit_invocation", TimeUnit.MICROSECONDS, TimeUnit.SECONDS );
+
+
+ @Override
+ public Future submit( final Collection<Count> counts ) {
+ return executor.submit( new Callable<Object>() {
+ final TimerContext timer = addTimer.time();
+
+
+ @Override
+ public Object call() throws Exception {
+ // TODO perhaps this could be pushed down further into CountProducer Impl?
+ // - this would leave generic submitter class
+ for ( Count c : counts ) {
+ log.info( "found count {}", c );
+ }
+ timer.stop();
+ return true;
+ }
+ } );
+ }
+
+
+ public void shutdown() {
+ log.warn( "Shutdown Slf4jBatchSubmitter" );
+ executor.shutdown();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/common/Count.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/common/Count.java b/stack/core/src/main/java/org/apache/usergrid/count/common/Count.java
new file mode 100644
index 0000000..c912bbf
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/common/Count.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count.common;
+
+
+import java.nio.ByteBuffer;
+
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang.StringUtils;
+
+import me.prettyprint.cassandra.serializers.SerializerTypeInferer;
+import me.prettyprint.cassandra.serializers.StringSerializer;
+import me.prettyprint.hector.api.Serializer;
+
+import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
+
+
+/**
+ * Loosely models a 'count' of things to
+ *
+ * @author zznate
+ */
+@JsonAutoDetect(creatorVisibility = Visibility.PUBLIC_ONLY)
+public class Count<K, C> {
+ private static final StringSerializer se = StringSerializer.get();
+
+ @JsonProperty
+ private final String tableName;
+ @JsonProperty
+ private final K keyName;
+ @JsonProperty
+ private final C columnName;
+ @JsonProperty
+ private long value;
+
+ private Serializer<K> keySerializer;
+ private Serializer<C> columnNameSerializer;
+ private String counterName;
+
+
+ @JsonCreator
+ public Count( @JsonProperty(value = "tableName") String tableName, @JsonProperty(value = "keyName") K keyName,
+ @JsonProperty(value = "columnName") C columnName, @JsonProperty(value = "value") long value ) {
+ this.tableName = tableName;
+ this.keyName = keyName;
+ this.columnName = columnName;
+ this.value = value;
+ this.keySerializer = SerializerTypeInferer.getSerializer( keyName );
+ this.columnNameSerializer = SerializerTypeInferer.getSerializer( columnName );
+ }
+
+
+ public Count apply( Count count ) {
+ if ( !StringUtils.equals( count.getCounterName(), getCounterName() ) ) {
+ throw new IllegalArgumentException( "Attempt to apply a counter with a different name" );
+ }
+ this.value += count.getValue();
+ return this;
+ }
+
+
+ /** the counter name should uniquely identify the entity being counted. */
+ @JsonIgnore
+ public String getCounterName() {
+ if ( counterName == null ) {
+ counterName = tableName + ":" + Hex.encodeHexString( getKeyNameBytes().array() ) + ":" + Hex
+ .encodeHexString( getColumnNameBytes().array() );
+ }
+ return counterName;
+ }
+
+
+ public long getValue() {
+ return value;
+ }
+
+
+ public C getColumnName() {
+ return columnName;
+ }
+
+
+ public K getKeyName() {
+ return keyName;
+ }
+
+
+ @JsonIgnore
+ public ByteBuffer getKeyNameBytes() {
+ return keySerializer.toByteBuffer( keyName );
+ }
+
+
+ @JsonIgnore
+ public ByteBuffer getColumnNameBytes() {
+ return columnNameSerializer.toByteBuffer( columnName );
+ }
+
+
+ @JsonIgnore
+ public Serializer<K> getKeySerializer() {
+ return keySerializer;
+ }
+
+
+ @JsonIgnore
+ public Serializer<C> getColumnNameSerializer() {
+ return columnNameSerializer;
+ }
+
+
+ public String getTableName() {
+ return tableName;
+ }
+
+
+ @Override
+ public String toString() {
+ return "Counter Name: ".concat( getCounterName() ).concat( " value: " ).concat( Long.toString( value ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/common/CountSerDeUtils.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/common/CountSerDeUtils.java b/stack/core/src/main/java/org/apache/usergrid/count/common/CountSerDeUtils.java
new file mode 100644
index 0000000..84492dc
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/common/CountSerDeUtils.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count.common;
+
+
+import java.io.IOException;
+
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonMethod;
+import org.codehaus.jackson.map.ObjectMapper;
+
+
+/** @author zznate */
+public class CountSerDeUtils {
+
+ public static String serialize( Count count ) {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ return mapper.writeValueAsString( count );
+ }
+ catch ( Exception ex ) {
+ throw new CountTransportSerDeException( "Problem in serialize() call", ex );
+ }
+ }
+
+
+ public static Count deserialize( String json ) {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setVisibility( JsonMethod.CREATOR, JsonAutoDetect.Visibility.ANY );
+
+ try {
+ return mapper.readValue( json, Count.class );
+ }
+ catch ( IOException e ) {
+ throw new CountTransportSerDeException( "Problem in deserialize() call", e );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/common/CountTransportSerDeException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/common/CountTransportSerDeException.java b/stack/core/src/main/java/org/apache/usergrid/count/common/CountTransportSerDeException.java
new file mode 100644
index 0000000..e1b7188
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/common/CountTransportSerDeException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.count.common;
+
+
+/** @author zznate */
+public class CountTransportSerDeException extends RuntimeException {
+ private static final String DEF_MSG =
+ "There was a serialization/deserialization problem in Count transport. Reason: ";
+
+
+ public CountTransportSerDeException() {
+ super( DEF_MSG );
+ }
+
+
+ public CountTransportSerDeException( String msg ) {
+ super( DEF_MSG + msg );
+ }
+
+
+ public CountTransportSerDeException( String msg, Throwable t ) {
+ super( DEF_MSG + msg, t );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/count/package-info.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/count/package-info.java b/stack/core/src/main/java/org/apache/usergrid/count/package-info.java
new file mode 100644
index 0000000..50e5957
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/count/package-info.java
@@ -0,0 +1 @@
+package org.apache.usergrid.count;
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/exception/JsonReadException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/exception/JsonReadException.java b/stack/core/src/main/java/org/apache/usergrid/exception/JsonReadException.java
new file mode 100644
index 0000000..7ddbfb4
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/exception/JsonReadException.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.exception;
+
+
+public class JsonReadException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+
+ public JsonReadException( String msg, Throwable t ) {
+ super( msg, t );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/exception/JsonWriteException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/exception/JsonWriteException.java b/stack/core/src/main/java/org/apache/usergrid/exception/JsonWriteException.java
new file mode 100644
index 0000000..4feb886
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/exception/JsonWriteException.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.exception;
+
+
+public class JsonWriteException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+
+ public JsonWriteException( String msg, Throwable t ) {
+ super( msg, t );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/exception/NotImplementedException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/exception/NotImplementedException.java b/stack/core/src/main/java/org/apache/usergrid/exception/NotImplementedException.java
new file mode 100644
index 0000000..17a6a6c
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/exception/NotImplementedException.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.exception;
+
+
+public class NotImplementedException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ *
+ */
+ public NotImplementedException() {
+ super();
+ }
+
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public NotImplementedException( String message, Throwable cause ) {
+ super( message, cause );
+ }
+
+
+ /**
+ * @param message
+ */
+ public NotImplementedException( String message ) {
+ super( message );
+ }
+
+
+ /**
+ * @param cause
+ */
+ public NotImplementedException( Throwable cause ) {
+ super( cause );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/Lock.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/Lock.java b/stack/core/src/main/java/org/apache/usergrid/locking/Lock.java
new file mode 100644
index 0000000..3826818
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/Lock.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking;
+
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.usergrid.locking.exception.UGLockException;
+
+
+/**
+ * The lock object to acquire
+ *
+ * @author tnine
+ */
+public interface Lock {
+
+ /**
+ * Acquire the lock. Wait the specified amount of time before giving up
+ *
+ * @param timeout The amount of time to wait
+ * @param time the units of time to wait
+ */
+ public boolean tryLock( long timeout, TimeUnit time ) throws UGLockException;
+
+ /** Block until a lock is available */
+ public void lock() throws UGLockException;
+
+ /** Release the lock */
+ public void unlock() throws UGLockException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/LockHelper.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/LockHelper.java b/stack/core/src/main/java/org/apache/usergrid/locking/LockHelper.java
new file mode 100644
index 0000000..ac92ac4
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/LockHelper.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking;
+
+
+import java.util.UUID;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.usergrid.locking.exception.UGLockException;
+import org.apache.usergrid.locking.noop.NoOpLockImpl;
+
+import static org.apache.usergrid.locking.LockPathBuilder.buildPath;
+import static org.apache.usergrid.utils.ConversionUtils.bytes;
+
+
+/** @author tnine */
+public class LockHelper {
+
+
+ private static final NoOpLockImpl NO_OP_LOCK = new NoOpLockImpl();
+
+
+ /**
+ * Build a string path for this lock. Since it's specifically for updating a property, the property needs appended
+ * to the path. If the property is null, it's getting deleted, so a lock on it isn't neccessary. In that case, a
+ * no op lock is returned
+ */
+ public static Lock getUniqueUpdateLock( LockManager manager, UUID applicationId, Object value, String... path )
+ throws UGLockException {
+ //we have no value, therefore there's nothing to lock
+ if ( value == null ) {
+ return NO_OP_LOCK;
+ }
+
+ return manager.createLock( applicationId, buildPath( Hex.encodeHexString( bytes( value ) ), path ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/LockManager.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/LockManager.java b/stack/core/src/main/java/org/apache/usergrid/locking/LockManager.java
new file mode 100644
index 0000000..db7d079
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/LockManager.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking;
+
+
+import java.util.UUID;
+
+import org.apache.usergrid.locking.exception.UGLockException;
+
+
+/**
+ * This Interface to a class responsible for distributed lock across system.
+ *
+ * @author tnine
+ */
+public interface LockManager {
+
+ /**
+ * Acquires a lock on a particular path.
+ *
+ * @param applicationId application UUID
+ * @param path a unique path
+ *
+ * @throws UGLockException if the lock cannot be acquired
+ */
+ public Lock createLock( final UUID applicationId, final String... path );
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/LockPathBuilder.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/LockPathBuilder.java b/stack/core/src/main/java/org/apache/usergrid/locking/LockPathBuilder.java
new file mode 100644
index 0000000..5842a07
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/LockPathBuilder.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking;
+
+
+import java.util.UUID;
+
+
+/**
+ * Helper class that contains the logic to build a lock path
+ *
+ * @author eanuff
+ */
+public class LockPathBuilder {
+
+ private static final String SLASH = "/";
+
+
+ /** Build a string path for this lock */
+ public static String buildPath( UUID applicationId, String... path ) {
+ StringBuilder builder = new StringBuilder();
+ builder.append( SLASH );
+ builder.append( applicationId.toString() );
+
+ for ( String element : path ) {
+ builder.append( SLASH );
+ builder.append( element );
+ }
+ return builder.toString();
+ }
+
+
+ /**
+ * Build a string path for this lock
+ *
+ * @param The binary value to append to the end of the lock path
+ * @param path The values to prepend to build path
+ */
+ public static String buildPath( String binaryValue, String... path ) {
+
+ StringBuilder builder = new StringBuilder();
+
+ for ( String element : path ) {
+ builder.append( SLASH );
+ builder.append( element );
+ }
+
+ builder.append( SLASH );
+ builder.append( binaryValue );
+
+ builder.deleteCharAt( 0 );
+
+ return builder.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockImpl.java
new file mode 100644
index 0000000..1812f37
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockImpl.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.cassandra;
+
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.exception.UGLockException;
+
+import me.prettyprint.hector.api.locking.HLock;
+import me.prettyprint.hector.api.locking.HLockManager;
+import me.prettyprint.hector.api.locking.HLockTimeoutException;
+
+
+/** @author tnine */
+public class HectorLockImpl implements Lock {
+
+ private HLock lock;
+ private HLockManager lm;
+ private AtomicInteger count = new AtomicInteger();
+
+
+ /**
+ *
+ */
+ public HectorLockImpl( HLock lock, HLockManager lm ) {
+ this.lock = lock;
+ this.lm = lm;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#acquire(long, java.util.concurrent.TimeUnit)
+ */
+ @Override
+ public boolean tryLock( long timeout, TimeUnit time ) throws UGLockException {
+ try {
+ lm.acquire( this.lock, time.toMillis( timeout ) );
+ count.incrementAndGet();
+ }
+ catch ( HLockTimeoutException hlte ) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#lock()
+ */
+ @Override
+ public void lock() throws UGLockException {
+ lm.acquire( lock );
+ count.incrementAndGet();
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#release()
+ */
+ @Override
+ public void unlock() throws UGLockException {
+ int current = count.decrementAndGet();
+
+ if ( current == 0 ) {
+ lm.release( this.lock );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockManagerImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockManagerImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockManagerImpl.java
new file mode 100644
index 0000000..6642f97
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/cassandra/HectorLockManagerImpl.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.cassandra;
+
+
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+
+import me.prettyprint.cassandra.locking.HLockManagerImpl;
+import me.prettyprint.hector.api.Cluster;
+import me.prettyprint.hector.api.ConsistencyLevelPolicy;
+import me.prettyprint.hector.api.locking.HLockManager;
+import me.prettyprint.hector.api.locking.HLockManagerConfigurator;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.LockManager;
+import org.apache.usergrid.locking.LockPathBuilder;
+import org.springframework.util.Assert;
+
+
+/**
+ * Uses the hector based locking implementation to obtain locks
+ *
+ * @author tnine
+ */
+public class HectorLockManagerImpl implements LockManager {
+ private int replicationFactor = 1;
+ private int numberOfLockObserverThreads = 1;
+ private long lockTtl = 2000;
+ private String keyspaceName;
+ private Cluster cluster;
+ private HLockManager lm;
+ private ConsistencyLevelPolicy consistencyLevelPolicy;
+
+
+ /**
+ *
+ */
+ public HectorLockManagerImpl() {
+ }
+
+
+ @PostConstruct
+ public void init() {
+ HLockManagerConfigurator hlc = new HLockManagerConfigurator();
+ hlc.setReplicationFactor( replicationFactor );
+ hlc.setKeyspaceName( keyspaceName );
+ hlc.setNumberOfLockObserverThreads( numberOfLockObserverThreads );
+ hlc.setLocksTTLInMillis( lockTtl );
+ lm = new HLockManagerImpl( cluster, hlc );
+ if ( consistencyLevelPolicy != null ) {
+ lm.getKeyspace().setConsistencyLevelPolicy(consistencyLevelPolicy);
+ }
+ // if consistencyLevelPolicy == null, use hector's default, which is QuorumAll, no need to explicitly set
+ lm.init();
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.usergrid.locking.LockManager#createLock(java.util.UUID,
+ * java.lang.String[])
+ */
+ @Override
+ public Lock createLock( UUID applicationId, String... path ) {
+
+ String lockPath = LockPathBuilder.buildPath( applicationId, path );
+
+ return new HectorLockImpl( lm.createLock( lockPath ), lm );
+ }
+
+
+ /**
+ * Note that in a real environment this MUST be an odd number. Locks are read and written at QUORUM. RF >= 3 is
+ * preferred for failure tolerance and replication. Defaults to 1
+ *
+ * @param replicationFactor the replicationFactor to set
+ */
+ public void setReplicationFactor( int replicationFactor ) {
+
+ Assert.isTrue( numberOfLockObserverThreads % 2 != 0, "You must specify an odd number for replication factor" );
+
+ this.replicationFactor = replicationFactor;
+ }
+
+
+ /**
+ * Set the number of threads the lock heartbeat executor uses. Must accommodate the total number of locks that may
+ * exist in the system. Locks are always renewed at the ttl/2 time.
+ *
+ * @param numberOfLockObserverThreads the numberOfLockObserverThreads to set
+ */
+ public void setNumberOfLockObserverThreads( int numberOfLockObserverThreads ) {
+ this.numberOfLockObserverThreads = numberOfLockObserverThreads;
+ }
+
+
+ /**
+ * The amount of time a lock must not be renewed before it times out. Set in milliseconds. 2000 is the default
+ *
+ * @param lockTtl the lockTtl to set
+ */
+ public void setLockTtl( long lockTtl ) {
+ this.lockTtl = lockTtl;
+ }
+
+
+ /** @param keyspaceName the keyspaceName to set */
+ public void setKeyspaceName( String keyspaceName ) {
+ this.keyspaceName = keyspaceName;
+ }
+
+
+ /** @param cluster the cluster to set */
+ public void setCluster( Cluster cluster ) {
+ this.cluster = cluster;
+ }
+
+
+ /**
+ * @param consistencyLevelPolicy the consistencyLevelPolicy to set
+ */
+ public void setConsistencyLevelPolicy(ConsistencyLevelPolicy consistencyLevelPolicy) {
+ this.consistencyLevelPolicy = consistencyLevelPolicy;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/exception/UGLockException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/exception/UGLockException.java b/stack/core/src/main/java/org/apache/usergrid/locking/exception/UGLockException.java
new file mode 100644
index 0000000..21a610d
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/exception/UGLockException.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.exception;
+
+
+public class UGLockException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -8902830935510966393L;
+
+
+ public UGLockException() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public UGLockException( String message, Throwable cause ) {
+ super( message, cause );
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public UGLockException( String message ) {
+ super( message );
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public UGLockException( Throwable cause ) {
+ super( cause );
+ // TODO Auto-generated constructor stub
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockImpl.java
new file mode 100644
index 0000000..dd1cc39
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockImpl.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.noop;
+
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.exception.UGLockException;
+
+
+/** @author tnine */
+public class NoOpLockImpl implements Lock {
+
+ /**
+ *
+ */
+ public NoOpLockImpl() {
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#acquire(long, java.util.concurrent.TimeUnit)
+ */
+ @Override
+ public boolean tryLock( long timeout, TimeUnit time ) throws UGLockException {
+ //no op
+ return true;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#lock()
+ */
+ @Override
+ public void lock() throws UGLockException {
+ //no op
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#release()
+ */
+ @Override
+ public void unlock() throws UGLockException {
+ //no op
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockManagerImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockManagerImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockManagerImpl.java
new file mode 100644
index 0000000..467f5a5
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/noop/NoOpLockManagerImpl.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.noop;
+
+
+import java.util.UUID;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.LockManager;
+
+
+/** This is a no-op manager used for testing. */
+public class NoOpLockManagerImpl implements LockManager {
+
+ public NoOpLockManagerImpl() {
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.LockManager#createLock(java.util.UUID, java.lang.String[])
+ */
+ @Override
+ public Lock createLock( UUID applicationId, String... path ) {
+ return new NoOpLockImpl();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockImpl.java
new file mode 100644
index 0000000..aec969a
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockImpl.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.singlenode;
+
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.exception.UGLockException;
+
+
+/** @author tnine */
+public class SingleNodeLockImpl implements Lock {
+
+ private final ReentrantLock lock;
+
+
+ /**
+ *
+ */
+ public SingleNodeLockImpl( ReentrantLock lock ) {
+ this.lock = lock;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#acquire(long)
+ */
+ @Override
+ public boolean tryLock( long timeout, TimeUnit time ) throws UGLockException {
+ try {
+ return this.lock.tryLock( timeout, time );
+ }
+ catch ( InterruptedException e ) {
+ throw new UGLockException( "Couldn't get the lock", e );
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#lock()
+ */
+ @Override
+ public void lock() throws UGLockException {
+ this.lock.lock();
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#release()
+ */
+ @Override
+ public void unlock() throws UGLockException {
+ this.lock.unlock();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockManagerImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockManagerImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockManagerImpl.java
new file mode 100644
index 0000000..b75ad76
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/singlenode/SingleNodeLockManagerImpl.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.singlenode;
+
+
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.LockManager;
+import org.apache.usergrid.locking.LockPathBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
+
+
+/**
+ * Single Node implementation for {@link LockManager} Note that this implementation has not been used in a production
+ * environment.
+ * <p/>
+ * The hector based implementation is the preferred production locking system
+ */
+public class SingleNodeLockManagerImpl implements LockManager {
+
+ private static final Logger logger = LoggerFactory.getLogger( SingleNodeLockManagerImpl.class );
+
+ public static final long MILLI_EXPIRATION = 5000;
+
+ /** Lock cache that sill expire after 5 seconds of no use for a lock path */
+ private LoadingCache<String, ReentrantLock> locks =
+ CacheBuilder.newBuilder().expireAfterWrite( MILLI_EXPIRATION, TimeUnit.MILLISECONDS )
+ // use weakValues. We want want entries removed if they're not being
+ // referenced by another
+ // thread somewhere and GC occurs
+ .weakValues().removalListener( new RemovalListener<String, ReentrantLock>() {
+
+ @Override
+ public void onRemoval( RemovalNotification<String, ReentrantLock> notification ) {
+ logger.debug( "Evicting reentrant lock for {}", notification.getKey() );
+ }
+ } ).build( new CacheLoader<String, ReentrantLock>() {
+
+ @Override
+ public ReentrantLock load( String arg0 ) throws Exception {
+ return new ReentrantLock( true );
+ }
+ } );
+
+
+ /** Default constructor. */
+ public SingleNodeLockManagerImpl() {
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.usergrid.locking.LockManager#createLock(java.util.UUID,
+ * java.lang.String[])
+ */
+ @Override
+ public Lock createLock( UUID applicationId, String... path ) {
+
+ String lockPath = LockPathBuilder.buildPath( applicationId, path );
+
+ try {
+ return new SingleNodeLockImpl( locks.get( lockPath ) );
+ }
+ catch ( ExecutionException e ) {
+ throw new RuntimeException( "Unable to create lock in cache", e );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZooKeeperLockManagerImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZooKeeperLockManagerImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZooKeeperLockManagerImpl.java
new file mode 100644
index 0000000..e0c7ae2
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZooKeeperLockManagerImpl.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.zookeeper;
+
+
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.LockManager;
+import org.apache.usergrid.locking.LockPathBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.curator.RetryPolicy;
+import com.netflix.curator.framework.CuratorFramework;
+import com.netflix.curator.framework.CuratorFrameworkFactory;
+import com.netflix.curator.framework.recipes.locks.InterProcessMutex;
+import com.netflix.curator.retry.ExponentialBackoffRetry;
+
+
+/** Implementation for Zookeeper service that handles global locks. */
+public final class ZooKeeperLockManagerImpl implements LockManager {
+
+ private String hostPort;
+
+ private int sessionTimeout = 2000;
+
+ private int maxAttempts = 5;
+
+ private CuratorFramework client;
+
+
+ public ZooKeeperLockManagerImpl( String hostPort, int sessionTimeout, int maxAttemps ) {
+ this.hostPort = hostPort;
+ this.sessionTimeout = sessionTimeout;
+ this.maxAttempts = maxAttemps;
+ init();
+ }
+
+
+ public ZooKeeperLockManagerImpl() {
+ }
+
+
+ @PostConstruct
+ public void init() {
+ RetryPolicy retryPolicy = new ExponentialBackoffRetry( sessionTimeout, maxAttempts );
+ client = CuratorFrameworkFactory.newClient( hostPort, retryPolicy );
+ client.start();
+ }
+
+
+ protected static final Logger logger = LoggerFactory.getLogger( ZooKeeperLockManagerImpl.class );
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.usergrid.locking.LockManager#createLock(java.util.UUID,
+ * java.lang.String[])
+ */
+ @Override
+ public Lock createLock( UUID applicationId, String... path ) {
+ String lockPath = LockPathBuilder.buildPath( applicationId, path );
+
+
+ return new ZookeeperLockImpl( new InterProcessMutex( client, lockPath ) );
+ }
+
+
+ public String getHostPort() {
+ return hostPort;
+ }
+
+
+ public void setHostPort( String hostPort ) {
+ this.hostPort = hostPort;
+ }
+
+
+ public int getSessionTimeout() {
+ return sessionTimeout;
+ }
+
+
+ public void setSessionTimeout( int sessionTimeout ) {
+ this.sessionTimeout = sessionTimeout;
+ }
+
+
+ public int getMaxAttempts() {
+ return maxAttempts;
+ }
+
+
+ public void setMaxAttempts( int maxAttemps ) {
+ this.maxAttempts = maxAttemps;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZookeeperLockImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZookeeperLockImpl.java b/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZookeeperLockImpl.java
new file mode 100644
index 0000000..185f37c
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/locking/zookeeper/ZookeeperLockImpl.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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.locking.zookeeper;
+
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.usergrid.locking.Lock;
+import org.apache.usergrid.locking.exception.UGLockException;
+
+import com.netflix.curator.framework.recipes.locks.InterProcessMutex;
+
+
+/**
+ * Wrapper for locks using curator
+ *
+ * @author tnine
+ */
+public class ZookeeperLockImpl implements Lock {
+
+
+ private InterProcessMutex zkMutex;
+
+
+ /**
+ *
+ */
+ public ZookeeperLockImpl( InterProcessMutex zkMutex ) {
+ this.zkMutex = zkMutex;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#tryLock(long, java.util.concurrent.TimeUnit)
+ */
+ @Override
+ public boolean tryLock( long timeout, TimeUnit time ) throws UGLockException {
+
+ try {
+ return zkMutex.acquire( timeout, time );
+ }
+ catch ( Exception e ) {
+ throw new UGLockException( "Unable to obtain lock", e );
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#lock()
+ */
+ @Override
+ public void lock() throws UGLockException {
+ try {
+ zkMutex.acquire();
+ }
+ catch ( Exception e ) {
+ throw new UGLockException( "Unable to obtain lock", e );
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.usergrid.locking.Lock#unlock()
+ */
+ @Override
+ public void unlock() throws UGLockException {
+ try {
+ zkMutex.release();
+ }
+ catch ( Exception e ) {
+ throw new UGLockException( "Unable to obtain lock", e );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/2c2acbe4/stack/core/src/main/java/org/apache/usergrid/mq/CounterQuery.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/mq/CounterQuery.java b/stack/core/src/main/java/org/apache/usergrid/mq/CounterQuery.java
new file mode 100644
index 0000000..2a0f074
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/mq/CounterQuery.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright 2012 Apigee Corporation
+ *
+ * Licensed 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;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.usergrid.mq.Query.CounterFilterPredicate;
+import org.apache.usergrid.persistence.CounterResolution;
+import org.apache.usergrid.utils.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.usergrid.utils.ClassUtils.cast;
+import static org.apache.usergrid.utils.ListUtils.firstBoolean;
+import static org.apache.usergrid.utils.ListUtils.firstInteger;
+import static org.apache.usergrid.utils.ListUtils.firstLong;
+import static org.apache.usergrid.utils.ListUtils.isEmpty;
+import static org.apache.usergrid.utils.MapUtils.toMapList;
+
+
+public class CounterQuery {
+
+ public static final Logger logger = LoggerFactory.getLogger( CounterQuery.class );
+
+ public static final int DEFAULT_MAX_RESULTS = 10;
+
+ private int limit = 0;
+ boolean limitSet = false;
+
+ private Long startTime;
+ private Long finishTime;
+ private boolean pad;
+ private CounterResolution resolution = CounterResolution.ALL;
+ private List<String> categories;
+ private List<CounterFilterPredicate> counterFilters;
+
+
+ public CounterQuery() {
+ }
+
+
+ public CounterQuery( CounterQuery q ) {
+ if ( q != null ) {
+ limit = q.limit;
+ limitSet = q.limitSet;
+ startTime = q.startTime;
+ finishTime = q.finishTime;
+ resolution = q.resolution;
+ pad = q.pad;
+ categories = q.categories != null ? new ArrayList<String>( q.categories ) : null;
+ counterFilters =
+ q.counterFilters != null ? new ArrayList<CounterFilterPredicate>( q.counterFilters ) : null;
+ }
+ }
+
+
+ public static CounterQuery newQueryIfNull( CounterQuery query ) {
+ if ( query == null ) {
+ query = new CounterQuery();
+ }
+ return query;
+ }
+
+
+ public static CounterQuery fromJsonString( String json ) {
+ Object o = JsonUtils.parse( json );
+ if ( o instanceof Map ) {
+ @SuppressWarnings({ "unchecked", "rawtypes" }) Map<String, List<String>> params =
+ cast( toMapList( ( Map ) o ) );
+ return fromQueryParams( params );
+ }
+ return null;
+ }
+
+
+ public static CounterQuery fromQueryParams( Map<String, List<String>> params ) {
+
+ CounterQuery q = null;
+ Integer limit = null;
+ Long startTime = null;
+ Long finishTime = null;
+ Boolean pad = null;
+ CounterResolution resolution = null;
+ List<CounterFilterPredicate> counterFilters = null;
+ List<String> categories = null;
+
+ List<String> l = null;
+
+ limit = firstInteger( params.get( "limit" ) );
+ startTime = firstLong( params.get( "start_time" ) );
+ finishTime = firstLong( params.get( "end_time" ) );
+
+ l = params.get( "resolution" );
+ if ( !isEmpty( l ) ) {
+ resolution = CounterResolution.fromString( l.get( 0 ) );
+ }
+
+ categories = params.get( "category" );
+
+ l = params.get( "counter" );
+ if ( !isEmpty( l ) ) {
+ counterFilters = CounterFilterPredicate.fromList( l );
+ }
+
+ pad = firstBoolean( params.get( "pad" ) );
+
+ if ( limit != null ) {
+ q = newQueryIfNull( q );
+ q.setLimit( limit );
+ }
+
+ if ( startTime != null ) {
+ q = newQueryIfNull( q );
+ q.setStartTime( startTime );
+ }
+
+ if ( finishTime != null ) {
+ q = newQueryIfNull( q );
+ q.setFinishTime( finishTime );
+ }
+
+ if ( resolution != null ) {
+ q = newQueryIfNull( q );
+ q.setResolution( resolution );
+ }
+
+ if ( categories != null ) {
+ q = newQueryIfNull( q );
+ q.setCategories( categories );
+ }
+
+ if ( counterFilters != null ) {
+ q = newQueryIfNull( q );
+ q.setCounterFilters( counterFilters );
+ }
+
+ if ( pad != null ) {
+ q = newQueryIfNull( q );
+ q.setPad( pad );
+ }
+
+ return q;
+ }
+
+
+ public int getLimit() {
+ return getLimit( DEFAULT_MAX_RESULTS );
+ }
+
+
+ public int getLimit( int defaultMax ) {
+ if ( limit <= 0 ) {
+ if ( defaultMax > 0 ) {
+ return defaultMax;
+ }
+ else {
+ return DEFAULT_MAX_RESULTS;
+ }
+ }
+ return limit;
+ }
+
+
+ public void setLimit( int limit ) {
+ limitSet = true;
+ this.limit = limit;
+ }
+
+
+ public CounterQuery withLimit( int limit ) {
+ limitSet = true;
+ this.limit = limit;
+ return this;
+ }
+
+
+ public boolean isLimitSet() {
+ return limitSet;
+ }
+
+
+ public Long getStartTime() {
+ return startTime;
+ }
+
+
+ public void setStartTime( Long startTime ) {
+ this.startTime = startTime;
+ }
+
+
+ public CounterQuery withStartTime( Long startTime ) {
+ this.startTime = startTime;
+ return this;
+ }
+
+
+ public Long getFinishTime() {
+ return finishTime;
+ }
+
+
+ public void setFinishTime( Long finishTime ) {
+ this.finishTime = finishTime;
+ }
+
+
+ public CounterQuery withFinishTime( Long finishTime ) {
+ this.finishTime = finishTime;
+ return this;
+ }
+
+
+ public boolean isPad() {
+ return pad;
+ }
+
+
+ public void setPad( boolean pad ) {
+ this.pad = pad;
+ }
+
+
+ public CounterQuery withPad( boolean pad ) {
+ this.pad = pad;
+ return this;
+ }
+
+
+ public void setResolution( CounterResolution resolution ) {
+ this.resolution = resolution;
+ }
+
+
+ public CounterResolution getResolution() {
+ return resolution;
+ }
+
+
+ public CounterQuery withResolution( CounterResolution resolution ) {
+ this.resolution = resolution;
+ return this;
+ }
+
+
+ public List<String> getCategories() {
+ return categories;
+ }
+
+
+ public CounterQuery addCategory( String category ) {
+ if ( categories == null ) {
+ categories = new ArrayList<String>();
+ }
+ categories.add( category );
+ return this;
+ }
+
+
+ public void setCategories( List<String> categories ) {
+ this.categories = categories;
+ }
+
+
+ public CounterQuery withCategories( List<String> categories ) {
+ this.categories = categories;
+ return this;
+ }
+
+
+ public List<CounterFilterPredicate> getCounterFilters() {
+ return counterFilters;
+ }
+
+
+ public CounterQuery addCounterFilter( String counter ) {
+ CounterFilterPredicate p = CounterFilterPredicate.fromString( counter );
+ if ( p == null ) {
+ return this;
+ }
+ if ( counterFilters == null ) {
+ counterFilters = new ArrayList<CounterFilterPredicate>();
+ }
+ counterFilters.add( p );
+ return this;
+ }
+
+
+ public void setCounterFilters( List<CounterFilterPredicate> counterFilters ) {
+ this.counterFilters = counterFilters;
+ }
+
+
+ public CounterQuery withCounterFilters( List<CounterFilterPredicate> counterFilters ) {
+ this.counterFilters = counterFilters;
+ return this;
+ }
+}