Package org.apache.sirona.store.tracking

Source Code of org.apache.sirona.store.tracking.InMemoryPathTrackingDataStore$Pointer

/*
* 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.sirona.store.tracking;

import org.apache.sirona.tracking.PathCallInformation;
import org.apache.sirona.tracking.PathTrackingEntry;
import org.apache.sirona.tracking.PathTrackingEntryComparator;
import org.apache.sirona.util.SerializeUtils;
import org.apache.sirona.util.UnsafeUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
* Very simple in memory storage for Path tracking feature
* <b>MUST NOT be used in production</b>
*/
public class InMemoryPathTrackingDataStore
    implements PathTrackingDataStore, CollectorPathTrackingDataStore
{


    /**
     * store path track tracking entries list per path tracking id
     * the value is the memory address
     */
    private ConcurrentMap<String, List<Pointer>> pathTrackingEntries =
        new ConcurrentHashMap<String, List<Pointer>>( 50 );

    @Override
    public void store( PathTrackingEntry pathTrackingEntry )
    {
        store( Collections.singletonList( pathTrackingEntry ) );
    }

    @Override
    public void store( Collection<PathTrackingEntry> pathTrackingEntries )
    {
        if ( pathTrackingEntries == null )
        {
            return;
        }

        // possible different trackingId so get that
        Map<String, Set<PathTrackingEntry>> entries = new HashMap<String, Set<PathTrackingEntry>>();

        for ( PathTrackingEntry pathTrackingEntry : pathTrackingEntries )
        {
            Set<PathTrackingEntry> entriesList = entries.get( pathTrackingEntry.getTrackingId() );
            if ( entriesList == null )
            {
                entriesList = new HashSet<PathTrackingEntry>();
            }
            entriesList.add( pathTrackingEntry );
            entries.put( pathTrackingEntry.getTrackingId(), entriesList );
        }

        for ( Map.Entry<String, Set<PathTrackingEntry>> entry : entries.entrySet() )
        {
            List<Pointer> entriesList = this.pathTrackingEntries.get( entry.getKey() );

            if ( entriesList == null )
            {
                entriesList = new CopyOnWriteArrayList<Pointer>();
            }
            entriesList.addAll( serialize( entry.getValue() ) );
            this.pathTrackingEntries.put( entry.getKey(), entriesList );
        }

    }

    @Override
    public Collection<PathTrackingEntry> retrieve( String trackingId )
    {
        List<Pointer> buffers = this.pathTrackingEntries.get( trackingId );

        return deserialize( buffers );
    }

    @Override
    public Collection<PathCallInformation> retrieveTrackingIds( Date startTime, Date endTime )
    {
        Set<PathCallInformation> trackingIds = new TreeSet<PathCallInformation>( PathCallInformation.COMPARATOR );
        for ( List<Pointer> buffers : this.pathTrackingEntries.values() )
        {
            if ( pathTrackingEntries.isEmpty() )
            {
                continue;
            }

            PathTrackingEntry first =
                SerializeUtils.deserialize( readBytes( buffers.iterator().next() ), PathTrackingEntry.class );

            if ( first.getStartTime() / 1000000 > startTime.getTime() //
                && first.getStartTime() / 1000000 < endTime.getTime() )
            {
                trackingIds.add(
                    new PathCallInformation( first.getTrackingId(), new Date( startTime.getTime() / 1000000 ) ) );
            }
        }
        return trackingIds;
    }

    private Collection<PathTrackingEntry> deserialize( List<Pointer> buffers )
    {
        List<PathTrackingEntry> entries = new ArrayList<PathTrackingEntry>( buffers.size() );

        for ( Pointer pointer : buffers )
        {
            byte[] bytes = readBytes( pointer );

            PathTrackingEntry entry = SerializeUtils.deserialize( bytes, PathTrackingEntry.class );
            if ( entry != null )
            {
                entries.add( entry );
            }
        }

        return entries;
    }

    public byte[] readBytes( Pointer pointer )
    {
        byte[] bytes = new byte[pointer.size];
        int length = pointer.size;
        long offset = pointer.offheapPointer;
        for ( int pos = 0; pos < length; pos++ )
        {
            bytes[pos] = UnsafeUtils.getUnsafe().getByte( pos + offset );
        }
        return bytes;
    }

    public static class Pointer
    {
        int size;

        long offheapPointer;

        boolean free;

        public int getSize()
        {
            return size;
        }

        public long getOffheapPointer()
        {
            return offheapPointer;
        }

        public void freeMemory()
        {
            if ( !free )
            {
                UnsafeUtils.getUnsafe().freeMemory( offheapPointer );
                free = true;
            }
        }

        public boolean isFree()
        {
            return free;
        }
    }

    private List<Pointer> serialize( Collection<PathTrackingEntry> entries )
    {
        List<Pointer> buffers = new ArrayList<Pointer>( entries.size() );

        for ( PathTrackingEntry entry : entries )
        {
            byte[] bytes = SerializeUtils.serialize( entry );
            if ( bytes != null )
            {
                long offheapPointer = UnsafeUtils.getUnsafe().allocateMemory( bytes.length );
                Pointer pointer = new Pointer();
                pointer.offheapPointer = offheapPointer;
                pointer.size = bytes.length;
                for ( int i = 0, size = bytes.length; i < size; i++ )
                {
                    UnsafeUtils.getUnsafe().putByte( offheapPointer + i, bytes[i] );
                }
                buffers.add( pointer );

            }
        }

        return buffers;
    }

    @Override
    public void clearEntries()
    {
        List<String> entriesToRemove = new ArrayList<String>();
        for ( Map.Entry<String, List<Pointer>> entry : pathTrackingEntries.entrySet() )
        {
            boolean allFree = true;
            // clear entries to not wait gc
            for ( Pointer pointer : entry.getValue() )
            {
                if ( !pointer.isFree() )
                {
                    allFree = false;
                }
            }
            if ( allFree )
            {
                entriesToRemove.add( entry.getKey() );
            }
        }

        for ( String key : entriesToRemove )
        {
            pathTrackingEntries.remove( key );
        }

    }

    protected Map<String, Set<PathTrackingEntry>> getPathTrackingEntries()
    {

        Map<String, Set<PathTrackingEntry>> entries =
            new HashMap<String, Set<PathTrackingEntry>>( this.pathTrackingEntries.size() );

        for ( Map.Entry<String, List<Pointer>> entry : this.pathTrackingEntries.entrySet() )
        {
            Set<PathTrackingEntry> pathTrackingEntries =
                new TreeSet<PathTrackingEntry>( PathTrackingEntryComparator.INSTANCE );
            pathTrackingEntries.addAll( deserialize( entry.getValue() ) );
            entries.put( entry.getKey(), pathTrackingEntries );
        }

        return entries;
    }

    protected Map<String, List<Pointer>> getPointers()
    {
        return this.pathTrackingEntries;
    }


}
TOP

Related Classes of org.apache.sirona.store.tracking.InMemoryPathTrackingDataStore$Pointer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.