Package services

Source Code of services.ReceptionUpdater$PageHolder

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package services;

import services.utils.TicketConvertor;
import domain.Collaborator;
import domain.shedule.WorkType;
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.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;
import utils.SimplePair;
import web.rechelper.Ticket;

/**
*
* @author petr
*/
public class ReceptionUpdater {

    /**
     * Класс хранящий обновления для странички с заданным уидом
     */
    class PageHolder {

        private int pageUID;
        private Date lastUpdate;
        private ArrayList<TicketConvertor> tickets;

        public PageHolder() {
            pageUID = ((int) (Math.random() * Integer.MAX_VALUE));
            lastUpdate = new Date();
            tickets = new ArrayList<TicketConvertor>();
        }

        public TicketConvertor[] getTickets() {
            TicketConvertor[] res = tickets.toArray(new TicketConvertor[tickets.size()]);
            tickets.clear();
            lastUpdate = new Date();
            return res;
        }

        public void addTicket(Ticket ticket) {
            tickets.add(new TicketConvertor(ticket));
        }

        public boolean check() {
            boolean c = new Date().getTime() - lastUpdate.getTime() < timeout;
            if (!c) {
                log.debug("check in: " + getPageUID() + " = " + c);
            }
            return c;
        }

        public int getPageUID() {
            return pageUID;
        }
    }
    protected static final Logger log = Logger.getLogger(ReceptionUpdater.class);
    /**сколько мс страничка не должна посылать запросов, что б отвалиться*/
    private static long timeout = 20000l;
    /**таймер, рубит странички по таймауту*/
    private Timer t;
    /**замок для синхронизации*/
    private final Lock lock = new ReentrantLock();
    /**
     * мап (сотрудник, тип работы) - список уидов страничек
     */
    private static Map<Integer, PageHolder> holderMap = new HashMap<Integer, PageHolder>();
    /**
     * мап пара айдишнегов (коллаборатор, тип работы) - список уидов страничек
     */
    private static Map<SimplePair, List<Integer>> ticketMap = new HashMap<SimplePair, List<Integer>>();
    private int id;

    /**
     * Конструктор, инициализирует таймер
     */
    public ReceptionUpdater() {
        id = ((int) (Math.random() * Integer.MAX_VALUE));
        t = new Timer();
        t.schedule(new TimerTask() {//

            @Override
            public void run() {
                clearHolder();
            }
        }, timeout, timeout);
    }

    ///////////////// торчат наружу /////////////////////////////////
    /**
     * Генерит странице уид, по которому она потом буде обновлятьси
     * запоминает его
     * @param collaborator
     * @param workType
     * @return
     */
    public int registerPage(Collaborator collaborator, WorkType workType) {
        PageHolder pageHolder = new PageHolder();
        holderMap.put(pageHolder.getPageUID(), pageHolder);
        findInTicketMap(collaborator, workType).add(pageHolder.pageUID);
        log.debug("createPageUID for: " + collaborator + ", " + workType + " = " + pageHolder.getPageUID());
        return pageHolder.getPageUID();
    }

    /**
     * Сию функцию вопрошает страничка через двр, на предмет обновлений
     * @param uids идентификатор страницы
     * @return список обновлений
     */
    public TicketConvertor[] getUpdatesP(int uid) {
        return getUpdates(uid);
    }

    /**
     * добавляет тикет
     * @param collaborator
     * @param workType
     * @param ticket
     */
    public void addTicketP(Collaborator collaborator, WorkType workType, Ticket ticket) {
        addTicket(collaborator, workType, ticket);
    }

    //////////////// дёргаются харатерными функциями, к-ые торчат наружу //////////////

    /**
     * Вызывает отцепление страниц по таймауту
     */
    private void clearHolder() {
        clearHolders();

    }

