<commit_before>/**
 * Copyright © 2016 <NAME>
 *
 * 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 simpleratelimiter;

import simpleratelimiter.exception.EventLimitException;
import simpleratelimiter.exception.EventRegisteredException;
import simpleratelimiter.exception.NoEventRegisteredException;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 *
 * Thread safe non-persistent limiter for single JVM.
 *
 * Created by <NAME> on 13.12.2016.
 */
public class BasicLimiter implements Limiter {

    private static BasicLimiter instance = null;

    private Map<String,EventLogbook> eventLogbooks;
    private Map<String,AtomicLong> nextAllowedTimestamps;

    private BasicLimiter()
    {
        eventLogbooks = new ConcurrentHashMap<String, EventLogbook>();
        nextAllowedTimestamps = new ConcurrentHashMap<String, AtomicLong>();
    }

    private EventLogbook getEventLogbook(String eventKey)
    {
        return eventLogbooks.get(eventKey);
    }

    /**
     * Logs event or throws @{@link EventLimitException} if rate limit reached.
     * Throws @{@link NoEventRegisteredException} if there's is no event registered.
     *
     * @param eventKey
     * @throws EventLimitException
     * @throws NoEventRegisteredException
     */
    public void logEvent(String eventKey) throws EventLimitException, NoEventRegisteredException
    {
        long logTimestamp = System.currentTimeMillis();
        EventLogbook eventLogbook = getEventLogbook(eventKey);
        if (eventLogbook==null)
        {
            throw new NoEventRegisteredException("No event registered for event key " + eventKey);
        }
        AtomicLong nextAllowedTimestamp = nextAllowedTimestamps.get(eventKey);
        Thread thread = new Thread(()-> {
            eventLogbook.eventTimestamps.add(logTimestamp);
            long oldestTimestamp = logTimestamp - eventLogbook.milllisInterval;
            // Clean up old logs and find new nextAllowedTimestamp;
            Iterator<Long> logsIterator = eventLogbook.eventTimestamps.iterator();
            int count = 0;
            long oldestValid = logTimestamp;
            while (logsIterator.hasNext())
            {
                long currentTimestamp = logsIterator.next();
                if (currentTimestamp<oldestTimestamp)
                {
                    logsIterator.remove();
                }
                else
                {
                    if (oldestTimestamp>currentTimestamp)
                    {
                        oldestTimestamp = currentTimestamp;
                    }
                    count++;
                }
            }
            if (count>=eventLogbook.limit)
            {
                AtomicLong nextAllowedTimestampObj =  nextAllowedTimestamps.get(eventKey);
                if (nextAllowedTimestampObj==null)
                {
                    nextAllowedTimestamps.put(eventKey, new AtomicLong(oldestTimestamp + eventLogbook.milllisInterval));
                }
                else
                {
                    nextAllowedTimestampObj.set(oldestTimestamp + eventLogbook.milllisInterval);
                }
            }
            else
            {
                nextAllowedTimestamps.remove(eventKey);
            }
        });
        thread.start();

        if (nextAllowedTimestamp==null)
        {
            return;
        }
    }

    private boolean isEventRegistered(String eventKey)
    {
        return eventLogbooks.containsKey(eventKey);
    }
<commit_msg>limit reached check<commit_after>/**
 * Copyright © 2016 <NAME>
 *
 * 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 simpleratelimiter;

import simpleratelimiter.exception.EventLimitException;
import simpleratelimiter.exception.EventRegisteredException;
import simpleratelimiter.exception.NoEventRegisteredException;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 *
 * Thread safe non-persistent limiter for single JVM.
 *
 * Created by <NAME> on 13.12.2016.
 */
public class BasicLimiter implements Limiter {

    private static BasicLimiter instance = null;

    private Map<String,EventLogbook> eventLogbooks;
    private Map<String,AtomicLong> nextAllowedTimestamps;

    private BasicLimiter()
    {
        eventLogbooks = new ConcurrentHashMap<String, EventLogbook>();
        nextAllowedTimestamps = new ConcurrentHashMap<String, AtomicLong>();
    }

    private EventLogbook getEventLogbook(String eventKey)
    {
        return eventLogbooks.get(eventKey);
    }

    /**
     * Logs event or throws @{@link EventLimitException} if rate limit reached.
     * Throws @{@link NoEventRegisteredException} if there's is no event registered.
     *
     * @param eventKey
     * @throws EventLimitException
     * @throws NoEventRegisteredException
     */
    public void logEvent(String eventKey) throws EventLimitException, NoEventRegisteredException
    {
        long logTimestamp = System.currentTimeMillis();
        EventLogbook eventLogbook = getEventLogbook(eventKey);
        if (eventLogbook==null)
        {
            throw new NoEventRegisteredException("No event registered for event key " + eventKey);
        }
        AtomicLong nextAllowedTimestamp = nextAllowedTimestamps.get(eventKey);
        Thread thread = new Thread(()-> {
            eventLogbook.eventTimestamps.add(logTimestamp);
            long oldestTimestamp = logTimestamp - eventLogbook.milllisInterval;
            // Clean up old logs and find new nextAllowedTimestamp;
            Iterator<Long> logsIterator = eventLogbook.eventTimestamps.iterator();
            int count = 0;
            long oldestValid = logTimestamp;
            while (logsIterator.hasNext())
            {
                long currentTimestamp = logsIterator.next();
                if (currentTimestamp<oldestTimestamp)
                {
                    logsIterator.remove();
                }
                else
                {
                    if (oldestTimestamp>currentTimestamp)
                    {
                        oldestTimestamp = currentTimestamp;
                    }
                    count++;
                }
            }
            if (count>=eventLogbook.limit)
            {
                AtomicLong nextAllowedTimestampObj =  nextAllowedTimestamps.get(eventKey);
                if (nextAllowedTimestampObj==null)
                {
                    nextAllowedTimestamps.put(eventKey, new AtomicLong(oldestTimestamp + eventLogbook.milllisInterval));
                }
                else
                {
                    nextAllowedTimestampObj.set(oldestTimestamp + eventLogbook.milllisInterval);
                }
            }
            else
            {
                nextAllowedTimestamps.remove(eventKey);
            }
        });
        thread.start();

        if (nextAllowedTimestamp==null)
        {
            return;
        }
        else if (nextAllowedTimestamp.longValue()>logTimestamp)
        {
            throw new EventLimitException("Limit reached for event key " + eventKey + ". Next event allowed on " + nextAllowedTimestamp.longValue());
        }
    }

    private boolean isEventRegistered(String eventKey)
    {
        return eventLogbooks.containsKey(eventKey);
    }

{'fraction_non_alphanumeric': 0.07585394581861013, 'fraction_numerical': 0.004004711425206125, 'mean_word_length': 2.2408396946564886, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5399268', 'n_tokens_mistral': 2125, 'n_tokens_neox': 2078, 'n_words': 540}