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 }