    /**
     * добавляет тикет
     * @param collaborator
     * @param workType
     * @param ticket
     */
    private void addTicket(Collaborator collaborator, WorkType workType, Ticket ticket) {
        lock.lock();
        try {
            log.debug("addTicket in " + Thread.currentThread().toString());
            List<Integer> uids = findInTicketMap(collaborator, workType);
            log.debug("Найдены страницы: " + uids);
            for (int i = uids.size() - 1; i >= 0; i--) {
                Integer uid = uids.get(i);
                PageHolder holder = holderMap.get(uid);
                if (holder == null/*|| !holder.check()*/) {
//                getHolderMap().remove(uid);
//                removeFromTicketMap(uid);
                    log.debug("Страница c uid" + uid + " не зарегестрирована");
                } else {
                    log.debug("Билет добавлен странице с uid " + uid);
                    holder.addTicket(ticket);
                }
            }
        } finally {
            lock.unlock();
        }
    }

    /**
     * возвращает обновления для запрошеной страницы
     * @param uid уид страницы
     * @return
     */
    private TicketConvertor[] getUpdates(int uid) {
        lock.lock();
        try {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            PageHolder holder = holderMap.get(uid);
            if (holder == null) {
                log.debug("holder == null uid: " + uid);
                return null;
            } else {
                if (!holder.check()) {
                    log.debug("!holder.check id: " + holder.getPageUID());
                    return null;
                } else {
                    TicketConvertor[] tickets = holder.getTickets();
                    if (tickets.length > 0) {
                        log.debug("getUpdates in " + Thread.currentThread().toString());
                        log.debug("getBusyTikets for " + uid + " return: " + tickets.length + " elements");
                    }
                    return tickets;
                }
            }
        } finally {
            lock.unlock();
        }
    }

    /**
     * чистит отвалившиеся страницы
     */
    private void clearHolders() {
        lock.lock();
        try {
            Set<Integer> toRemove = new HashSet<Integer>();
            Map<Integer, PageHolder> holderMapLocal = holderMap;
            if (holderMapLocal != null && holderMapLocal.keySet() != null) {
                Set<Integer> keys = Collections.synchronizedSet(holderMapLocal.keySet());
                Vector<Integer> uids = new Vector<Integer>(keys);
                for (int i = uids.size() - 1; i >= 0; i--) {
//                for (Integer uid : holderMapLocal.keySet()) {
                    Integer uid = uids.elementAt(i);
                    if (!holderMapLocal.get(uid).check()) {
                        holderMapLocal.remove(uid);
                        toRemove.add(uid);
                    }
                }
                if (!toRemove.isEmpty()) {
                    removeFromTicketMap(toRemove);
                    log.debug("clearHolders in " + Thread.currentThread().toString());
                    log.debug("clearHolders: remove " + toRemove);
                }
            }
        } finally {
            lock.unlock();
        }
    }

    /////////////////////// сервисные /////////////////////////////////////
    /**
     * Сервисная, удаляет по ид списком страницы из мапа
     * @param uids
     */
    private void removeFromTicketMap(Set<Integer> uids) {
//        threadControl("removeFromTicketMap");
        log.debug("removeFromTicketMap: " + uids);
        Collection<List<Integer>> values = ticketMap.values();
        for (List<Integer> list : values) {
            if (list != null) {
                list.removeAll(uids);
            }
        }
    }

    /**
     * сервисная, ищет список уидов страницек в мапе по сотруднику и типу работы
     * @param collaborator
     * @param workType
     * @return
     */
    private List<Integer> findInTicketMap(Collaborator collaborator, WorkType workType) {
        log.debug("findInTicketMap: " + collaborator + ", " + workType);

        SimplePair findPair = new SimplePair(collaborator.getId(), workType.getId());
        List<Integer> list = ticketMap.get(findPair);
        if (list == null) {
            list = new Vector<Integer>();
            ticketMap.put(findPair, list);
        }
        log.debug("findInTicketMap return " + list);
        return list;
    }
}
TOP

Related Classes of services.ReceptionUpdater$PageHolder

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.