PageRenderTime 683ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/common/src/actionscript/org/flowplayer/net/ClusterManager.as

https://github.com/longlho/flowplayer
ActionScript | 277 lines | 211 code | 41 blank | 25 comment | 32 complexity | 6530e593c4bc0c3df1363b5e3a2e924a MD5 | raw file
Possible License(s): MIT, BSD-3-Clause
  1. /*
  2. * This file is part of Flowplayer, http://flowplayer.org
  3. *
  4. * By: Daniel Rossi, <electroteque@gmail.com>, Anssi Piirainen Flowplayer Oy
  5. * Copyright (c) 2008-2011 Flowplayer Oy *
  6. * Released under the MIT License:
  7. * http://www.opensource.org/licenses/mit-license.php
  8. */
  9. package org.flowplayer.net
  10. {
  11. import flash.events.TimerEvent;
  12. import flash.net.SharedObject;
  13. import flash.utils.Timer;
  14. import mx.utils.URLUtil;
  15. import flash.net.NetConnection;
  16. import flash.net.NetStream;
  17. import org.flowplayer.flow_internal;
  18. import org.flowplayer.model.ClipEvent;
  19. import org.flowplayer.model.PluginEventDispatcher;
  20. import org.flowplayer.model.PluginEventType;
  21. import org.flowplayer.model.PluginModel;
  22. import org.flowplayer.model.PluginModelImpl;
  23. import org.flowplayer.util.Log;
  24. use namespace flow_internal;
  25. public class ClusterManager {
  26. protected var _hosts:Array;
  27. protected var _timer:Timer;
  28. protected var _hostIndex:int = 0;
  29. protected var _hostCount:int = 0;
  30. protected var _connectCount:int = 0;
  31. protected var _reConnectCount:int = 0;
  32. protected var _connectTimeout:int = 2000;
  33. protected var _loadBalanceServers:Boolean = false;
  34. protected var _liveHosts:Array;
  35. protected var _liveRandomServers:Array = [];
  36. private var _startAfterConnect:Boolean;
  37. protected var _failureExpiry:int = 0;
  38. private var _config:*;
  39. private var _dispatcher:PluginModelImpl;
  40. private var log:Log = new Log(this);
  41. private var _reconnectListener:Function;
  42. private var _failureListener:Function;
  43. private var _currentHost:Object;
  44. public function ClusterManager(connection:NetConnection, netStream:NetStream, hosts:Vector.<*>)
  45. //public function ClusterManager(hosts:Vector.<*>, config:*)
  46. {
  47. //_config = config;
  48. _connection = connection;
  49. _netStream = netStream;
  50. // there can be several hosts, or we are just using one single netConnectionUrl
  51. initHosts(hosts, config.netConnectionUrl);
  52. //_connectCount = config.connectCount;
  53. //_connectTimeout = config.connectTimeout;
  54. //_failureExpiry = config.failureExpiry;
  55. _currentHost = _hosts[0];
  56. }
  57. public function set connectCount(value:Number):void {
  58. _connectCount = value;
  59. }
  60. public function set connectTimeout(value:Number):void {
  61. _connectTimeout = value;
  62. }
  63. public function set failureExpiry(value:Number):void {
  64. _failureExpiry = value;
  65. }
  66. private function initHosts(hosts:Vector.<*>, fallback:String):void {
  67. log.debug("initHosts()");
  68. var myHosts:Array = [];
  69. if (! hosts || hosts.length == 0) {
  70. if (! fallback) {
  71. throw new Error("A hosts array or a netConnectionUrl must be configured");
  72. }
  73. myHosts.push({ 'host': fallback});
  74. } else {
  75. for (var i:int = 0; i < hosts.length; i++) {
  76. myHosts.push(hosts[i] is String ? { 'host': hosts[i] } : hosts[i]);
  77. }
  78. }
  79. _hosts = myHosts;
  80. _liveHosts = _hosts;
  81. log.debug("initHosts(), we have " + _liveHosts.length + " live hosts initially");
  82. }
  83. public function onReconnected(listener:Function):void {
  84. _reconnectListener = listener;
  85. }
  86. public function onFailed(listener:Function):void {
  87. _failureListener = listener;
  88. }
  89. public function get currentHosts():Array
  90. {
  91. return _hosts.filter(_checkLiveHost);
  92. }
  93. public function get hosts():Array
  94. {
  95. return _hosts;
  96. }
  97. public function get nextHost():String
  98. {
  99. if (hasMultipleHosts())
  100. {
  101. _liveHosts = currentHosts;
  102. if (_liveHosts.length == 0) {
  103. log.error("no live hosts available");
  104. if (_failureListener != null) {
  105. _failureListener();
  106. return null;
  107. }
  108. }
  109. if (_config.loadBalance)
  110. {
  111. _hostIndex = getRandomIndex();
  112. log.debug("Load balanced index " + _hostIndex);
  113. }
  114. if (_liveHosts.length > _hostIndex) {
  115. log.debug("cluster has multiple hosts");
  116. _currentHost = _liveHosts[_hostIndex];
  117. return _currentHost.host;
  118. }
  119. }
  120. log.error("no hosts available");
  121. return null;
  122. }
  123. public function start():void
  124. {
  125. if (_timer && _timer.running) {
  126. _timer.stop();
  127. }
  128. _timer = new Timer(_connectTimeout, _liveHosts.length);
  129. _timer.addEventListener(TimerEvent.TIMER , tryFallBack);
  130. if (hasMultipleHosts()) {
  131. log.debug("starting connection timeout timer, with a delay of " + _connectTimeout);
  132. _timer.start();
  133. }
  134. }
  135. public function stop():void
  136. {
  137. if (_timer != null && _timer.running) _timer.stop();
  138. }
  139. public function hasMultipleHosts():Boolean
  140. {
  141. return _liveHosts.length > 0;
  142. }
  143. public function getRandomIndex():uint {
  144. return Math.round(Math.random() * (_liveHosts.length - 1));
  145. }
  146. public function get liveServers():Array
  147. {
  148. return _liveHosts;
  149. }
  150. private function _checkLiveHost(element:*, index:int, arr:Array):Boolean
  151. {
  152. return _isLiveServer(element);
  153. }
  154. private function _getFailedServerSO(host:String):SharedObject
  155. {
  156. var domain:String = URLUtil.getServerName(host);
  157. return SharedObject.getLocal(domain,"/");
  158. }
  159. public function setFailedServer(host:String):void
  160. {
  161. log.debug("Setting Failed Server: " + host);
  162. var server:SharedObject = _getFailedServerSO(host);
  163. server.data.failureTimestamp = new Date();
  164. }
  165. /*
  166. public function set connectCount(count:Number):void
  167. {
  168. _connectCount = count;
  169. } */
  170. protected function hasMoreHosts():Boolean
  171. {
  172. if (_failureExpiry == 0)
  173. _hostIndex++
  174. else
  175. _hostIndex = 0;
  176. _liveHosts = currentHosts;
  177. if (_hostIndex >= _liveHosts.length)
  178. {
  179. //
  180. _reConnectCount++;
  181. if (_reConnectCount < _connectCount)
  182. {
  183. log.debug("Restarting Connection Attempts");
  184. _hostIndex = 0;
  185. }
  186. }
  187. log.debug("Host Index: " + _hostIndex + " LiveServers: " + _liveHosts.length);
  188. return (_hostIndex <= _liveHosts.length && _liveHosts[_hostIndex]);
  189. }
  190. private function _isLiveServer(element:*):Boolean
  191. {
  192. var host:String = element.host;
  193. var server:SharedObject = _getFailedServerSO(host);
  194. // Server is failed, determine if the failure expiry interval has been reached and clear it
  195. if (server.data.failureTimestamp)
  196. {
  197. var date:Date = new Date();
  198. // Determine the failure offset
  199. var offset:int = date.getTime() - server.data.failureTimestamp.getTime();
  200. log.debug("Failed Server Remaining Expiry: " + offset + " Start Time: " + server.data.failureTimestamp.getTime() + " Current Time: " + date.getTime());
  201. // Failure offset has reached the failureExpiry setting, clear it from the list to allow a connection
  202. if (offset >= _failureExpiry)
  203. {
  204. log.debug("Clearing Failure Period " + _failureExpiry);
  205. server.clear();
  206. return true;
  207. }
  208. return false;
  209. }
  210. return true;
  211. }
  212. protected function tryFallBack(e:TimerEvent):void
  213. {
  214. // Check if there is more hosts to attempt reconnection to
  215. if (hasMoreHosts())
  216. {
  217. log.debug("invoking reconnect listener");
  218. if (_reconnectListener != null) {
  219. _reconnectListener();
  220. }
  221. } else {
  222. // we have reached the end of the hosts list stop reconnection attempts and send a failed event
  223. stop();
  224. if (_failureListener != null) {
  225. _failureListener();
  226. }
  227. }
  228. }
  229. public function get currentHost():String {
  230. return _currentHost.host;
  231. }
  232. public function get currentHostIndex():int {
  233. return _hosts.indexOf(_currentHost);
  234. }
  235. }
  236. }