PageRenderTime 40ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap/MessageAgent.cs

https://bitbucket.org/danipen/mono
C# | 435 lines | 266 code | 29 blank | 140 comment | 29 complexity | b5379dcc245e76e57b863646bcb9887e MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. /******************************************************************************
  2. * The MIT License
  3. * Copyright (c) 2003 Novell Inc. www.novell.com
  4. *
  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:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  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
  21. * SOFTWARE.
  22. *******************************************************************************/
  23. //
  24. // Novell.Directory.Ldap.MessageAgent.cs
  25. //
  26. // Author:
  27. // Sunil Kumar (Sunilk@novell.com)
  28. //
  29. // (C) 2003 Novell, Inc (http://www.novell.com)
  30. //
  31. using System;
  32. using Novell.Directory.Ldap.Utilclass;
  33. namespace Novell.Directory.Ldap
  34. {
  35. /* package */
  36. class MessageAgent
  37. {
  38. private void InitBlock()
  39. {
  40. messages = new MessageVector(5, 5);
  41. }
  42. /// <summary> empty and return all messages owned by this agent
  43. ///
  44. ///
  45. /// </summary>
  46. virtual internal System.Object[] MessageArray
  47. {
  48. /* package */
  49. get
  50. {
  51. return messages.ObjectArray;
  52. }
  53. }
  54. /// <summary> Get a list of message ids controlled by this agent
  55. ///
  56. /// </summary>
  57. /// <returns> an array of integers representing the message ids
  58. /// </returns>
  59. virtual internal int[] MessageIDs
  60. {
  61. /* package */
  62. get
  63. {
  64. int size = messages.Count;
  65. int[] ids = new int[size];
  66. Message info;
  67. for (int i = 0; i < size; i++)
  68. {
  69. info = (Message) messages[i];
  70. ids[i] = info.MessageID;
  71. }
  72. return ids;
  73. }
  74. }
  75. /// <summary> Get the maessage agent number for debugging
  76. ///
  77. /// </summary>
  78. /// <returns> the agent number
  79. /// </returns>
  80. virtual internal System.String AgentName
  81. {
  82. /*packge*/
  83. get
  84. {
  85. return name;
  86. }
  87. }
  88. /// <summary> Get a count of all messages queued</summary>
  89. virtual internal int Count
  90. {
  91. /* package */
  92. get
  93. {
  94. int count = 0;
  95. for (int i = 0; i < messages.Count; i++)
  96. {
  97. Message m = (Message) messages[i];
  98. count += m.Count;
  99. }
  100. return count;
  101. }
  102. }
  103. private MessageVector messages;
  104. private int indexLastRead = 0;
  105. private static System.Object nameLock; // protect agentNum
  106. private static int agentNum = 0; // Debug, agent number
  107. private System.String name; // String name for debug
  108. /* package */
  109. internal MessageAgent()
  110. {
  111. InitBlock();
  112. // Get a unique agent id for debug
  113. }
  114. /// <summary> merges two message agents
  115. ///
  116. /// </summary>
  117. /// <param name="fromAgent">the agent to be merged into this one
  118. /// </param>
  119. /* package */
  120. internal void merge(MessageAgent fromAgent)
  121. {
  122. System.Object[] msgs = fromAgent.MessageArray;
  123. for (int i = 0; i < msgs.Length; i++)
  124. {
  125. messages.Add(msgs[i]);
  126. ((Message) (msgs[i])).Agent = this;
  127. }
  128. lock (messages.SyncRoot)
  129. {
  130. if (msgs.Length > 1)
  131. {
  132. System.Threading.Monitor.PulseAll(messages.SyncRoot); // wake all threads waiting for messages
  133. }
  134. else if (msgs.Length == 1)
  135. {
  136. System.Threading.Monitor.Pulse(messages.SyncRoot); // only wake one thread
  137. }
  138. }
  139. return ;
  140. }
  141. /// <summary> Wakes up any threads waiting for messages in the message agent
  142. ///
  143. /// </summary>
  144. /* package */
  145. internal void sleepersAwake(bool all)
  146. {
  147. lock (messages.SyncRoot)
  148. {
  149. if (all)
  150. System.Threading.Monitor.PulseAll(messages.SyncRoot);
  151. else
  152. System.Threading.Monitor.Pulse(messages.SyncRoot);
  153. }
  154. return ;
  155. }
  156. /// <summary> Returns true if any responses are queued for any of the agent's messages
  157. ///
  158. /// return false if no responses are queued, otherwise true
  159. /// </summary>
  160. /* package */
  161. internal bool isResponseReceived()
  162. {
  163. int size = messages.Count;
  164. int next = indexLastRead + 1;
  165. Message info;
  166. for (int i = 0; i < size; i++)
  167. {
  168. if (next == size)
  169. {
  170. next = 0;
  171. }
  172. info = (Message) messages[next];
  173. if (info.hasReplies())
  174. {
  175. return true;
  176. }
  177. }
  178. return false;
  179. }
  180. /// <summary> Returns true if any responses are queued for the specified msgId
  181. ///
  182. /// return false if no responses are queued, otherwise true
  183. /// </summary>
  184. /* package */
  185. internal bool isResponseReceived(int msgId)
  186. {
  187. try
  188. {
  189. Message info = messages.findMessageById(msgId);
  190. return info.hasReplies();
  191. }
  192. catch (System.FieldAccessException ex)
  193. {
  194. return false;
  195. }
  196. }
  197. /// <summary> Abandon the request associated with MsgId
  198. ///
  199. /// </summary>
  200. /// <param name="msgId">the message id to abandon
  201. ///
  202. /// </param>
  203. /// <param name="cons">constraints associated with this request
  204. /// </param>
  205. /* package */
  206. internal void Abandon(int msgId, LdapConstraints cons)
  207. //, boolean informUser)
  208. {
  209. Message info = null;
  210. try
  211. {
  212. // Send abandon request and remove from connection list
  213. info = messages.findMessageById(msgId);
  214. SupportClass.VectorRemoveElement(messages, info); // This message is now dead
  215. info.Abandon(cons, null);
  216. return ;
  217. }
  218. catch (System.FieldAccessException ex)
  219. {
  220. }
  221. return ;
  222. }
  223. /// <summary> Abandon all requests on this MessageAgent</summary>
  224. /* package */
  225. internal void AbandonAll()
  226. {
  227. int size = messages.Count;
  228. Message info;
  229. for (int i = 0; i < size; i++)
  230. {
  231. info = (Message) messages[i];
  232. // Message complete and no more replies, remove from id list
  233. SupportClass.VectorRemoveElement(messages, info);
  234. info.Abandon(null, null);
  235. }
  236. return ;
  237. }
  238. /// <summary> Indicates whether a specific operation is complete
  239. ///
  240. /// </summary>
  241. /// <returns> true if a specific operation is complete
  242. /// </returns>
  243. /* package */
  244. internal bool isComplete(int msgid)
  245. {
  246. try
  247. {
  248. Message info = messages.findMessageById(msgid);
  249. if (!info.Complete)
  250. {
  251. return false;
  252. }
  253. }
  254. catch (System.FieldAccessException ex)
  255. {
  256. ; // return true, if no message, it must be complete
  257. }
  258. return true;
  259. }
  260. /// <summary> Returns the Message object for a given messageID
  261. ///
  262. /// </summary>
  263. /// <param name="msgid">the message ID.
  264. /// </param>
  265. /* package */
  266. internal Message getMessage(int msgid)
  267. {
  268. return messages.findMessageById(msgid);
  269. }
  270. /// <summary> Send a request to the server. A Message class is created
  271. /// for the specified request which causes the message to be sent.
  272. /// The request is added to the list of messages being managed by
  273. /// this agent.
  274. ///
  275. /// </summary>
  276. /// <param name="conn">the connection that identifies the server.
  277. ///
  278. /// </param>
  279. /// <param name="msg">the LdapMessage to send
  280. ///
  281. /// </param>
  282. /// <param name="timeOut">the interval to wait for the message to complete or
  283. /// <code>null</code> if infinite.
  284. /// </param>
  285. /// <param name="queue">the LdapMessageQueue associated with this request.
  286. /// </param>
  287. /* package */
  288. internal void sendMessage(Connection conn, LdapMessage msg, int timeOut, LdapMessageQueue queue, BindProperties bindProps)
  289. {
  290. // creating a messageInfo causes the message to be sent
  291. // and a timer to be started if needed.
  292. Message message = new Message(msg, timeOut, conn, this, queue, bindProps);
  293. messages.Add(message);
  294. message.sendMessage(); // Now send message to server
  295. return ;
  296. }
  297. /// <summary> Returns a response queued, or waits if none queued
  298. ///
  299. /// </summary>
  300. /* package */
  301. // internal System.Object getLdapMessage(System.Int32 msgId)
  302. internal System.Object getLdapMessage(System.Int32 msgId)
  303. {
  304. return (getLdapMessage(new Integer32(msgId)));
  305. }
  306. internal System.Object getLdapMessage(Integer32 msgId)
  307. {
  308. System.Object rfcMsg;
  309. // If no messages for this agent, just return null
  310. if (messages.Count == 0)
  311. {
  312. return null;
  313. }
  314. if ( msgId != null)
  315. {
  316. // Request messages for a specific ID
  317. try
  318. {
  319. // Get message for this ID
  320. // Message info = messages.findMessageById(msgId);
  321. Message info = messages.findMessageById(msgId.intValue);
  322. rfcMsg = info.waitForReply(); // blocks for a response
  323. if (!info.acceptsReplies() && !info.hasReplies())
  324. {
  325. // Message complete and no more replies, remove from id list
  326. SupportClass.VectorRemoveElement(messages, info);
  327. info.Abandon(null, null); // Get rid of resources
  328. }
  329. else
  330. {
  331. }
  332. return rfcMsg;
  333. }
  334. catch (System.FieldAccessException ex)
  335. {
  336. // no such message id
  337. return null;
  338. }
  339. }
  340. else
  341. {
  342. // A msgId was NOT specified, any message will do
  343. lock (messages.SyncRoot)
  344. {
  345. while (true)
  346. {
  347. int next = indexLastRead + 1;
  348. Message info;
  349. for (int i = 0; i < messages.Count; i++)
  350. {
  351. if (next >= messages.Count)
  352. {
  353. next = 0;
  354. }
  355. info = (Message) messages[next];
  356. indexLastRead = next++;
  357. rfcMsg = info.Reply;
  358. // Check this request is complete
  359. if (!info.acceptsReplies() && !info.hasReplies())
  360. {
  361. // Message complete & no more replies, remove from id list
  362. SupportClass.VectorRemoveElement(messages, info); // remove from list
  363. info.Abandon(null, null); // Get rid of resources
  364. // Start loop at next message that is now moved
  365. // to the current position in the Vector.
  366. i -= 1;
  367. }
  368. if (rfcMsg != null)
  369. {
  370. // We got a reply
  371. return rfcMsg;
  372. }
  373. else
  374. {
  375. // We found no reply here
  376. }
  377. } // end for loop */
  378. // Messages can be removed in this loop, we we must
  379. // check if any messages left for this agent
  380. if (messages.Count == 0)
  381. {
  382. return null;
  383. }
  384. // No data, wait for something to come in.
  385. try
  386. {
  387. System.Threading.Monitor.Wait(messages.SyncRoot);
  388. }
  389. catch (System.Threading.ThreadInterruptedException ex)
  390. {
  391. }
  392. } /* end while */
  393. } /* end synchronized */
  394. }
  395. }
  396. /// <summary> Debug code to print messages in message vector</summary>
  397. private void debugDisplayMessages()
  398. {
  399. return ;
  400. }
  401. static MessageAgent()
  402. {
  403. nameLock = new System.Object();
  404. }
  405. }
  406. }