Mercurial Hosting > nabble
comparison src/nabble/view/web/user/OnlineStatus.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children | 18cf4872fd7f |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7ecd1a4ef557 |
---|---|
1 package nabble.view.web.user; | |
2 | |
3 import fschmidt.util.servlet.ServletUtils; | |
4 import nabble.model.Executors; | |
5 import nabble.model.ModelHome; | |
6 import nabble.model.Person; | |
7 import nabble.model.Site; | |
8 import nabble.model.User; | |
9 import nabble.view.lib.Jtp; | |
10 import org.slf4j.Logger; | |
11 import org.slf4j.LoggerFactory; | |
12 | |
13 import javax.servlet.http.HttpServletRequest; | |
14 import java.util.ArrayList; | |
15 import java.util.Collection; | |
16 import java.util.HashMap; | |
17 import java.util.Iterator; | |
18 import java.util.List; | |
19 import java.util.Map; | |
20 import java.util.Set; | |
21 import java.util.concurrent.TimeUnit; | |
22 | |
23 public class OnlineStatus { | |
24 | |
25 private static final Logger logger = LoggerFactory.getLogger(OnlineStatus.class); | |
26 | |
27 private static final long TIMEOUT = 3 * 60 * 1000L; // 3 minutes | |
28 private static final String INVISIBLE = "invisible:"; | |
29 | |
30 /** Maps a site ID to a map (Person-Source-ID > last time) */ | |
31 private static final Map<Long, Map<String, Long>> sitesMap = new HashMap<Long, Map<String, Long>>(); | |
32 | |
33 public static void setOnline(HttpServletRequest request, Person visitor, Site site) { | |
34 setOnline(request,visitor.getSearchId(),site); | |
35 } | |
36 | |
37 private static void setOnline(HttpServletRequest request, String sourceId, Site site) { | |
38 synchronized(sitesMap) { | |
39 Map<String, Long> map = sitesMap.get(site.getId()); | |
40 if (map == null) { | |
41 map = new HashMap<String, Long>(); | |
42 sitesMap.put(site.getId(), map); | |
43 logger.debug("New map for site ID = " + site.getId()); | |
44 } | |
45 boolean isVisible = ServletUtils.getCookieValue(request, "visible") == null || !Jtp.isInteger(sourceId); | |
46 map.put(isVisible? sourceId : INVISIBLE+sourceId, System.currentTimeMillis()); | |
47 } | |
48 } | |
49 | |
50 public static boolean isOnline(Person visitor, Site site) { | |
51 return isOnline(visitor.getSearchId(),site); | |
52 } | |
53 | |
54 public static boolean isOnline(String sourceId, Site site) { | |
55 synchronized(sitesMap) { | |
56 Map<String, Long> map = sitesMap.get(site.getId()); | |
57 return map != null && map.get(sourceId) != null; | |
58 } | |
59 } | |
60 | |
61 private static void runGC() { | |
62 final long start = System.currentTimeMillis(); | |
63 synchronized(sitesMap) { | |
64 for( Iterator<Map<String, Long>> iter = sitesMap.values().iterator(); iter.hasNext(); ) { | |
65 Map<String, Long> map = iter.next(); | |
66 for( Iterator<Long> subIter = map.values().iterator(); subIter.hasNext(); ) { | |
67 long time = subIter.next(); | |
68 if (start - time > TIMEOUT) { | |
69 subIter.remove(); | |
70 logger.debug("Removed user"); | |
71 } | |
72 } | |
73 if( map.isEmpty() ) { | |
74 iter.remove(); | |
75 logger.debug("Removed map"); | |
76 } | |
77 } | |
78 } | |
79 logger.info("OnlineStatus GC took " + (System.currentTimeMillis()-start) + " ms"); | |
80 } | |
81 | |
82 public static String getOnlineStats() { | |
83 int count = 0; | |
84 int sites; | |
85 float ratio = 0f; | |
86 synchronized(sitesMap) { | |
87 Collection<Map<String, Long>> entries = sitesMap.values(); | |
88 for (Map<String, Long> entry : entries) { | |
89 count += entry.keySet().size(); | |
90 } | |
91 sites = sitesMap.size(); | |
92 if (sites > 0) | |
93 ratio = count / (float) sitesMap.size(); | |
94 } | |
95 return "Users = " + count + " | Sites = " + sites + " | Ratio = " + String.format("%.2f", ratio); | |
96 } | |
97 | |
98 public static Map<String, Integer> getOnlineSites() { | |
99 Map<String, Integer> sites = new HashMap<String, Integer>(); | |
100 | |
101 synchronized(sitesMap) { | |
102 for (Map.Entry<Long, Map<String, Long>> entry : sitesMap.entrySet()) { | |
103 String url = ModelHome.getSite(entry.getKey()).getBaseUrl(); | |
104 sites.put(url, entry.getValue().size()); | |
105 } | |
106 } | |
107 return sites; | |
108 } | |
109 | |
110 public static List<User> getOnlineUsers(Site site, boolean includeInvisibleUsers) { | |
111 String[] visitorIDs = getVisitorIds(site); | |
112 List<User> users = new ArrayList<User>(); | |
113 for (String id : visitorIDs) { | |
114 long userId = 0; | |
115 if (Jtp.isInteger(id)) { | |
116 userId = Long.valueOf(id); | |
117 } else if (includeInvisibleUsers && isInvisible(id)) { | |
118 userId = Long.valueOf(id.substring(INVISIBLE.length())); | |
119 } | |
120 if (userId > 0) { | |
121 User u = site.getUser(userId); | |
122 if (u != null) | |
123 users.add(u); | |
124 } | |
125 } | |
126 return users; | |
127 } | |
128 | |
129 public static int getOnlineAnonymousUsersCount(Site site) { | |
130 String[] visitorIDs = getVisitorIds(site); | |
131 int c = 0; | |
132 for (String id : visitorIDs) | |
133 if (!Jtp.isInteger(id) && !isInvisible(id)) { | |
134 c++; | |
135 } | |
136 return c; | |
137 } | |
138 | |
139 public static int getOnlineInvisibleUsersCount(Site site) { | |
140 String[] visitorIDs = getVisitorIds(site); | |
141 int c = 0; | |
142 for (String id : visitorIDs) { | |
143 if (isInvisible(id)) | |
144 c++; | |
145 } | |
146 return c; | |
147 } | |
148 | |
149 private static String[] getVisitorIds(Site site) { | |
150 synchronized(sitesMap) { | |
151 Map<String, Long> map = sitesMap.get(site.getId()); | |
152 if (map == null) | |
153 return new String[0]; | |
154 Set<String> set = map.keySet(); | |
155 String[] visitorIds = new String[set.size()]; | |
156 set.toArray(visitorIds); | |
157 return visitorIds; | |
158 } | |
159 } | |
160 | |
161 private static boolean isInvisible(String id) { | |
162 return id.startsWith(INVISIBLE); | |
163 } | |
164 | |
165 static { | |
166 Executors.scheduleWithFixedDelay(new Runnable(){ | |
167 public void run(){ | |
168 runGC(); | |
169 } | |
170 }, 2*60, 2*60, TimeUnit.SECONDS); // Every 2 minutes | |
171 } | |
172 | |
173 } |