<commit_before>package me.ifelseif.apns2.impl;

import me.ifelseif.apns2.ApnsHttp2Client;
import me.ifelseif.apns2.ResponseListener;
import me.ifelseif.apns2.model.Notification;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.api.server.ServerSessionListener;
import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.PingFrame;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Created by linmingchang on 16/12/21.
 */
public class ApnsHttp2ClientImpl implements ApnsHttp2Client {
    private static final Logger log = LoggerFactory.getLogger(ApnsHttp2ClientImpl.class);
    private static final String APNS_HOST = "api.push.apple.com";
    private static final int APNS_PORT = 443;
    private final String URI_BASE = "https://" + APNS_PORT + ":" + APNS_PORT + "/3/device/";
    private HTTP2Client http2Client;
    private Session session;
    private long sendCount;
    private long createTime;
    private final Object lock = new Object();
    private final int connectTimeout;
    private final int pushTimeout;
    private final String topic;
    private static final int BACKOFF_MAX = 300000;
    private static final int BACKOFF_MIN = 3000;
    private final int pushRetryTimes;
    private final int apnsExpiration;
    private final int apnsPriority;
    private final SslContextFactory sslContextFactory;
    private volatile boolean pingFailed = false;
    private final String clientName;
    private final int heartbeatInterval;
    private Timer timer;

    public ApnsHttp2ClientImpl(String clientName, SslContextFactory sslContextFactory, int connectTimeout, int pushTimeout, String topic, int pushRetryTimes, int apnsExpiration, int apnsPriority, int heartbeatInterval) {
        this.clientName = clientName;
        this.connectTimeout = connectTimeout;
        this.pushTimeout = pushTimeout;
        this.topic = topic;
        this.pushRetryTimes = pushRetryTimes;
        this.apnsExpiration = apnsExpiration;
        this.apnsPriority = apnsPriority;
        this.sslContextFactory = sslContextFactory;
        this.heartbeatInterval = heartbeatInterval;
    }

    @Override
    public ApnsHttp2ClientImpl start() {
        if (http2Client == null) {
            connectRetry();
        } else {
            final int hours = 10;
            long sendCount = getSendCount();
            if (pingFailed) {
                log.warn("{} ping failed ,already send {} messages，will reconnect", clientName, sendCount);
                connectRetry();
            } else if (getSendCount() > 100000) {
                log.warn("{} already send {} messages，will reconnect", clientName, sendCount);
                connectRetry();
            } else if (System.currentTimeMillis() - getCreateTime() > 3600 * 1000 * hours) {
                log.warn("{} already keep alive {} hours and send {} messages，will reconnect", clientName, hours, sendCount);
                connectRetry();
            }
        }
        return this;
    }


    @Override
    public void stop() {
        try {
            if (http2Client != null) {
                http2Client.stop();
                http2Client = null;
            }
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
        } catch (Exception ex) {
            log.warn("{} stop error,host={}", clientName, APNS_HOST, ex);
        }
    }

    private void connectRetry() {
        int backoff = BACKOFF_MIN;
        while (true) {
            try {
                connect();
                break;
            } catch (Exception ex) {
                log.warn("{} connect apns error", clientName, ex);
                try {
                    Thread.sleep(backoff);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
                backoff = backoff > BACKOFF_MAX ? BACKOFF_MAX : backoff * 2;
            }
        }
        //start ping
        if (timer == null) {
            timer = new Timer(true);
        }
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                ping();
            }
        }, 1000, heartbeatInterval);<commit_msg>fix resource leak and URI_BASE<commit_after>package me.ifelseif.apns2.impl;

import me.ifelseif.apns2.ApnsHttp2Client;
import me.ifelseif.apns2.ResponseListener;
import me.ifelseif.apns2.model.Notification;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.api.server.ServerSessionListener;
import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.PingFrame;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Created by linmingchang on 16/12/21.
 */
public class ApnsHttp2ClientImpl implements ApnsHttp2Client {
    private static final Logger log = LoggerFactory.getLogger(ApnsHttp2ClientImpl.class);
    private static final String APNS_HOST = "api.push.apple.com";
    private static final int APNS_PORT = 443;
    private final String URI_BASE = "https://" + APNS_HOST + ":" + APNS_PORT + "/3/device/";
    private HTTP2Client http2Client;
    private Session session;
    private long sendCount;
    private long createTime;
    private final Object lock = new Object();
    private final int connectTimeout;
    private final int pushTimeout;
    private final String topic;
    private static final int BACKOFF_MAX = 300000;
    private static final int BACKOFF_MIN = 3000;
    private final int pushRetryTimes;
    private final int apnsExpiration;
    private final int apnsPriority;
    private final SslContextFactory sslContextFactory;
    private volatile boolean pingFailed = false;
    private final String clientName;
    private final int heartbeatInterval;
    private Timer timer;

    public ApnsHttp2ClientImpl(String clientName, SslContextFactory sslContextFactory, int connectTimeout, int pushTimeout, String topic, int pushRetryTimes, int apnsExpiration, int apnsPriority, int heartbeatInterval) {
        this.clientName = clientName;
        this.connectTimeout = connectTimeout;
        this.pushTimeout = pushTimeout;
        this.topic = topic;
        this.pushRetryTimes = pushRetryTimes;
        this.apnsExpiration = apnsExpiration;
        this.apnsPriority = apnsPriority;
        this.sslContextFactory = sslContextFactory;
        this.heartbeatInterval = heartbeatInterval;
    }

    @Override
    public ApnsHttp2ClientImpl start() {
        if (http2Client == null) {
            connectRetry();
        } else {
            final int hours = 10;
            long sendCount = getSendCount();
            if (pingFailed) {
                log.warn("{} ping failed ,already send {} messages，will reconnect", clientName, sendCount);
                connectRetry();
            } else if (getSendCount() > 100000) {
                log.warn("{} already send {} messages，will reconnect", clientName, sendCount);
                connectRetry();
            } else if (System.currentTimeMillis() - getCreateTime() > 3600 * 1000 * hours) {
                log.warn("{} already keep alive {} hours and send {} messages，will reconnect", clientName, hours, sendCount);
                connectRetry();
            }
        }
        return this;
    }


    @Override
    public void stop() {
        try {
            if (http2Client != null) {
                http2Client.stop();
                http2Client = null;
            }
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
        } catch (Exception ex) {
            log.warn("{} stop error,host={}", clientName, APNS_HOST, ex);
        }
    }

    private void connectRetry() {
        int backoff = BACKOFF_MIN;
        while (true) {
            try {
                connect();
                break;
            } catch (Exception ex) {
                log.warn("{} connect apns error", clientName, ex);
                try {
                    Thread.sleep(backoff);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
                stop();
                backoff = backoff > BACKOFF_MAX ? BACKOFF_MAX : backoff * 2;
            }
        }
        //start ping
        if (timer == null) {
            timer = new Timer(true);
        }
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                ping();
            }
        }, 1000, heartbeatInterval);
{'fraction_non_alphanumeric': 0.09417560127499276, 'fraction_numerical': 0.012943108277793876, 'mean_word_length': 2.4398671096345517, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, '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': '7319636', 'n_tokens_mistral': 2958, 'n_tokens_neox': 2830, 'n_words': 702}