/* * Copyright 2007 Zhang, Zheng <oldbig@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.util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import cn.edu.zju.acm.onlinejudge.bean.AbstractContest; import cn.edu.zju.acm.onlinejudge.bean.Problem; import cn.edu.zju.acm.onlinejudge.bean.Submission; import cn.edu.zju.acm.onlinejudge.bean.request.SubmissionCriteria; import cn.edu.zju.acm.onlinejudge.judgeservice.JudgeService; import cn.edu.zju.acm.onlinejudge.judgeservice.JudgingQueueIterator; import cn.edu.zju.acm.onlinejudge.persistence.PersistenceCreationException; import cn.edu.zju.acm.onlinejudge.persistence.PersistenceException; import cn.edu.zju.acm.onlinejudge.security.RoleSecurity; import cn.edu.zju.acm.onlinejudge.util.cache.Cache; public class StatisticsManager { private final Cache<ContestStatistics> contestStatisticsCache; private final Cache<ProblemStatistics> problemStatisticsCache; private final Cache<RankList> ranklistCache; private final Cache<ProblemsetRankList> problemsetRanklistCache; private final Cache<UserStatistics> solvedCache; private final Cache<SubmissionCacheEntry> submissionCache; /** * StatisticsManager. */ private static StatisticsManager instance = null; /** * <p> * Constructor of StatisticsManager class. * </p> * * @throws PersistenceCreationException * */ private StatisticsManager() throws PersistenceCreationException { // TODO this.contestStatisticsCache = new Cache<ContestStatistics>(20000, 20); this.problemStatisticsCache = new Cache<ProblemStatistics>(20000, 50); this.ranklistCache = new Cache<RankList>(10000, 20); this.problemsetRanklistCache = new Cache<ProblemsetRankList>(30000, 20); this.solvedCache = new Cache<UserStatistics>(10000, 50); this.submissionCache = new Cache<SubmissionCacheEntry>(10000, 50); } /** * Gets the singleton instance. * * @return the singleton instance. * @throws PersistenceCreationException */ public static StatisticsManager getInstance() throws PersistenceCreationException { if (StatisticsManager.instance == null) { synchronized (StatisticsManager.class) { if (StatisticsManager.instance == null) { StatisticsManager.instance = new StatisticsManager(); } } } return StatisticsManager.instance; } public ContestStatistics getContestStatistics(long contestId) throws PersistenceException { return this.getContestStatistics(contestId, 0, Integer.MAX_VALUE); } public ContestStatistics getContestStatistics(long contestId, int offset, int count) throws PersistenceException { List<Object> key = new ArrayList<Object>(); key.add(contestId); key.add(offset); key.add(count); synchronized (this.contestStatisticsCache) { ContestStatistics statistics = this.contestStatisticsCache.get(key); if (statistics == null) { List<Problem> problems = ContestManager.getInstance().getContestProblems(contestId, offset, count); statistics = PersistenceManager.getInstance().getSubmissionPersistence().getContestStatistics(problems); this.contestStatisticsCache.put(key, statistics); } return statistics; } } public ProblemStatistics getProblemStatistics(long problemId, String orderBy, int count) throws PersistenceCreationException, PersistenceException { List<Object> key = new ArrayList<Object>(); key.add(problemId); key.add(orderBy); key.add(count); synchronized (this.problemStatisticsCache) { ProblemStatistics statistics = this.problemStatisticsCache.get(key); if (statistics == null) { statistics = PersistenceManager.getInstance().getSubmissionPersistence() .getProblemStatistics(problemId, orderBy, count); this.problemStatisticsCache.put(key, statistics); } return statistics; } } public RankList getRankList(long contestId) throws PersistenceException { return this.getRankList(contestId, -1); } public ProblemsetRankList getProblemsetRankList(long contestId, int offset, int count, String sort) throws PersistenceException { List<Object> key = new ArrayList<Object>(); key.add(contestId); key.add(offset); key.add(count); key.add(sort); synchronized (this.problemsetRanklistCache) { ProblemsetRankList ranklist = this.problemsetRanklistCache.get(key); if (ranklist == null) { ranklist = PersistenceManager.getInstance().getSubmissionPersistence().getProblemsetRankList(contestId, offset, count, sort); this.problemsetRanklistCache.put(key, ranklist); } return ranklist; } } public RankList getRankList(long contestId, long roleId) throws PersistenceException { List<Long> key = new ArrayList<Long>(); key.add(contestId); key.add(roleId); synchronized (this.ranklistCache) { RankList ranklist = this.ranklistCache.get(key); if (ranklist == null) { ranklist = new RankList(); List<RoleSecurity> roles = PersistenceManager.getInstance().getAuthorizationPersistence().getContestRoles(contestId); ranklist.setRoles(roles); for (RoleSecurity role : roles) { if (role.getId() == roleId) { ranklist.setRole(role); break; } } if (roleId < 0 || ranklist.getRole() != null) { AbstractContest contest = ContestManager.getInstance().getContest(contestId); List<Problem> problems = ContestManager.getInstance().getContestProblems(contestId); List<RankListEntry> entries = PersistenceManager.getInstance().getSubmissionPersistence() .getRankList(problems, contest.getStartTime().getTime(), roleId); for (RankListEntry entry : entries) { entry.setUserProfile(UserManager.getInstance().getUserProfile(entry.getUserProfile().getId())); } ranklist.setEntries(entries); } this.ranklistCache.put(key, ranklist); } return ranklist; } } public UserStatistics getUserStatistics(long contestId, long userId) throws PersistenceException { ArrayList<Object> key = new ArrayList<Object>(); key.add(new Long(contestId)); key.add(new Long(userId)); synchronized (this.solvedCache) { UserStatistics ret = this.solvedCache.get(key); if (ret == null) { ret = PersistenceManager.getInstance().getSubmissionPersistence().getUserStatistics(contestId, userId); this.solvedCache.put(key, ret); } return ret; } } public List<Submission> getSubmissions(SubmissionCriteria criteria, long firstId, long lastId, int count) throws PersistenceException { List<Object> key = new ArrayList<Object>(); key.add(criteria); key.add(new Long(firstId)); key.add(new Long(lastId)); key.add(new Integer(count)); SubmissionCacheEntry entry; synchronized (this.submissionCache) { entry = this.submissionCache.get(key); if (entry == null) { JudgingQueueIterator iter = JudgeService.getInstance().getJudgingQueueIterator(); List<Submission> submissions = PersistenceManager.getInstance().getSubmissionPersistence().searchSubmissions(criteria, firstId, lastId, count); entry = new SubmissionCacheEntry(iter, submissions); this.submissionCache.put(key, entry); } } return entry.getSubmissions(); } public void refresh(long contestId) { Object key = new Long(contestId); synchronized (this.contestStatisticsCache) { this.contestStatisticsCache.remove(key); } synchronized (this.ranklistCache) { this.ranklistCache.remove(key); } } private static class SubmissionCacheEntry { private JudgingQueueIterator iter; private List<Submission> submissions; private Map<Long, Submission> submissionMap = new HashMap<Long, Submission>(); public SubmissionCacheEntry(JudgingQueueIterator iter, List<Submission> submissions) { this.iter = iter; this.submissions = submissions; } public List<Submission> getSubmissions() { for (;;) { Submission submission = this.iter.next(); if (submission == null) { break; } this.submissionMap.put(submission.getId(), submission); } for (int i = 0; i < this.submissions.size(); i++) { Submission submission = this.submissions.get(i); Submission t = this.submissionMap.get(submission.getId()); if (t != null) { submission.setTimeConsumption(t.getTimeConsumption()); submission.setMemoryConsumption(t.getMemoryConsumption()); submission.setJudgeComment(t.getJudgeComment()); submission.setJudgeReply(t.getJudgeReply()); } } return new ArrayList<Submission>(this.submissions); } } }