Package cn.edu.zju.acm.onlinejudge.judgeservice

Source Code of cn.edu.zju.acm.onlinejudge.judgeservice.JudgeService

/*
* Copyright 2007 Xu, Chuan <xuchuan@gmail.com>
*
* This file is part of ZOJ.
*
* ZOJ is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either revision 3 of the License, or (at your option) any later revision.
*
* ZOJ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with ZOJ. if not, see
* <http://www.gnu.org/licenses/>.
*/

package cn.edu.zju.acm.onlinejudge.judgeservice;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import cn.edu.zju.acm.onlinejudge.bean.Submission;
import cn.edu.zju.acm.onlinejudge.bean.enumeration.JudgeReply;
import cn.edu.zju.acm.onlinejudge.judgeservice.submissionfilter.SubmissionFilter;
import cn.edu.zju.acm.onlinejudge.persistence.PersistenceException;
import cn.edu.zju.acm.onlinejudge.persistence.SubmissionPersistence;
import cn.edu.zju.acm.onlinejudge.util.ConfigManager;
import cn.edu.zju.acm.onlinejudge.util.PersistenceManager;

public class JudgeService extends Thread {
    private static JudgeService instance;

    static {
        try {
            JudgeService.instance =
                    new JudgeService(Integer.parseInt(ConfigManager.getValue("queue_port")),
                                     ConfigManager.getValues("client_ip"),
                                     Integer.parseInt(ConfigManager.getValue("client_max_job")));
            JudgeService.instance.start();
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private ServerSocket serverSocket;

    private List<JudgeClient> judgeClientList = new ArrayList<JudgeClient>();

    private Logger logger = Logger.getLogger(JudgeService.class);

    private JudgingQueue judgingQueue = new JudgingQueue();

    private SubmissionQueue submissionQueue = new SubmissionQueue();

    private SubmissionFilter submissionFilter = null;

    private Set<String> clientHostAddressSet = new HashSet<String>();

    private int defaultNumberOfJudgeThreads;

    private Set<Long> queuingSubmissionIdSet = new HashSet<Long>();

    private Thread rejudgeThread;

    public static JudgeService getInstance() {
        return JudgeService.instance;
    }

    private JudgeService(int port, String[] clientHostAddressList, int defaultNumberOfJudgeThreads) throws IOException {
        this.serverSocket = new ServerSocket(port);
        this.logger.info("Listening on port " + port);
        if (clientHostAddressList != null) {
            for (String clientHostAddress : clientHostAddressList) {
                this.clientHostAddressSet.add(clientHostAddress);
            }
        }
        this.defaultNumberOfJudgeThreads = defaultNumberOfJudgeThreads;
        this.rejudgeThread = new Thread() {
            public void run() {
                SubmissionPersistence submissionPersistence =
                        PersistenceManager.getInstance().getSubmissionPersistence();
                try {
                    long last = 0;
                    for (int i = 0;; ++i) {
                        List<Submission> submissions = submissionPersistence.getQueueingSubmissions(last - 1, 100);
                        if (submissions.size() == 0) {
                            break;
                        }
                        synchronized (JudgeService.this.queuingSubmissionIdSet) {
                            for (int j = submissions.size() - 1; j >= 0; --j) {
                                Submission submission = submissions.get(j);
                                JudgeService.this.queuingSubmissionIdSet.add(submission.getId());
                                if (i == 0) {
                                    JudgeService.instance.judge(submission, Priority.NORMAL);
                                } else {
                                    JudgeService.instance.judge(submission, Priority.LOW);
                                }
                            }
                            JudgeService.this.queuingSubmissionIdSet.wait();
                        }
                        last = submissions.get(0).getId();
                    }
                } catch (PersistenceException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                }
                JudgeService.this.rejudgeThread = null;
                JudgeService.this.queuingSubmissionIdSet = null;
            }
        };
        rejudgeThread.start();
    }

    @Override
    public void run() {
        while (!this.serverSocket.isClosed()) {
            try {
                Socket socket = this.serverSocket.accept();
                this.logger
                           .info("Connection from " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
                if (!socket.getInetAddress().isLoopbackAddress() &&
                    !this.clientHostAddressSet.contains(socket.getInetAddress().getHostAddress())) {
                    this.logger.info("Refused");
                    socket.close();
                    continue;
                }
                JudgeClient client = new JudgeClient(this, socket, this.defaultNumberOfJudgeThreads);
                client.start();
                synchronized (this.judgeClientList) {
                    this.judgeClientList.add(client);
                }
            } catch (IOException e) {
                this.logger.error(e);
            }
        }

    }

    public List<JudgeClient> getJudgeClientList() {
        synchronized (this.judgeClientList) {
            return new ArrayList<JudgeClient>(this.judgeClientList);
        }
    }

    public JudgingQueueIterator getJudgingQueueIterator() {
        return this.judgingQueue.iterator();
    }

    public SubmissionFilter getSubmissionFilter() {
        return this.submissionFilter;
    }

    public void judge(Submission submission, int priority) {
        submission.setJudgeReply(JudgeReply.QUEUING);
        this.submissionQueue.push(submission, priority);
    }

    void judgeStart(Submission submission) {
        this.judgingQueue.push(submission);
    }

    void judgeDone(Submission submission) {
        this.judgingQueue.remove(submission);
        if (this.queuingSubmissionIdSet != null) {
            try {
                synchronized (this.queuingSubmissionIdSet) {
                    this.queuingSubmissionIdSet.remove(submission.getId());
                    if (this.queuingSubmissionIdSet.size() == 0) {
                        this.queuingSubmissionIdSet.notify();
                    }
                }
            } catch (NullPointerException e) {
                // In case queuingSubmissionIdSet is null
            }
        }
    }

    public SubmissionQueue getSubmissionQueue() {
        return this.submissionQueue;
    }

    @Override
    public void interrupt() {
        super.interrupt();
        synchronized (this.judgeClientList) {
            for (JudgeClient client : this.judgeClientList) {
                client.interrupt();
            }
        }
        try {
            this.rejudgeThread.interrupt();
        } catch (NullPointerException e) {
            // In case rejudgeThread is null
        }
    }
}
TOP

Related Classes of cn.edu.zju.acm.onlinejudge.judgeservice.JudgeService

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.