1 /******************************************************************************
3 * Copyright (c) 2003 Novell Inc. www.novell.com
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 *******************************************************************************/
24 // Novell.Directory.Ldap.MessageAgent.cs
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
33 using Novell.Directory.Ldap.Utilclass;
35 namespace Novell.Directory.Ldap
41 private void InitBlock()
43 messages = new MessageVector(5, 5);
45 /// <summary> empty and return all messages owned by this agent
49 virtual internal System.Object[] MessageArray
55 return messages.ObjectArray;
59 /// <summary> Get a list of message ids controlled by this agent
62 /// <returns> an array of integers representing the message ids
64 virtual internal int[] MessageIDs
70 int size = messages.Count;
71 int[] ids = new int[size];
74 for (int i = 0; i < size; i++)
76 info = (Message) messages[i];
77 ids[i] = info.MessageID;
83 /// <summary> Get the maessage agent number for debugging
86 /// <returns> the agent number
88 virtual internal System.String AgentName
98 /// <summary> Get a count of all messages queued</summary>
99 virtual internal int Count
106 for (int i = 0; i < messages.Count; i++)
108 Message m = (Message) messages[i];
115 private MessageVector messages;
116 private int indexLastRead = 0;
117 private static System.Object nameLock; // protect agentNum
118 private static int agentNum = 0; // Debug, agent number
119 private System.String name; // String name for debug
122 internal MessageAgent()
125 // Get a unique agent id for debug
128 /// <summary> merges two message agents
131 /// <param name="fromAgent">the agent to be merged into this one
134 internal void merge(MessageAgent fromAgent)
136 System.Object[] msgs = fromAgent.MessageArray;
137 for (int i = 0; i < msgs.Length; i++)
139 messages.Add(msgs[i]);
140 ((Message) (msgs[i])).Agent = this;
142 lock (messages.SyncRoot)
146 System.Threading.Monitor.PulseAll(messages.SyncRoot); // wake all threads waiting for messages
148 else if (msgs.Length == 1)
150 System.Threading.Monitor.Pulse(messages.SyncRoot); // only wake one thread
157 /// <summary> Wakes up any threads waiting for messages in the message agent
161 internal void sleepersAwake(bool all)
163 lock (messages.SyncRoot)
166 System.Threading.Monitor.PulseAll(messages.SyncRoot);
168 System.Threading.Monitor.Pulse(messages.SyncRoot);
173 /// <summary> Returns true if any responses are queued for any of the agent's messages
175 /// return false if no responses are queued, otherwise true
178 internal bool isResponseReceived()
180 int size = messages.Count;
181 int next = indexLastRead + 1;
183 for (int i = 0; i < size; i++)
189 info = (Message) messages[next];
190 if (info.hasReplies())
198 /// <summary> Returns true if any responses are queued for the specified msgId
200 /// return false if no responses are queued, otherwise true
203 internal bool isResponseReceived(int msgId)
207 Message info = messages.findMessageById(msgId);
208 return info.hasReplies();
210 catch (System.FieldAccessException ex)
216 /// <summary> Abandon the request associated with MsgId
219 /// <param name="msgId">the message id to abandon
222 /// <param name="cons">constraints associated with this request
225 internal void Abandon(int msgId, LdapConstraints cons)
226 //, boolean informUser)
231 // Send abandon request and remove from connection list
232 info = messages.findMessageById(msgId);
233 SupportClass.VectorRemoveElement(messages, info); // This message is now dead
234 info.Abandon(cons, null);
238 catch (System.FieldAccessException ex)
244 /// <summary> Abandon all requests on this MessageAgent</summary>
246 internal void AbandonAll()
248 int size = messages.Count;
251 for (int i = 0; i < size; i++)
253 info = (Message) messages[i];
254 // Message complete and no more replies, remove from id list
255 SupportClass.VectorRemoveElement(messages, info);
256 info.Abandon(null, null);
261 /// <summary> Indicates whether a specific operation is complete
264 /// <returns> true if a specific operation is complete
267 internal bool isComplete(int msgid)
271 Message info = messages.findMessageById(msgid);
277 catch (System.FieldAccessException ex)
279 ; // return true, if no message, it must be complete
284 /// <summary> Returns the Message object for a given messageID
287 /// <param name="msgid">the message ID.
290 internal Message getMessage(int msgid)
292 return messages.findMessageById(msgid);
295 /// <summary> Send a request to the server. A Message class is created
296 /// for the specified request which causes the message to be sent.
297 /// The request is added to the list of messages being managed by
301 /// <param name="conn">the connection that identifies the server.
304 /// <param name="msg">the LdapMessage to send
307 /// <param name="timeOut">the interval to wait for the message to complete or
308 /// <code>null</code> if infinite.
310 /// <param name="queue">the LdapMessageQueue associated with this request.
313 internal void sendMessage(Connection conn, LdapMessage msg, int timeOut, LdapMessageQueue queue, BindProperties bindProps)
315 // creating a messageInfo causes the message to be sent
316 // and a timer to be started if needed.
317 Message message = new Message(msg, timeOut, conn, this, queue, bindProps);
318 messages.Add(message);
319 message.sendMessage(); // Now send message to server
323 /// <summary> Returns a response queued, or waits if none queued
327 // internal System.Object getLdapMessage(System.Int32 msgId)
328 internal System.Object getLdapMessage(System.Int32 msgId)
330 return (getLdapMessage(new Integer32(msgId)));
333 internal System.Object getLdapMessage(Integer32 msgId)
335 System.Object rfcMsg;
336 // If no messages for this agent, just return null
337 if (messages.Count == 0)
343 // Request messages for a specific ID
346 // Get message for this ID
347 // Message info = messages.findMessageById(msgId);
348 Message info = messages.findMessageById(msgId.intValue);
349 rfcMsg = info.waitForReply(); // blocks for a response
350 if (!info.acceptsReplies() && !info.hasReplies())
352 // Message complete and no more replies, remove from id list
353 SupportClass.VectorRemoveElement(messages, info);
354 info.Abandon(null, null); // Get rid of resources
361 catch (System.FieldAccessException ex)
363 // no such message id
369 // A msgId was NOT specified, any message will do
370 lock (messages.SyncRoot)
374 int next = indexLastRead + 1;
376 for (int i = 0; i < messages.Count; i++)
378 if (next >= messages.Count)
382 info = (Message) messages[next];
383 indexLastRead = next++;
385 // Check this request is complete
386 if (!info.acceptsReplies() && !info.hasReplies())
388 // Message complete & no more replies, remove from id list
389 SupportClass.VectorRemoveElement(messages, info); // remove from list
390 info.Abandon(null, null); // Get rid of resources
391 // Start loop at next message that is now moved
392 // to the current position in the Vector.
402 // We found no reply here
405 // Messages can be removed in this loop, we we must
406 // check if any messages left for this agent
407 if (messages.Count == 0)
412 // No data, wait for something to come in.
415 System.Threading.Monitor.Wait(messages.SyncRoot);
417 catch (System.Threading.ThreadInterruptedException ex)
421 } /* end synchronized */
425 /// <summary> Debug code to print messages in message vector</summary>
426 private void debugDisplayMessages()
430 static MessageAgent()
432 nameLock = new System.Object();