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 System
.Object
[] msgs
= messages
.ToArray();
107 for (int i
= 0; i
< msgs
.Length
; i
++)
109 Message m
= (Message
) msgs
[i
];
116 private MessageVector messages
;
117 private int indexLastRead
= 0;
118 private static System
.Object nameLock
; // protect agentNum
119 private static int agentNum
= 0; // Debug, agent number
120 private System
.String name
; // String name for debug
123 internal MessageAgent()
126 // Get a unique agent id for debug
129 /// <summary> merges two message agents
132 /// <param name="fromAgent">the agent to be merged into this one
135 internal void merge(MessageAgent fromAgent
)
137 System
.Object
[] msgs
= fromAgent
.MessageArray
;
138 for (int i
= 0; i
< msgs
.Length
; i
++)
140 messages
.Add(msgs
[i
]);
141 ((Message
) (msgs
[i
])).Agent
= this;
147 System
.Threading
.Monitor
.PulseAll(messages
); // wake all threads waiting for messages
149 else if (msgs
.Length
== 1)
151 System
.Threading
.Monitor
.Pulse(messages
); // only wake one thread
158 /// <summary> Wakes up any threads waiting for messages in the message agent
162 internal void sleepersAwake(bool all
)
167 System
.Threading
.Monitor
.PulseAll(messages
);
169 System
.Threading
.Monitor
.Pulse(messages
);
174 /// <summary> Returns true if any responses are queued for any of the agent's messages
176 /// return false if no responses are queued, otherwise true
179 internal bool isResponseReceived()
181 int size
= messages
.Count
;
182 int next
= indexLastRead
+ 1;
184 for (int i
= 0; i
< size
; i
++)
190 info
= (Message
) messages
[next
];
191 if (info
.hasReplies())
199 /// <summary> Returns true if any responses are queued for the specified msgId
201 /// return false if no responses are queued, otherwise true
204 internal bool isResponseReceived(int msgId
)
208 Message info
= messages
.findMessageById(msgId
);
209 return info
.hasReplies();
211 catch (System
.FieldAccessException ex
)
217 /// <summary> Abandon the request associated with MsgId
220 /// <param name="msgId">the message id to abandon
223 /// <param name="cons">constraints associated with this request
226 internal void Abandon(int msgId
, LdapConstraints cons
)
227 //, boolean informUser)
232 // Send abandon request and remove from connection list
233 info
= messages
.findMessageById(msgId
);
234 SupportClass
.VectorRemoveElement(messages
, info
); // This message is now dead
235 info
.Abandon(cons
, null);
239 catch (System
.FieldAccessException ex
)
245 /// <summary> Abandon all requests on this MessageAgent</summary>
247 internal void AbandonAll()
249 int size
= messages
.Count
;
252 for (int i
= 0; i
< size
; i
++)
254 info
= (Message
) messages
[i
];
255 // Message complete and no more replies, remove from id list
256 SupportClass
.VectorRemoveElement(messages
, info
);
257 info
.Abandon(null, null);
262 /// <summary> Indicates whether a specific operation is complete
265 /// <returns> true if a specific operation is complete
268 internal bool isComplete(int msgid
)
272 Message info
= messages
.findMessageById(msgid
);
278 catch (System
.FieldAccessException ex
)
280 ; // return true, if no message, it must be complete
285 /// <summary> Returns the Message object for a given messageID
288 /// <param name="msgid">the message ID.
291 internal Message
getMessage(int msgid
)
293 return messages
.findMessageById(msgid
);
296 /// <summary> Send a request to the server. A Message class is created
297 /// for the specified request which causes the message to be sent.
298 /// The request is added to the list of messages being managed by
302 /// <param name="conn">the connection that identifies the server.
305 /// <param name="msg">the LdapMessage to send
308 /// <param name="timeOut">the interval to wait for the message to complete or
309 /// <code>null</code> if infinite.
311 /// <param name="queue">the LdapMessageQueue associated with this request.
314 internal void sendMessage(Connection conn
, LdapMessage msg
, int timeOut
, LdapMessageQueue queue
, BindProperties bindProps
)
316 // creating a messageInfo causes the message to be sent
317 // and a timer to be started if needed.
318 Message message
= new Message(msg
, timeOut
, conn
, this, queue
, bindProps
);
319 messages
.Add(message
);
320 message
.sendMessage(); // Now send message to server
324 /// <summary> Returns a response queued, or waits if none queued
328 // internal System.Object getLdapMessage(System.Int32 msgId)
329 internal System
.Object
getLdapMessage(System
.Int32 msgId
)
331 return (getLdapMessage(new Integer32(msgId
)));
334 internal System
.Object
getLdapMessage(Integer32 msgId
)
336 System
.Object rfcMsg
;
337 // If no messages for this agent, just return null
338 if (messages
.Count
== 0)
344 // Request messages for a specific ID
347 // Get message for this ID
348 // Message info = messages.findMessageById(msgId);
349 Message info
= messages
.findMessageById(msgId
.intValue
);
350 rfcMsg
= info
.waitForReply(); // blocks for a response
351 if (!info
.acceptsReplies() && !info
.hasReplies())
353 // Message complete and no more replies, remove from id list
354 SupportClass
.VectorRemoveElement(messages
, info
);
355 info
.Abandon(null, null); // Get rid of resources
362 catch (System
.FieldAccessException ex
)
364 // no such message id
370 // A msgId was NOT specified, any message will do
375 int next
= indexLastRead
+ 1;
377 for (int i
= 0; i
< messages
.Count
; i
++)
379 if (next
>= messages
.Count
)
383 info
= (Message
) messages
[next
];
384 indexLastRead
= next
++;
386 // Check this request is complete
387 if (!info
.acceptsReplies() && !info
.hasReplies())
389 // Message complete & no more replies, remove from id list
390 SupportClass
.VectorRemoveElement(messages
, info
); // remove from list
391 info
.Abandon(null, null); // Get rid of resources
392 // Start loop at next message that is now moved
393 // to the current position in the Vector.
403 // We found no reply here
406 // Messages can be removed in this loop, we we must
407 // check if any messages left for this agent
408 if (messages
.Count
== 0)
413 // No data, wait for something to come in.
416 System
.Threading
.Monitor
.Wait(messages
);
418 catch (System
.Threading
.ThreadInterruptedException ex
)
422 } /* end synchronized */
426 /// <summary> Debug code to print messages in message vector</summary>
427 private void debugDisplayMessages()
431 static MessageAgent()
433 nameLock
= new System
.Object();