3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 /******************************************************************************
24 * Copyright (c) 2003 Novell Inc. www.novell.com
26 * Permission is hereby granted, free of charge, to any person obtaining a copy
27 * of this software and associated documentation files (the Software), to deal
28 * in the Software without restriction, including without limitation the rights
29 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30 * copies of the Software, and to permit persons to whom the Software is
31 * furnished to do so, subject to the following conditions:
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
36 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
43 *******************************************************************************/
45 // Novell.Directory.Ldap.MessageAgent.cs
48 // Sunil Kumar (Sunilk@novell.com)
50 // (C) 2003 Novell, Inc (http://www.novell.com)
54 using Novell.Directory.Ldap.Utilclass;
56 namespace Novell.Directory.Ldap
62 private void InitBlock()
64 messages = new MessageVector(5, 5);
66 /// <summary> empty and return all messages owned by this agent
70 virtual internal System.Object[] MessageArray
76 return messages.ObjectArray;
80 /// <summary> Get a list of message ids controlled by this agent
83 /// <returns> an array of integers representing the message ids
85 virtual internal int[] MessageIDs
91 int size = messages.Count;
92 int[] ids = new int[size];
95 for (int i = 0; i < size; i++)
97 info = (Message) messages[i];
98 ids[i] = info.MessageID;
104 /// <summary> Get the maessage agent number for debugging
107 /// <returns> the agent number
109 virtual internal System.String AgentName
119 /// <summary> Get a count of all messages queued</summary>
120 virtual internal int Count
127 System.Object[] msgs = messages.ToArray();
128 for (int i = 0; i < msgs.Length; i++)
130 Message m = (Message) msgs[i];
137 private MessageVector messages;
138 private int indexLastRead = 0;
139 private static System.Object nameLock; // protect agentNum
140 private static int agentNum = 0; // Debug, agent number
141 private System.String name; // String name for debug
144 internal MessageAgent()
147 // Get a unique agent id for debug
150 /// <summary> merges two message agents
153 /// <param name="fromAgent">the agent to be merged into this one
156 internal void merge(MessageAgent fromAgent)
158 System.Object[] msgs = fromAgent.MessageArray;
159 for (int i = 0; i < msgs.Length; i++)
161 messages.Add(msgs[i]);
162 ((Message) (msgs[i])).Agent = this;
168 System.Threading.Monitor.PulseAll(messages); // wake all threads waiting for messages
170 else if (msgs.Length == 1)
172 System.Threading.Monitor.Pulse(messages); // only wake one thread
179 /// <summary> Wakes up any threads waiting for messages in the message agent
183 internal void sleepersAwake(bool all)
188 System.Threading.Monitor.PulseAll(messages);
190 System.Threading.Monitor.Pulse(messages);
195 /// <summary> Returns true if any responses are queued for any of the agent's messages
197 /// return false if no responses are queued, otherwise true
200 internal bool isResponseReceived()
202 int size = messages.Count;
203 int next = indexLastRead + 1;
205 for (int i = 0; i < size; i++)
211 info = (Message) messages[next];
212 if (info.hasReplies())
220 /// <summary> Returns true if any responses are queued for the specified msgId
222 /// return false if no responses are queued, otherwise true
225 internal bool isResponseReceived(int msgId)
229 Message info = messages.findMessageById(msgId);
230 return info.hasReplies();
232 catch (System.FieldAccessException ex)
238 /// <summary> Abandon the request associated with MsgId
241 /// <param name="msgId">the message id to abandon
244 /// <param name="cons">constraints associated with this request
247 internal void Abandon(int msgId, LdapConstraints cons)
248 //, boolean informUser)
253 // Send abandon request and remove from connection list
254 info = messages.findMessageById(msgId);
255 SupportClass.VectorRemoveElement(messages, info); // This message is now dead
256 info.Abandon(cons, null);
260 catch (System.FieldAccessException ex)
266 /// <summary> Abandon all requests on this MessageAgent</summary>
268 internal void AbandonAll()
270 int size = messages.Count;
273 for (int i = 0; i < size; i++)
275 info = (Message) messages[i];
276 // Message complete and no more replies, remove from id list
277 SupportClass.VectorRemoveElement(messages, info);
278 info.Abandon(null, null);
283 /// <summary> Indicates whether a specific operation is complete
286 /// <returns> true if a specific operation is complete
289 internal bool isComplete(int msgid)
293 Message info = messages.findMessageById(msgid);
299 catch (System.FieldAccessException ex)
301 ; // return true, if no message, it must be complete
306 /// <summary> Returns the Message object for a given messageID
309 /// <param name="msgid">the message ID.
312 internal Message getMessage(int msgid)
314 return messages.findMessageById(msgid);
317 /// <summary> Send a request to the server. A Message class is created
318 /// for the specified request which causes the message to be sent.
319 /// The request is added to the list of messages being managed by
323 /// <param name="conn">the connection that identifies the server.
326 /// <param name="msg">the LdapMessage to send
329 /// <param name="timeOut">the interval to wait for the message to complete or
330 /// <code>null</code> if infinite.
332 /// <param name="queue">the LdapMessageQueue associated with this request.
335 internal void sendMessage(Connection conn, LdapMessage msg, int timeOut, LdapMessageQueue queue, BindProperties bindProps)
337 // creating a messageInfo causes the message to be sent
338 // and a timer to be started if needed.
339 Message message = new Message(msg, timeOut, conn, this, queue, bindProps);
340 messages.Add(message);
341 message.sendMessage(); // Now send message to server
345 /// <summary> Returns a response queued, or waits if none queued
349 // internal System.Object getLdapMessage(System.Int32 msgId)
350 internal System.Object getLdapMessage(System.Int32 msgId)
352 return (getLdapMessage(new Integer32(msgId)));
355 internal System.Object getLdapMessage(Integer32 msgId)
357 System.Object rfcMsg;
358 // If no messages for this agent, just return null
359 if (messages.Count == 0)
365 // Request messages for a specific ID
368 // Get message for this ID
369 // Message info = messages.findMessageById(msgId);
370 Message info = messages.findMessageById(msgId.intValue);
371 rfcMsg = info.waitForReply(); // blocks for a response
372 if (!info.acceptsReplies() && !info.hasReplies())
374 // Message complete and no more replies, remove from id list
375 SupportClass.VectorRemoveElement(messages, info);
376 info.Abandon(null, null); // Get rid of resources
383 catch (System.FieldAccessException ex)
385 // no such message id
391 // A msgId was NOT specified, any message will do
396 int next = indexLastRead + 1;
398 for (int i = 0; i < messages.Count; i++)
400 if (next >= messages.Count)
404 info = (Message) messages[next];
405 indexLastRead = next++;
407 // Check this request is complete
408 if (!info.acceptsReplies() && !info.hasReplies())
410 // Message complete & no more replies, remove from id list
411 SupportClass.VectorRemoveElement(messages, info); // remove from list
412 info.Abandon(null, null); // Get rid of resources
413 // Start loop at next message that is now moved
414 // to the current position in the Vector.
424 // We found no reply here
427 // Messages can be removed in this loop, we we must
428 // check if any messages left for this agent
429 if (messages.Count == 0)
434 // No data, wait for something to come in.
437 System.Threading.Monitor.Wait(messages);
439 catch (System.Threading.ThreadInterruptedException ex)
443 } /* end synchronized */
447 /// <summary> Debug code to print messages in message vector</summary>
448 private void debugDisplayMessages()
452 static MessageAgent()
454 nameLock = new System.Object();