All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.usergrid.persistence.cassandra.CounterUtils Maven / Gradle / Ivy

There is a newer version: 0.0.27.1
Show newest version
/*******************************************************************************
 * 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.usergrid.persistence.cassandra;

import static me.prettyprint.hector.api.factory.HFactory.createColumn;
import static me.prettyprint.hector.api.factory.HFactory.createCounterColumn;
import static org.usergrid.persistence.Schema.DICTIONARY_COUNTERS;
import static org.usergrid.persistence.cassandra.ApplicationCF.APPLICATION_AGGREGATE_COUNTERS;
import static org.usergrid.persistence.cassandra.ApplicationCF.ENTITY_COUNTERS;
import static org.usergrid.persistence.cassandra.ApplicationCF.ENTITY_DICTIONARIES;
import static org.usergrid.persistence.cassandra.CassandraPersistenceUtils.addInsertToMutator;
import static org.usergrid.persistence.cassandra.CassandraPersistenceUtils.key;
import static org.usergrid.utils.ConversionUtils.bytebuffer;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import me.prettyprint.cassandra.serializers.ByteBufferSerializer;
import me.prettyprint.cassandra.serializers.LongSerializer;
import me.prettyprint.cassandra.serializers.PrefixedSerializer;
import me.prettyprint.cassandra.serializers.StringSerializer;
import me.prettyprint.cassandra.serializers.UUIDSerializer;
import me.prettyprint.hector.api.beans.HCounterColumn;
import me.prettyprint.hector.api.mutation.Mutator;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usergrid.mq.Message;
import org.usergrid.mq.cassandra.QueuesCF;
import org.usergrid.persistence.CounterResolution;
import org.usergrid.persistence.entities.Event;

import com.usergrid.count.Batcher;
import com.usergrid.count.common.Count;

public class CounterUtils {

	public static final Logger logger = LoggerFactory
			.getLogger(CounterUtils.class);

	public static final LongSerializer le = new LongSerializer();
	public static final StringSerializer se = new StringSerializer();
	public static final ByteBufferSerializer be = new ByteBufferSerializer();
	public static final UUIDSerializer ue = new UUIDSerializer();

	private String counterType = "o";

	private Batcher batcher;

	public void setBatcher(Batcher batcher) {
		this.batcher = batcher;
	}

	/**
	 * Set the type to 'new' ("n"), 'parallel' ("p"), 'old' ("o" - the default)
	 * If not one of the above, do nothing
	 * 
	 * @param counterType
	 */
	public void setCounterType(String counterType) {
		if (counterType == null) {
			return;
		}
		if ("n".equals(counterType) || "p".equals(counterType)
				|| "o".equals(counterType)) {
			this.counterType = counterType;
		}
	}

	public boolean getIsCounterBatched() {
		return "n".equals(counterType);
	}

	public static class AggregateCounterSelection {
        public static final String COLON = ":";
        public static final String STAR = "*";
        String name;
		UUID userId;
		UUID groupId;
		UUID queueId;
		String category;

		public AggregateCounterSelection(String name, UUID userId,
				UUID groupId, UUID queueId, String category) {
			this.name = name.toLowerCase();
			this.userId = userId;
			this.groupId = groupId;
			this.queueId = queueId;
			this.category = category;
		}

        public void apply(String name, UUID userId,
                          UUID groupId, UUID queueId, String category) {
            this.name = name.toLowerCase();
            this.userId = userId;
            this.groupId = groupId;
            this.queueId = queueId;
            this.category = category;
        }


		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public UUID getUserId() {
			return userId;
		}

		public void setUserId(UUID userId) {
			this.userId = userId;
		}

		public UUID getGroupId() {
			return groupId;
		}

		public void setGroupId(UUID groupId) {
			this.groupId = groupId;
		}

		public UUID getQueueId() {
			return queueId;
		}

		public void setQueueId(UUID queueId) {
			this.queueId = queueId;
		}

		public String getCategory() {
			return category;
		}

		public void setCategory(String category) {
			this.category = category;
		}

		public String getRow(CounterResolution resolution) {
            return rowBuilder(name, userId, groupId, queueId, category, resolution);
		}

        public static String rowBuilder(String name, UUID userId,
                                  UUID groupId, UUID queueId, String category,
                                  CounterResolution resolution) {
            StringBuilder builder = new StringBuilder(name);
                        builder.append(COLON).append((userId != null ? userId.toString() : STAR))
                                .append(COLON).append(groupId != null ? groupId.toString() : STAR).append(COLON)
                                .append((queueId != null ? queueId.toString() : STAR)).append(COLON)
                                .append((category != null ? category : STAR)).append(COLON)
                                .append(resolution.name());
                        return builder.toString();
        }
	}

	public void addEventCounterMutations(Mutator m,
			UUID applicationId, Event event, long timestamp) {
		if (event.getCounters() != null) {
			for (Entry value : event.getCounters().entrySet()) {
				batchIncrementAggregateCounters(m, applicationId,
						event.getUser(), event.getGroup(), null,
						event.getCategory(), value.getKey().toLowerCase(),
						value.getValue(), event.getTimestamp(), timestamp);
			}
		}
	}

	public void addMessageCounterMutations(Mutator m,
			UUID applicationId, UUID queueId, Message msg, long timestamp) {
		if (msg.getCounters() != null) {
			for (Entry value : msg.getCounters().entrySet()) {
				batchIncrementAggregateCounters(m, applicationId, null, null,
						queueId, msg.getCategory(), value.getKey()
								.toLowerCase(), value.getValue(),
						msg.getTimestamp(), timestamp);
			}
		}
	}

	public void batchIncrementAggregateCounters(Mutator m,
			UUID applicationId, UUID userId, UUID groupId, UUID queueId,
			String category, Map counters, long timestamp) {
		if (counters != null) {
			for (Entry value : counters.entrySet()) {
				batchIncrementAggregateCounters(m, applicationId, userId,
						groupId, queueId, category, value.getKey()
								.toLowerCase(), value.getValue(), timestamp);
			}
		}
	}

	public void batchIncrementAggregateCounters(Mutator m,
			UUID applicationId, UUID userId, UUID groupId, UUID queueId,
			String category, String name, long value, long cassandraTimestamp) {
		batchIncrementAggregateCounters(m, applicationId, userId, groupId,
				queueId, category, name, value, cassandraTimestamp / 1000,
				cassandraTimestamp);
	}

	public void batchIncrementAggregateCounters(Mutator m,
			UUID applicationId, UUID userId, UUID groupId, UUID queueId,
			String category, String name, long value, long counterTimestamp,
			long cassandraTimestamp) {
		for (CounterResolution resolution : CounterResolution.values()) {
			logger.debug("BIAC for resolution {}", resolution);
			batchIncrementAggregateCounters(m, userId, groupId, queueId,
					category, resolution, name, value, counterTimestamp,
					applicationId);
			logger.debug("DONE BIAC for resolution {}", resolution);
		}
		batchIncrementEntityCounter(m, applicationId, name, value,
				cassandraTimestamp, applicationId);
		if (userId != null) {
			batchIncrementEntityCounter(m, userId, name, value,
					cassandraTimestamp, applicationId);
		}
		if (groupId != null) {
			batchIncrementEntityCounter(m, groupId, name, value,
					cassandraTimestamp, applicationId);
		}
	}

	private void batchIncrementAggregateCounters(Mutator m,
			UUID userId, UUID groupId, UUID queueId, String category,
			CounterResolution resolution, String name, long value,
			long counterTimestamp, UUID applicationId) {

		String[] segments = StringUtils.split(name, '.');
		for (int j = 0; j < segments.length; j++) {
			name = StringUtils.join(segments, '.', 0, j + 1);
			// skip system counter
			if ("system".equals(name)) {
				continue;
			}

			// *:*:*:*
			handleAggregateCounterRow(
					m,
					AggregateCounterSelection.rowBuilder(name, null, null, null, null,
							resolution), resolution.round(counterTimestamp),
					value, applicationId);
			String currentRow = null;
			HashSet rowSet = new HashSet(16);
			for (int i = 0; i < 16; i++) {

				boolean include_user = (i & 0x01) != 0;
				boolean include_group = (i & 0x02) != 0;
				boolean include_queue = (i & 0x04) != 0;
				boolean include_category = (i & 0x08) != 0;

				Object[] parameters = { include_user ? userId : null,
						include_group ? groupId : null,
						include_queue ? queueId : null,
						include_category ? category : null };
				int non_null = 0;
				for (Object p : parameters) {
					if (p != null) {
						non_null++;
					}
				}
				currentRow = AggregateCounterSelection.rowBuilder(name, (UUID) parameters[0],
						(UUID) parameters[1], (UUID) parameters[2],
						(String) parameters[3], resolution);

				if (non_null > 0 && !rowSet.contains(currentRow)) {
					rowSet.add(currentRow);
					handleAggregateCounterRow(m, currentRow,
							resolution.round(counterTimestamp), value,
							applicationId);
				}

			}
		}
	}

	private void handleAggregateCounterRow(Mutator m, String key,
			long column, long value, UUID applicationId) {
		if (logger.isDebugEnabled()) {
			logger.info(
					"HACR: aggregateRow for app {} with key {} column {} and value {}",
					new Object[] { applicationId, key, column, value });
		}
		if ("o".equals(counterType) || "p".equals(counterType)) {
			if (m != null) {
				HCounterColumn c = createCounterColumn(column, value, le);
				m.addCounter(bytebuffer(key),
						APPLICATION_AGGREGATE_COUNTERS.toString(), c);
			}
		}
		if ("n".equals(counterType) || "p".equals(counterType)) {
			// create and add Count
			PrefixedSerializer ps = new PrefixedSerializer(applicationId,
					UUIDSerializer.get(), StringSerializer.get());
			batcher.add(new Count(APPLICATION_AGGREGATE_COUNTERS.toString(), ps
					.toByteBuffer(key), column, value));
		}
	}

	public AggregateCounterSelection getAggregateCounterSelection(String name,
			UUID userId, UUID groupId, UUID queueId, String category) {
		return new AggregateCounterSelection(name, userId, groupId, queueId,
				category);
	}

	public String getAggregateCounterRow(String name, UUID userId,
			UUID groupId, UUID queueId, String category,
			CounterResolution resolution) {
		return AggregateCounterSelection.rowBuilder(name, userId, groupId, queueId,
				category,resolution);
	}

	public List getAggregateCounterRows(
			List selections,
			CounterResolution resolution) {
		List keys = new ArrayList();
		for (AggregateCounterSelection selection : selections) {
			keys.add(selection.getRow(resolution));
		}
		return keys;
	}

	private Mutator batchIncrementEntityCounter(
			Mutator m, UUID entityId, String name, Long value,
			long timestamp, UUID applicationId) {
		if (logger.isDebugEnabled()) {
			logger.debug(
					"BIEC: Incrementing property {} of entity {} by value {}",
					new Object[] { name, entityId, value });
		}
		addInsertToMutator(m, ENTITY_DICTIONARIES,
				key(entityId, DICTIONARY_COUNTERS), name, null, timestamp);
		if ("o".equals(counterType) || "p".equals(counterType)) {
			HCounterColumn c = createCounterColumn(name, value);
			m.addCounter(bytebuffer(entityId), ENTITY_COUNTERS.toString(), c);
		}
		if ("n".equals(counterType) || "p".equals(counterType)) {
			PrefixedSerializer ps = new PrefixedSerializer(applicationId,
					UUIDSerializer.get(), UUIDSerializer.get());
			batcher.add(new Count(ENTITY_COUNTERS.toString(), ps
					.toByteBuffer(entityId), name, value));
		}
		return m;
	}


	public Mutator batchIncrementQueueCounter(
			Mutator m, UUID queueId, String name, long value,
			long timestamp, UUID applicationId) {
		if (logger.isDebugEnabled()) {
			logger.debug(
					"BIQC: Incrementing property {} of queue {} by value {}",
					new Object[] { name, queueId, value });
		}
		m.addInsertion(
				bytebuffer(key(queueId, DICTIONARY_COUNTERS).toString()),
				QueuesCF.QUEUE_DICTIONARIES.toString(),
				createColumn(name, ByteBuffer.allocate(0), timestamp, se, be));
		if ("o".equals(counterType) || "p".equals(counterType)) {
			HCounterColumn c = createCounterColumn(name, value);
			ByteBuffer keybytes = bytebuffer(queueId);
			m.addCounter(keybytes, QueuesCF.COUNTERS.toString(), c);
		}
		if ("n".equals(counterType) || "p".equals(counterType)) {
			PrefixedSerializer ps = new PrefixedSerializer(applicationId,
					UUIDSerializer.get(), UUIDSerializer.get());
			batcher.add(new Count(QueuesCF.COUNTERS.toString(), ps
					.toByteBuffer(queueId), name, value));
		}
		return m;
	}

	public Mutator batchIncrementQueueCounters(
			Mutator m, UUID queueId, Map values,
			long timestamp, UUID applicationId) {
		for (Entry entry : values.entrySet()) {
			batchIncrementQueueCounter(m, queueId, entry.getKey(),
					entry.getValue(), timestamp, applicationId);
		}
		return m;
	}

	public Mutator batchIncrementQueueCounters(
			Mutator m, Map> values,
			long timestamp, UUID applicationId) {
		for (Entry> entry : values.entrySet()) {
			batchIncrementQueueCounters(m, entry.getKey(), entry.getValue(),
					timestamp, applicationId);
		}
		return m;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy