All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.eg.agent.android.harvest.HarvestTimer Maven / Gradle / Ivy

There is a newer version: 2.1.3
Show newest version
package com.eg.agent.android.harvest;
/*
import com.newrelic.agent.android.background.ApplicationStateMonitor;
import com.newrelic.agent.android.logging.AgentLog;
import com.newrelic.agent.android.logging.AgentLogManager;
import com.newrelic.agent.android.stats.TicToc;
import com.newrelic.agent.android.util.NamedThreadFactory;*/

import com.eg.agent.android.background.ApplicationStateMonitor;
import com.eg.agent.android.logging.AgentLog;
import com.eg.agent.android.logging.AgentLogManager;
import com.eg.agent.android.util.NamedThreadFactory;
import com.eg.agent.android.util.TicToc;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class HarvestTimer implements Runnable {
    private static final long DEFAULT_HARVEST_PERIOD = 60000;
    private static final long HARVEST_PERIOD_LEEWAY = 1000;
    private static final long NEVER_TICKED = -1;
    protected final Harvester harvester;
    protected long lastTickTime;
    private Lock lock = new ReentrantLock();
    private final AgentLog log = AgentLogManager.getAgentLog();
    protected long period = DEFAULT_HARVEST_PERIOD;
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Harvester"));
    private long startTimeMs;
    private ScheduledFuture tickFuture = null;

    public HarvestTimer(Harvester harvester) {
        this.harvester = harvester;
        this.startTimeMs = 0;
    }

    public void run() {
        try {
            this.lock.lock();
            tickIfReady();
        } catch (Exception e) {
            this.log.error("HarvestTimer: Exception in timer tick: " + e.getMessage());
            e.printStackTrace();
            AgentHealth.noticeException(e);
        } finally {
            this.lock.unlock();
        }
    }

    private void tickIfReady() {
        long lastTickDelta = timeSinceLastTick();
        if (1000 + lastTickDelta >= this.period || lastTickDelta == -1) {
            this.log.debug("HarvestTimer: time since last tick: " + lastTickDelta);
            long tickStart = now();
            try {
                tick();
            } catch (Exception e) {
                this.log.error("HarvestTimer: Exception in timer tick: " + e.getMessage());
                e.printStackTrace();
                AgentHealth.noticeException(e);
            }
            this.lastTickTime = tickStart;
            this.log.debug("Set last tick time to: " + this.lastTickTime);
            return;
        }
        this.log.debug("HarvestTimer: Tick is too soon (" + lastTickDelta + " delta) Last tick time: " + this.lastTickTime + " . Skipping.");
    }

    protected void tick() {
        this.log.debug("Harvest: tick");
        TicToc t = new TicToc();
        t.tic();
        try {
            if (ApplicationStateMonitor.isAppInBackground()) {
                this.log.error("HarvestTimer: Attempting to harvest while app is in background");
            } else {
                this.harvester.execute();
                this.log.debug("Harvest: executed");
            }
        } catch (Exception e) {
            this.log.error("HarvestTimer: Exception in harvest execute: " + e.getMessage());
            e.printStackTrace();
            AgentHealth.noticeException(e);
        }
        if (this.harvester.isDisabled()) {
            stop();
        }
        this.log.debug("HarvestTimer tick took " + t.toc() + "ms");
    }

    public void start() {
        if (ApplicationStateMonitor.isAppInBackground()) {
            this.log.warning("HarvestTimer: Attempting to start while app is in background");
        } else if (isRunning()) {
            this.log.warning("HarvestTimer: Attempting to start while already running");
        } else if (this.period <= 0) {
            this.log.error("HarvestTimer: Refusing to start with a period of 0 ms");
        } else {
            this.log.debug("HarvestTimer: Starting with a period of " + this.period + "ms");
            this.startTimeMs = System.currentTimeMillis();
            this.tickFuture = this.scheduler.scheduleAtFixedRate(this, 0, this.period, TimeUnit.MILLISECONDS);
            this.harvester.start();
        }
    }

    public void stop() {
        if (isRunning()) {
            cancelPendingTasks();
            this.log.debug("HarvestTimer: Stopped.");
            this.startTimeMs = 0;
            this.harvester.stop();
            return;
        }
        this.log.warning("HarvestTimer: Attempting to stop when not running");
    }

    public void shutdown() {
        cancelPendingTasks();
        this.scheduler.shutdownNow();
    }

    public void tickNow() {
        final HarvestTimer timer = this;
        try {
            this.scheduler.schedule(new Runnable() {
                public void run() {
                    timer.tick();
                }
            }, 0, TimeUnit.SECONDS).get();
        } catch (Exception e) {
            this.log.error("Exception waiting for tickNow to finish: " + e.getMessage());
            e.printStackTrace();
            AgentHealth.noticeException(e);
        }
    }

    public boolean isRunning() {
        return this.tickFuture != null;
    }

    public void setPeriod(long period) {
        this.period = period;
    }

    public long timeSinceLastTick() {
        if (this.lastTickTime == 0) {
            return -1;
        }
        return now() - this.lastTickTime;
    }

    public long timeSinceStart() {
        if (this.startTimeMs == 0) {
            return 0;
        }
        return now() - this.startTimeMs;
    }

    private long now() {
        return System.currentTimeMillis();
    }

    protected void cancelPendingTasks() {
        try {
            this.lock.lock();
            if (this.tickFuture != null) {
                this.tickFuture.cancel(true);
                this.tickFuture = null;
            }
            this.lock.unlock();
        } catch (Throwable th) {
            this.lock.unlock();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy