Package net.windwards.dnsfrontend.frontend

Source Code of net.windwards.dnsfrontend.frontend.TaskKeeperImpl

package net.windwards.dnsfrontend.frontend;

import net.sf.ehcache.CacheException;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.windwards.dnsfrontend.api.AbstractTaskKeeper;
import net.windwards.dnsfrontend.api.Backend;
import net.windwards.dnsfrontend.api.BackendRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xbill.DNS.DClass;
import org.xbill.DNS.Name;
import org.xbill.DNS.Record;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
import org.xbill.DNS.UNKRecord;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class TaskKeeperImpl extends AbstractTaskKeeper {
    private Logger logger = LoggerFactory.getLogger(TaskKeeperImpl.class);

    protected ScheduledThreadPoolExecutor pool;
    protected Ehcache cache;
    protected Map<String, FuturePackage> futures;

    protected static class FuturePackage {
        public ResolveTask task;
        public ScheduledFuture future;

        public FuturePackage(ResolveTask task, ScheduledFuture future) {
            this.task = task;
            this.future = future;
        }
    }

    public static final Record Unknown = null;
    static {
        try {
            Record.newRecord(new Name("."), Type.ANY, DClass.IN);
        } catch (TextParseException ignore) {

        }
    }

    public TaskKeeperImpl(Ehcache cache) {
        this.futures = new ConcurrentHashMap<String, FuturePackage>(100);
        this.cache = cache;
    }

    @Override
    public void start() {
        this.pool = new ScheduledThreadPoolExecutor(10);
        this.cache.getCacheEventNotificationService().registerListener(this);
    }

    @Override
    public void stop() {
        this.pool.shutdown();
    }

    @Override
    public void keep(final ResolveTask task) {
        Runnable timeout = new Runnable() {
            @Override
            public void run() {
                Element lmnt = new Element(task.getIdent(), Unknown);
                lmnt.setTimeToLive(negativeExpiry);
                cache.put(lmnt);
            }
        };

        ScheduledFuture future = this.pool.schedule(
                timeout, this.expireTime, TimeUnit.MILLISECONDS);

        String ident = task.getIdent();
        this.futures.put(ident, new FuturePackage(task, future));
    }

    @Override
    public void replyArrived(Ehcache cache, Element lmnt) throws CacheException {
        logger.debug("Cache update received [lmnt={}]", lmnt);
        Record record = (Record) lmnt.getObjectValue();
        FuturePackage pack;
        if(record == Unknown) {
            pack = this.futures.remove(lmnt.getObjectKey());
            pack.task.timeout();
            return;
        }

        Backend backend = this.repo.lookup(record.getType());
        String key = backend.makeKey(record);
        pack = this.futures.remove(key);

        if (pack == null) {
            logger.info("Unsolicited cache insert [key={}, record={}]", key, record);
            return;
        }

        if (pack.future.cancel(false)) {
            pack.task.answer(record, false);
        else {
            // Obscure race
            logger.warn("Race with timeout [name={}]", pack.task.getIdent());
        }
    }

    @Override
    public void discard(ResolveTask task) {
        this.futures.remove(task.getIdent());
    }
}
TOP

Related Classes of net.windwards.dnsfrontend.frontend.TaskKeeperImpl

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.