/* * 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.count; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.usergrid.count.common.Count; import me.prettyprint.cassandra.model.HCounterColumnImpl; import me.prettyprint.hector.api.Keyspace; import me.prettyprint.hector.api.factory.HFactory; import me.prettyprint.hector.api.mutation.Mutator; import static org.apache.usergrid.persistence.cassandra.Serializers.*; /** * Encapsulate counter writes to Cassandra * * @author zznate */ public class CassandraCounterStore implements CounterStore { private static final Logger logger = 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, be ); 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) { logger.error( "CounterStore insert failed, first instance", e); counterInsertFailures.put( error, 1); } else { int count = counterInsertFailures.get(error) + 1; counterInsertFailures.put(error, count); logger.error("{} caused CounterStore insert failure, count = {}", error, count, e); } } } }