001    /*
002     * Copyright (c) 2007-2015 Concurrent, Inc. All Rights Reserved.
003     *
004     * Project and contact information: http://www.cascading.org/
005     *
006     * This file is part of the Cascading project.
007     *
008     * Licensed under the Apache License, Version 2.0 (the "License");
009     * you may not use this file except in compliance with the License.
010     * You may obtain a copy of the License at
011     *
012     *     http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing, software
015     * distributed under the License is distributed on an "AS IS" BASIS,
016     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017     * See the License for the specific language governing permissions and
018     * limitations under the License.
019     */
020    
021    package cascading.stats.local;
022    
023    import java.util.Collection;
024    import java.util.Collections;
025    import java.util.HashMap;
026    import java.util.HashSet;
027    import java.util.LinkedHashSet;
028    import java.util.Map;
029    import java.util.Properties;
030    import java.util.Set;
031    
032    import cascading.flow.FlowStep;
033    import cascading.management.state.ClientState;
034    import cascading.stats.FlowStepStats;
035    
036    import static java.util.Collections.synchronizedMap;
037    import static java.util.Collections.unmodifiableCollection;
038    
039    /**
040     *
041     */
042    public class LocalStepStats extends FlowStepStats
043      {
044      final Map<String, Map<String, Long>> counters = synchronizedMap( new HashMap<String, Map<String, Long>>() );
045    
046      /** Constructor CascadingStats creates a new CascadingStats instance. */
047      public LocalStepStats( FlowStep<Properties> flowStep, ClientState clientState )
048        {
049        super( flowStep, clientState );
050        }
051    
052      @Override
053      public void recordChildStats()
054        {
055        }
056    
057      @Override
058      public Collection<String> getCounterGroups()
059        {
060        synchronized( counters )
061          {
062          return unmodifiableCollection( new LinkedHashSet<String>( counters.keySet() ) );
063          }
064        }
065    
066      @Override
067      public Collection<String> getCounterGroupsMatching( String regex )
068        {
069        Collection<String> counterGroups = getCounterGroups();
070    
071        Set<String> results = new HashSet<String>();
072    
073        synchronized( counters )
074          {
075          for( String group : counterGroups )
076            {
077            if( group.matches( regex ) )
078              results.add( group );
079            }
080          }
081    
082        return unmodifiableCollection( results );
083        }
084    
085      @Override
086      public Collection<String> getCountersFor( String group )
087        {
088        Map<String, Long> groupCollection = counters.get( group );
089    
090        if( groupCollection == null )
091          return Collections.emptySet();
092    
093        synchronized( groupCollection )
094          {
095          return unmodifiableCollection( new LinkedHashSet<String>( groupCollection.keySet() ) );
096          }
097        }
098    
099      @Override
100      public long getCounterValue( Enum counter )
101        {
102        Map<String, Long> counterMap = counters.get( counter.getDeclaringClass().getName() );
103    
104        String counterString = counter.toString();
105    
106        // we don't remove counters, so safe
107        if( counterMap == null || !counterMap.containsKey( counterString ) )
108          return 0;
109    
110        return counterMap.get( counterString );
111        }
112    
113      @Override
114      public long getCounterValue( String group, String counter )
115        {
116        Map<String, Long> counterMap = counters.get( group );
117    
118        // we don't remove counters, so safe
119        if( counterMap == null || !counterMap.containsKey( counter ) )
120          return 0;
121    
122        return counterMap.get( counter );
123        }
124    
125      public void increment( Enum counter, long amount )
126        {
127        increment( counter.getDeclaringClass().getName(), counter.toString(), amount );
128        }
129    
130      public void increment( String group, String counter, long amount )
131        {
132        Map<String, Long> groupMap = getCreateCounter( group );
133    
134        synchronized( groupMap )
135          {
136          Long value = groupMap.get( counter );
137    
138          if( value == null )
139            value = 0L;
140    
141          groupMap.put( counter, value + amount );
142          }
143        }
144    
145      private Map<String, Long> getCreateCounter( String group )
146        {
147        synchronized( counters )
148          {
149          Map<String, Long> counterMap = counters.get( group );
150    
151          if( counterMap == null )
152            {
153            counterMap = synchronizedMap( new HashMap<String, Long>() );
154            counters.put( group, counterMap );
155            }
156    
157          return counterMap;
158          }
159        }
160    
161      @Override
162      public void captureDetail()
163        {
164        }
165    
166      @Override
167      public Collection getChildren()
168        {
169        return Collections.emptyList();
170        }
171      }