Mercurial > hg > RemoteEditor > REPSessionManager
annotate rep/Session.java @ 485:cc262a519b8a
add dead lock detection (don't forget remove )
author | one |
---|---|
date | Wed, 20 Oct 2010 22:59:19 +0900 |
parents | 7420dea70dd7 |
children |
rev | line source |
---|---|
0 | 1 package rep; |
2 | |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
3 import java.util.Collection; |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
4 import java.util.HashMap; |
1 | 5 import java.util.LinkedList; |
131 | 6 import rep.channel.REPSocketChannel; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
7 import rep.handler.Editor; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
8 import rep.handler.REPNode; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
9 import rep.handler.Forwarder; |
131 | 10 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
11 public class Session extends HashMap<Integer,REPNode> { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
12 /** |
411 | 13 * Editor Session |
14 * contains interacting editors | |
15 * accessed by eid. There is one masterEditor which | |
16 * has a file name (is a sessionName). | |
17 * | |
18 * maintain connection among handlers (Dispatcher, | |
19 * Forwarder, Editor). | |
20 * first->editor->editor...->last | |
21 * first may equal to the last. When a session is | |
22 * created, first equals the last. | |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
23 */ |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
24 private static final long serialVersionUID = 1L; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
25 private REPNode masterEditor; |
1 | 26 private int sessionID; |
27 private String sessionName; | |
411 | 28 // isOnwer means this session is owner of an active channels(forwarders). |
67 | 29 private boolean isOwner = false; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
30 private REPNode first; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
31 private REPNode last; |
9 | 32 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
33 public Session(int sid, String name, REPNode editor) { |
227 | 34 this(sid, editor); |
35 sessionName = name; | |
1 | 36 } |
320 | 37 |
39 | 38 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
39 public Session(int sid, REPNode master) { |
144 | 40 sessionID = sid; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
41 if (master!=null) { |
320 | 42 // we have a master |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
43 masterEditor = last = master; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
44 master.setSID(sid); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
45 put(master.eid,master); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
46 if(master.channel!=null) { |
411 | 47 // master is a real connected editor |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
48 first = master; |
323 | 49 masterEditor.setNext(masterEditor); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
50 isOwner = true; |
323 | 51 } |
320 | 52 } |
1 | 53 } |
319 | 54 |
372 | 55 /* |
56 * どこにlocal editorを入れても良いのだが、まとめた方が良いか? | |
57 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
58 public void addForwarder(REPNode editor) { |
320 | 59 // add a forwarder and connect this to the session |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
60 editor.setSID(sessionID); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
61 editor.setNext(last.getNextForwarder()); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
62 last.setNext(editor); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
63 last = editor; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
64 put(editor.eid,editor); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
65 isOwner = true; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
66 if(first==null) first = editor; |
373 | 67 |
376 | 68 // printSessionDetail(); |
319 | 69 } |
70 | |
320 | 71 public void addEditor(Editor editor) { |
72 // add a not-connected editor in a sassion | |
411 | 73 // the editor is in the outside of this manager |
362 | 74 editor.setSID(sessionID); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
75 put(editor.eid,editor); |
320 | 76 } |
77 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
78 public Collection<REPNode> getEditorList() { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
79 return values(); |
1 | 80 } |
319 | 81 |
56 | 82 public int getSID() { |
83 return sessionID; | |
38 | 84 } |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
85 public REPNode getOwner() { |
38 | 86 return masterEditor; |
87 } | |
88 public String getName() { | |
89 return sessionName; | |
90 } | |
319 | 91 |
411 | 92 /* |
93 * Remove and disconnect a forwarder from the session | |
94 */ | |
274 | 95 public boolean deleteEditor(REPSocketChannel<REPCommand> channel) { |
411 | 96 // this is fanatic, one channel may have multiple sessions, but |
97 // a session should have only one channel that is one editor. | |
98 // REPNode e = getEditor(channel); | |
99 // if (e!=null) { unconnect((Forwarder)e); remove(e); } is Ok. | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
100 LinkedList<REPNode> toBeRemoved = new LinkedList<REPNode>(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
101 for (REPNode e:values() ) { |
275 | 102 if (e.getChannel()==channel) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
103 unconnect((Forwarder)e); |
411 | 104 // we cannot directly remove this because of the concurrent access |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
105 toBeRemoved.add(e); |
274 | 106 } |
107 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
108 for(REPNode e:toBeRemoved) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
109 remove(e); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
110 } |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
111 return !toBeRemoved.isEmpty(); |
274 | 112 } |
113 | |
358 | 114 public boolean deleteForwarder(Forwarder editor) { |
115 unconnect(editor); | |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
116 return remove(editor)!=null; |
358 | 117 } |
118 | |
411 | 119 /* |
120 * Clear connection of a forwarder. The rest of the forwarders in this | |
121 * session have to be connected properly. | |
122 */ | |
319 | 123 private void unconnect(Forwarder e) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
124 boolean hasOwner = false; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
125 for(REPNode e1:values()) { |
319 | 126 Forwarder f = (Forwarder)e1; |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
127 if(f.next==e) { |
319 | 128 f.next=e.next; |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
129 } else { |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
130 if (f.channel!=null) hasOwner=true; |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
131 } |
319 | 132 } |
376 | 133 if(first==e) first=null; |
319 | 134 if(masterEditor==e) masterEditor=null; |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
135 isOwner = hasOwner; |
319 | 136 } |
137 | |
227 | 138 public void setSID(int sid) { |
139 sessionID = sid; | |
56 | 140 } |
274 | 141 |
158 | 142 public boolean hasOwner() { |
67 | 143 return isOwner; |
144 } | |
319 | 145 |
146 | |
144 | 147 public Editor getEditor(REPSocketChannel<REPCommand> channel) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
148 for(REPNode editor : values()){ |
319 | 149 if(editor.getChannel() == channel) { |
150 return (Editor)editor; | |
151 } | |
144 | 152 } |
153 return null; | |
154 } | |
315 | 155 |
156 | |
319 | 157 |
411 | 158 /** |
159 * Start closing protocol | |
160 * not yet implemented. Use quit instead. | |
161 */ | |
259 | 162 public void closeSession() { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
163 REPNode f = first; |
394 | 164 if (f!=null) { |
165 REPCommand command = new REPCommand(REP.REPCMD_CLOSE, sessionID, REP.SM_EID.id, 0, 0, ""); | |
376 | 166 f.send(command); |
394 | 167 } |
300 | 168 } |
316 | 169 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
170 public REPNode getForwarder(REPSocketChannel<REPCommand> channel) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
171 REPNode f = first; |
373 | 172 while(f.channel!=channel) f = f.next; |
384 | 173 ServerMainLoop.logger.writeLog("getFirstForwarder="+f.next+"=>"+f.next.channel); |
372 | 174 return f.next; |
316 | 175 } |
358 | 176 |
177 | |
411 | 178 /** |
179 * @param manager | |
180 * | |
181 * remove all editors in this session from our manager. | |
182 */ | |
358 | 183 public void remove(SessionManager manager) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
184 for(REPNode editor : values()){ |
358 | 185 if(editor.getChannel() !=null) |
186 unconnect((Forwarder)editor); | |
187 manager.editorList.remove(editor); | |
188 } | |
189 } | |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
190 |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
191 |
411 | 192 /** |
193 * @param s | |
194 * | |
195 * Merge editors from UPDATED session. Only dummy editors | |
196 * outside of this manager to be add. | |
197 */ | |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
198 public void merge(Session s) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
199 for(REPNode editor : s.values()){ |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
200 REPNode mine = get(editor.eid); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
201 if (mine==null) { |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
202 put(editor.eid,editor); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
203 } else { |
411 | 204 // update editor status |
484 | 205 mine.mergeEditor(editor); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
206 } |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
207 } |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
208 } |
319 | 209 |
360 | 210 @Override |
211 public String toString() { | |
212 String s = super.toString(); | |
213 return s+" sid="+sessionID+" "+sessionName+" master="+ | |
214 ((masterEditor==null)?"null":masterEditor.toString()); | |
215 } | |
216 | |
217 | |
218 public void setName(String string) { | |
219 sessionName = string; | |
220 } | |
320 | 221 |
361 | 222 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
223 public void setFirstForwarder(REPNode f) { |
362 | 224 f.setSID(sessionID); |
361 | 225 put(f.eid,f); |
372 | 226 f.setNext(f); |
376 | 227 first = last = f; |
361 | 228 } |
229 | |
373 | 230 public void printSessionDetail() { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
376
diff
changeset
|
231 REPNode f = first; |
373 | 232 if (f==null) return; |
233 String log = "Session Detail "; | |
234 while (f!=null) { | |
235 log += ","+f+"="+f.channel+"->"+f.next; | |
236 f = f.next; | |
376 | 237 if (f==first) { |
373 | 238 log += "*"; |
239 break; | |
240 } | |
241 } | |
384 | 242 ServerMainLoop.logger.writeLog(log); |
373 | 243 } |
361 | 244 |
0 | 245 } |