From 637b6261d24fc43716ddb746bc2f60fbafc29fc2 Mon Sep 17 00:00:00 2001 From: Koen Deforche Date: Tue, 18 Nov 2014 22:42:12 +0100 Subject: [PATCH] Several changes: - WResource: added static resource concurrency test - WResource: reorganized resource/continuations concurrency - WResource: allow aborted requests to be handled, and allow an individual request to be continued - Http::Client: allow response data to be processed incrementally --- CMakeLists.txt | 4 +- WConfig.h.in | 1 + src/Wt/Http/Response | 12 +- src/Wt/Http/Response.C | 14 +-- src/Wt/Http/ResponseContinuation | 31 +++-- src/Wt/Http/ResponseContinuation.C | 129 +++++++++++-------- src/Wt/WAbstractMedia.C | 3 +- src/Wt/WBoostAny.C | 2 +- src/Wt/WResource | 36 ++++-- src/Wt/WResource.C | 192 ++++++++++++++++++----------- src/web/WebController.C | 3 +- src/web/skeleton/Wt.js | 18 ++- src/web/skeleton/Wt.min.js | 78 ++++++------ test/http/HttpClientServerTest.C | 66 +++++++++- 14 files changed, 388 insertions(+), 201 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f60d69097c..b680b614aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -377,8 +377,8 @@ IF(BOOST_WT_MT_FOUND) IF(MULTI_THREADED) MESSAGE("** Enabling multi threading.") SET(MULTI_THREADED_BUILD true) - - ADD_DEFINITIONS(-DWT_THREADED -D_REENTRANT -DBOOST_SPIRIT_THREADSAFE) + SET(WT_THREADED true) + ADD_DEFINITIONS(-D_REENTRANT -DBOOST_SPIRIT_THREADSAFE) ELSE(MULTI_THREADED) MESSAGE("** Disabling multi threading.") SET(MULTI_THREADED_BUILD false) diff --git a/WConfig.h.in b/WConfig.h.in index ebf651ed82..93f2634ba3 100644 --- a/WConfig.h.in +++ b/WConfig.h.in @@ -40,6 +40,7 @@ #cmakedefine WT_NO_STD_WSTRING #cmakedefine WT_USE_OPENGL #cmakedefine WT_DEBUG_ENABLED +#cmakedefine WT_THREADED #cmakedefine WT_USE_BOOST_SIGNALS #cmakedefine WT_USE_BOOST_SIGNALS2 diff --git a/src/Wt/Http/Response b/src/Wt/Http/Response index 414d16746a..fd548ae566 100644 --- a/src/Wt/Http/Response +++ b/src/Wt/Http/Response @@ -112,14 +112,14 @@ public: WT_BOSTREAM& bout() { return out(); } private: - WResource *resource_; - WebResponse *response_; - ResponseContinuation *continuation_; - WT_BOSTREAM *out_; - bool headersCommitted_; + WResource *resource_; + WebResponse *response_; + ResponseContinuationPtr continuation_; + WT_BOSTREAM *out_; + bool headersCommitted_; Response(WResource *resource, WebResponse *response, - ResponseContinuation *continuation); + ResponseContinuationPtr continuation); Response(WResource *resource, WT_BOSTREAM& out); friend class Wt::WResource; diff --git a/src/Wt/Http/Response.C b/src/Wt/Http/Response.C index f90f198d79..7a7ef710e3 100644 --- a/src/Wt/Http/Response.C +++ b/src/Wt/Http/Response.C @@ -40,18 +40,19 @@ void Response::addHeader(const std::string& name, const std::string& value) ResponseContinuation *Response::createContinuation() { - if (!continuation_) - continuation_ = new ResponseContinuation(resource_, response_); - else + if (!continuation_) { + ResponseContinuation *c = new ResponseContinuation(resource_, response_); + continuation_ = resource_->addContinuation(c); + } else continuation_->resource_ = resource_; - return continuation_; + return continuation_.get(); } ResponseContinuation *Response::continuation() const { if (continuation_ && continuation_->resource_) - return continuation_; + return continuation_.get(); else return 0; } @@ -126,7 +127,7 @@ WT_BOSTREAM& Response::out() } Response::Response(WResource *resource, WebResponse *response, - ResponseContinuation *continuation) + ResponseContinuationPtr continuation) : resource_(resource), response_(response), continuation_(continuation), @@ -137,7 +138,6 @@ Response::Response(WResource *resource, WebResponse *response, Response::Response(WResource *resource, WT_BOSTREAM& out) : resource_(resource), response_(0), - continuation_(0), out_(&out), headersCommitted_(false) { } diff --git a/src/Wt/Http/ResponseContinuation b/src/Wt/Http/ResponseContinuation index b4b2c39154..b3adfc1295 100644 --- a/src/Wt/Http/ResponseContinuation +++ b/src/Wt/Http/ResponseContinuation @@ -10,6 +10,13 @@ #include #include +#include +#include + +namespace boost { + class recursive_mutex; +} + namespace Wt { class WResource; @@ -42,9 +49,12 @@ namespace Wt { * * \ingroup http */ -class WT_API ResponseContinuation +class WT_API ResponseContinuation + : public boost::enable_shared_from_this { public: + ~ResponseContinuation(); + /*! \brief Set data associated with the continuation. * * You could do this to keep track of the state of sending the data @@ -83,23 +93,22 @@ public: */ bool isWaitingForMoreData() const { return waiting_; } - /* - * Only useful for server-side events: force continuation. - */ - void doContinue(WebWriteEvent event); - private: +#ifdef WT_THREADED + boost::shared_ptr mutex_; +#endif + WResource *resource_; WebResponse *response_; boost::any data_; - bool waiting_, readyToContinue_, needsContinue_; + bool waiting_, readyToContinue_; ResponseContinuation(WResource *resource, WebResponse *response); ResponseContinuation(const ResponseContinuation&); - ~ResponseContinuation(); - void cancel(); - void flagReadyToContinue(WebWriteEvent); + void cancel(bool resourceIsBeingDeleted); + void readyToContinue(WebWriteEvent writeResult); + WebResponse *response() { return response_; } friend class Wt::WResource; @@ -107,6 +116,8 @@ private: friend class Response; }; +typedef boost::shared_ptr ResponseContinuationPtr; + } } diff --git a/src/Wt/Http/ResponseContinuation.C b/src/Wt/Http/ResponseContinuation.C index 7edf14ddae..d4b31b341d 100644 --- a/src/Wt/Http/ResponseContinuation.C +++ b/src/Wt/Http/ResponseContinuation.C @@ -10,6 +10,10 @@ #include "WebRequest.h" +#ifdef WT_THREADED +#include +#endif + namespace Wt { LOGGER("Http::ResponseContinuation"); @@ -23,79 +27,106 @@ void ResponseContinuation::setData(const boost::any& data) void ResponseContinuation::haveMoreData() { - if (isWaitingForMoreData()) - doContinue(WriteCompleted); + WResource::UseLock useLock; + WResource *resource = 0; + + { +#ifdef WT_THREADED + boost::recursive_mutex::scoped_lock lock(*mutex_); +#endif // WT_THREADED + + if (!useLock.use(resource_)) + return; + + if (waiting_) { + waiting_ = false; + if (readyToContinue_) { + readyToContinue_ = false; + resource = resource_; + resource_ = 0; + } + } + } + + if (resource) + resource->doContinue(shared_from_this()); } -void ResponseContinuation::doContinue(WebWriteEvent event) +void ResponseContinuation::readyToContinue(WebWriteEvent event) { if (event == WriteError) { LOG_ERROR("WriteError"); - cancel(); + cancel(false); return; } - /* - * Although we are waiting for more data, we're not yet ready to continue - * We'll remember to continue as soon as we become ready. - */ - if (waiting_ && !readyToContinue_) { - needsContinue_ = true; - return; - } + WResource::UseLock useLock; + WResource *resource = 0; + + { +#ifdef WT_THREADED + boost::recursive_mutex::scoped_lock lock(*mutex_); +#endif // WT_THREADED - waiting_ = false; - needsContinue_ = false; + if (!useLock.use(resource_)) + return; - // We are certain that the continuation is still "alive" because it is - // protected by a mutex, and thus a simultaneous change with - // WebResponse::flush() is not possible: ResponseContinuation::cancel(), - // called from beingDeleted() and protected by the same mutex - // will not be called while we are here. - resource_->doContinue(this); + readyToContinue_ = true; + + if (!waiting_) { + readyToContinue_ = false; + resource = resource_; + resource_ = 0; + } + } + + if (resource) + resource->doContinue(shared_from_this()); } ResponseContinuation::ResponseContinuation(WResource *resource, WebResponse *response) - : resource_(resource), + : +#ifdef WT_THREADED + mutex_(resource->mutex_), +#endif + resource_(resource), response_(response), waiting_(false), - readyToContinue_(false), - needsContinue_(false) -{ - resource_->continuations_.push_back(this); -} + readyToContinue_(false) +{ } -void ResponseContinuation::cancel() +void ResponseContinuation::cancel(bool resourceIsBeingDeleted) { - Http::Request request(*response_, this); - resource_->handleAbort(request); - resource_->removeContinuation(this); - - response_->flush(WebResponse::ResponseDone); + WResource::UseLock useLock; + WResource *resource = 0; + + { +#ifdef WT_THREADED + boost::recursive_mutex::scoped_lock lock(*mutex_); +#endif // WT_THREADED + + if (resourceIsBeingDeleted) { + if (!resource_) + return; + } else if (!useLock.use(resource_)) + return; + + resource = resource_; + resource_ = 0; + } - delete this; + if (resource) { + Http::Request request(*response_, this); + resource->handleAbort(request); + resource->removeContinuation(shared_from_this()); + response_->flush(WebResponse::ResponseDone); + } } void ResponseContinuation::waitForMoreData() { waiting_ = true; - needsContinue_ = false; - readyToContinue_ = false; -} - -void ResponseContinuation::flagReadyToContinue(WebWriteEvent event) -{ - if (event == WriteError) { - LOG_ERROR("WriteError"); - cancel(); - return; - } - - readyToContinue_ = true; - - if (needsContinue_) - doContinue(event); } ResponseContinuation::~ResponseContinuation() diff --git a/src/Wt/WAbstractMedia.C b/src/Wt/WAbstractMedia.C index 2aed9ad74c..0e1d4af420 100644 --- a/src/Wt/WAbstractMedia.C +++ b/src/Wt/WAbstractMedia.C @@ -127,8 +127,7 @@ void WAbstractMedia::setFormData(const FormData& formData) try { readyState_ = intToReadyState(boost::lexical_cast(attributes[5])); } catch (const std::exception& e) { - throw WException("WAbstractMedia: error parsing: " + formData.values[0] - + ": " + e.what()); + readyState_ = HaveNothing; } } else throw WException("WAbstractMedia: error parsing: " + formData.values[0]); diff --git a/src/Wt/WBoostAny.C b/src/Wt/WBoostAny.C index 16b02b90a7..5074538dff 100644 --- a/src/Wt/WBoostAny.C +++ b/src/Wt/WBoostAny.C @@ -6,7 +6,7 @@ #include #include #include - +#include "Wt/WConfig.h" #ifdef WT_THREADED #include #include diff --git a/src/Wt/WResource b/src/Wt/WResource index 1281f2736b..1ac8ab34b6 100644 --- a/src/Wt/WResource +++ b/src/Wt/WResource @@ -14,9 +14,13 @@ #include +#ifdef WT_THREADED +#include + namespace boost { class recursive_mutex; } +#endif // WT_THREADED namespace Wt { @@ -28,6 +32,8 @@ namespace Wt { class Request; class Response; class ResponseContinuation; + + typedef boost::shared_ptr ResponseContinuationPtr; } /*! \class WResource Wt/WResource Wt/WResource @@ -395,21 +401,36 @@ protected: void beingDeleted(); private: -#ifndef WT_TARGET_JAVA + struct UseLock { + UseLock(); + ~UseLock(); + + bool use(WResource *resource); + + private: + WResource *resource_; + }; + +#ifdef WT_THREADED boost::shared_ptr mutex_; -#endif // WT_TARGET_JAVA + bool beingDeleted_; + int useCount_; + boost::condition useDone_; +#endif Signal dataChanged_; Signal< ::uint64_t, ::uint64_t > dataReceived_; - bool beingDeleted_, trackUploadProgress_; + bool trackUploadProgress_; - std::vector continuations_; + std::vector continuations_; - void removeContinuation(Http::ResponseContinuation *continuation); - void doContinue(Http::ResponseContinuation *continuation); + void removeContinuation(Http::ResponseContinuationPtr continuation); + Http::ResponseContinuationPtr addContinuation(Http::ResponseContinuation *c); + void doContinue(Http::ResponseContinuationPtr continuation); void handle(WebRequest *webRequest, WebResponse *webResponse, - Http::ResponseContinuation *continuation = 0); + Http::ResponseContinuationPtr continuation + = Http::ResponseContinuationPtr()); Wt::WString suggestedFileName_; DispositionType dispositionType_; @@ -417,6 +438,7 @@ private: std::string internalPath_; friend class Http::ResponseContinuation; + friend class Http::Response; friend class WebSession; friend class WebController; friend class Configuration; diff --git a/src/Wt/WResource.C b/src/Wt/WResource.C index 84f2771082..7a2ff8febe 100644 --- a/src/Wt/WResource.C +++ b/src/Wt/WResource.C @@ -23,27 +23,83 @@ namespace Wt { LOGGER("WResource"); +/* + * Resource locking strategy: + * + * A resource is reentrant: multiple calls to handleRequest can happen + * simultaneously. + * + * The mutex_ protects: + * - beingDeleted_: indicates that the resource wants to be deleted, + * and thus should no longer be used (by continuations) + * - useCount_: number of requests currently being handled + * - continuations_: the list of continuations + */ + +WResource::UseLock::UseLock() + : resource_(0) +{ } + +bool WResource::UseLock::use(WResource *resource) +{ +#ifdef WT_THREADED + if (resource && !resource->beingDeleted_) { + resource_ = resource; + ++resource_->useCount_; + + return true; + } else + return false; +#else + return true; +#endif +} + +WResource::UseLock::~UseLock() +{ +#ifdef WT_THREADED + if (resource_) { + boost::recursive_mutex::scoped_lock lock(*resource_->mutex_); + --resource_->useCount_; + if (resource_->useCount_ == 0) + resource_->useDone_.notify_one(); + } +#endif +} + WResource::WResource(WObject* parent) : WObject(parent), dataChanged_(this), - beingDeleted_(false), trackUploadProgress_(false), dispositionType_(NoDisposition) { #ifdef WT_THREADED mutex_.reset(new boost::recursive_mutex()); + beingDeleted_ = false; + useCount_ = 0; #endif // WT_THREADED } void WResource::beingDeleted() { + std::vector cs; + + { #ifdef WT_THREADED - boost::recursive_mutex::scoped_lock lock(*mutex_); - beingDeleted_ = true; + boost::recursive_mutex::scoped_lock lock(*mutex_); + beingDeleted_ = true; + + while (useCount_ > 0) + useDone_.wait(lock); #endif // WT_THREADED - while (!continuations_.empty()) - continuations_.back()->cancel(); + cs = continuations_; + + continuations_.clear(); + } + + for (unsigned i = 0; i < cs.size(); ++i) + cs[i]->cancel(true); } WResource::~WResource() @@ -73,22 +129,21 @@ void WResource::setUploadProgress(bool enabled) void WResource::haveMoreData() { + std::vector cs; + + { #ifdef WT_THREADED - boost::recursive_mutex::scoped_lock lock(*mutex_); + boost::recursive_mutex::scoped_lock lock(*mutex_); #endif // WT_THREADED - - std::vector cs = continuations_; + cs = continuations_; + } for (unsigned i = 0; i < cs.size(); ++i) cs[i]->haveMoreData(); } -void WResource::doContinue(Http::ResponseContinuation *continuation) +void WResource::doContinue(Http::ResponseContinuationPtr continuation) { -#ifdef WT_THREADED - boost::recursive_mutex::scoped_lock lock(*mutex_); -#endif // WT_THREADED - WebResponse *webResponse = continuation->response(); WebRequest *webRequest = webResponse; @@ -101,81 +156,80 @@ void WResource::doContinue(Http::ResponseContinuation *continuation) } } -void WResource::removeContinuation(Http::ResponseContinuation *continuation) +void WResource::removeContinuation(Http::ResponseContinuationPtr continuation) { #ifdef WT_THREADED boost::recursive_mutex::scoped_lock lock(*mutex_); #endif - Utils::erase(continuations_, continuation); } +Http::ResponseContinuationPtr +WResource::addContinuation(Http::ResponseContinuation *c) +{ + Http::ResponseContinuationPtr result(c); + +#ifdef WT_THREADED + boost::recursive_mutex::scoped_lock lock(*mutex_); +#endif + continuations_.push_back(result); + + return result; +} + void WResource::handle(WebRequest *webRequest, WebResponse *webResponse, - Http::ResponseContinuation *continuation) + Http::ResponseContinuationPtr continuation) { - bool retakeLock = false; + /* + * If we are a new request for a dynamic resource, then we will have + * the session lock at this point and thus the resource is protected + * against deletion. + * + * If we come from a continuation, then the continuation increased the + * use count and we are thus protected against deletion. + */ + bool retakeHandlerLock = false; WebSession::Handler *handler = WebSession::Handler::instance(); + UseLock useLock; - bool dynamic = handler || continuation; - - { + if (handler && !continuation) { #ifdef WT_THREADED - boost::shared_ptr mutex = mutex_; - boost::recursive_mutex::scoped_lock lock(*mutex, boost::defer_lock); - - if (dynamic) { - lock.lock(); - if (beingDeleted_) - return; - - // when we are handling a continuation, we do not have the session - // lock, unless we are being called from haveMoreData(), but then it's - // fine I guess ? - if (!continuation) { - if (handler->haveLock() && - handler->lockOwner() == boost::this_thread::get_id()) { - retakeLock = true; - handler->lock().unlock(); - } - } + boost::recursive_mutex::scoped_lock lock(*mutex_); + + if (!useLock.use(this)) + return; + + if (handler->haveLock() && + handler->lockOwner() == boost::this_thread::get_id()) { + retakeHandlerLock = true; + handler->lock().unlock(); } #endif // WT_THREADED + } - if (continuation) - continuation->resource_ = 0; + Http::Request request(*webRequest, continuation.get()); + Http::Response response(this, webResponse, continuation); - Http::Request request(*webRequest, continuation); - Http::Response response(this, webResponse, continuation); + if (!continuation) + response.setStatus(200); - if (!continuation) - response.setStatus(200); + handleRequest(request, response); - handleRequest(request, response); + if (!response.continuation_ || !response.continuation_->resource_) { + if (response.continuation_) + removeContinuation(response.continuation_); - if (!response.continuation_ || !response.continuation_->resource_) { - if (response.continuation_) { - Utils::erase(continuations_, response.continuation_); - delete response.continuation_; - } - - response.out(); // trigger committing the headers if still necessary - - webResponse->flush(WebResponse::ResponseDone); - } else { - if (response.continuation_->isWaitingForMoreData()) { - webResponse->flush - (WebResponse::ResponseFlush, - boost::bind(&Http::ResponseContinuation::flagReadyToContinue, - response.continuation_, _1)); - } else - webResponse->flush - (WebResponse::ResponseFlush, - boost::bind(&Http::ResponseContinuation::doContinue, - response.continuation_, _1)); - } + response.out(); // trigger committing the headers if still necessary + + webResponse->flush(WebResponse::ResponseDone); + } else { + webResponse->flush + (WebResponse::ResponseFlush, + boost::bind(&Http::ResponseContinuation::readyToContinue, + response.continuation_, _1)); } - if (retakeLock) { + if (retakeHandlerLock) { #ifdef WT_THREADED if (!handler->haveLock()) handler->lock().lock(); @@ -254,12 +308,10 @@ void WResource::write(WT_BOSTREAM& out, // While the resource indicates more data to be sent, get it too. while (response.continuation_ && response.continuation_->resource_) { response.continuation_->resource_ = 0; - request.continuation_ = response.continuation_; + request.continuation_ = response.continuation_.get(); handleRequest(request, response); } - - delete response.continuation_; } } diff --git a/src/web/WebController.C b/src/web/WebController.C index 42a27ac37d..4c64e5b95a 100644 --- a/src/web/WebController.C +++ b/src/web/WebController.C @@ -591,7 +591,8 @@ void WebController::handleRequest(WebRequest *request) } if (request->entryPoint_->type() == StaticResource) { - request->entryPoint_->resource()->handle(request, (WebResponse *)request); + request + ->entryPoint_->resource()->handle(request, (WebResponse *)request); return; } diff --git a/src/web/skeleton/Wt.js b/src/web/skeleton/Wt.js index eef8c5d337..a065ce5d54 100644 --- a/src/web/skeleton/Wt.js +++ b/src/web/skeleton/Wt.js @@ -749,9 +749,12 @@ this.pageCoordinates = function(e) { if (target && (target.ownerDocument != document)) for (var i=0; i < window.frames.length; i++) { if (target.ownerDocument == window.frames[i].document) { - var rect = window.frames[i].frameElement.getBoundingClientRect(); - posX = rect.left; - posY = rect.top; + try{ + var rect = window.frames[i].frameElement.getBoundingClientRect(); + posX = rect.left; + posY = rect.top; + }catch (e) { + } } } @@ -1210,9 +1213,12 @@ this.capture = function(obj) { // attach to possible iframes for (var i=0; i < window.frames.length; i++) - if (! window.frames[i].document.body.hasMouseHandlers) { - attachMouseHandlers(window.frames[i].document.body); - window.frames[i].document.body.hasMouseHandlers = true; + try{ + if (! window.frames[i].document.body.hasMouseHandlers) { + attachMouseHandlers(window.frames[i].document.body); + window.frames[i].document.body.hasMouseHandlers = true; + } + }catch (e) { } captureElement = obj; diff --git a/src/web/skeleton/Wt.min.js b/src/web/skeleton/Wt.min.js index c426acff3f..c9a0880821 100644 --- a/src/web/skeleton/Wt.min.js +++ b/src/web/skeleton/Wt.min.js @@ -21,12 +21,12 @@ g.isGecko&&window.addEventListener("mouseout",function(b){!b.relatedTarget&&g.ha "%25").replace(/\+/g,"%2b").replace(/ /g,"%20").replace(/&/g,"%26")}var g=this;this.condCall=function(a,b,d){a[b]&&a[b](d)};var na=this.buttons=0;this.button=function(a){try{var b=a.type;if(g.isIE&&(b=="click"||b=="dblclick"))return na;if(b!="mouseup"&&b!="mousedown"&&b!="click"&&b!="dblclick")return 0}catch(d){return 0}return!g.isGecko&&typeof a.which!=="undefined"&&typeof a.which!=="unknown"?a.which==3?4:a.which==2?2:a.which==1?1:0:g.isIE&&typeof a.which!=="undefined"&&typeof a.which!=="unknown"? a.button==2?4:a.button==4?2:a.button==1?1:0:typeof a.which!=="undefined"&&typeof a.which!=="unknown"?a.button==2?4:a.button==1?2:1:0};this.mouseDown=function(a){g.buttons|=g.button(a)};this.mouseUp=function(a){na=g.button(a);g.buttons&=~na};this.arrayRemove=function(a,b,d){d=a.slice((d||b)+1||a.length);a.length=b<0?a.length+b:b;return a.push.apply(a,d)};this.addAll=function(a,b){for(var d=0,k=b.length;d",k[0];);return b>4?b:a}(),Y=navigator.userAgent.toLowerCase();this.isIE=ga!==undefined;this.isIE6=ga===6;this.isIE8=ga===8;this.isIElt9=ga<9;this.isIEMobile=Y.indexOf("msie 4")!=-1||Y.indexOf("msie 5")!=-1;this.isOpera=typeof window.opera!=="undefined";this.isAndroid=Y.indexOf("safari")!=-1&&Y.indexOf("android")!=-1;this.isWebKit=Y.indexOf("applewebkit")!=-1;this.isGecko=Y.indexOf("gecko")!=-1&&!this.isWebKit;this.updateDelay=this.isIE?10:51;if(this.isAndroid){console.error("init console.error"); -console.info("init console.info");console.log("init console.log");console.warn("init console.warn")}var ha=new Date;this.trace=function(a,b){if(b)ha=new Date;b=new Date;b=(b.getMinutes()-ha.getMinutes())*6E4+(b.getSeconds()-ha.getSeconds())*1E3+(b.getMilliseconds()-ha.getMilliseconds());window.console&&console.log("["+b+"]: "+a)};this.initAjaxComm=function(a,b){function d(h,m){var o=null,q=true;if(window.XMLHttpRequest){o=new XMLHttpRequest;if(k)if("withCredentials"in o){if(m){o.open(h,m,true);o.withCredentials= -"true"}}else if(typeof XDomainRequest!="undefined"){o=new XDomainRequest;if(m){q=false;try{o.open(h,m+"&contentType=x-www-form-urlencoded")}catch(t){o=null}}}else o=null;else m&&o.open(h,m,true)}else if(!k&&window.ActiveXObject){try{o=new ActiveXObject("Msxml2.XMLHTTP")}catch(u){try{o=new ActiveXObject("Microsoft.XMLHTTP")}catch(w){}}m&&o&&o.open(h,m,true)}o&&m&&q&&o.setRequestHeader("Content-type","application/x-www-form-urlencoded");return o}var k=(a.indexOf("://")!=-1||a.indexOf("//")==0)&&P(a)!= -window.location.host;return d("POST",a)!=null?new (function(){function h(o,q,t,u){function w(r){if(!G){clearTimeout(M);if(r){G=true;b(0,v.responseText,q)}else b(1,null,q);if(v){v.onreadystatechange=new Function;try{v.onload=v.onreadystatechange}catch(Z){}v=null}G=true}}function y(){if(v.readyState==4){var r=v.status==200&&v.getResponseHeader("Content-Type")&&v.getResponseHeader("Content-Type").indexOf("text/javascript")==0;w(r)}}function z(){v.onreadystatechange=new Function;v=null;G=true;b(2,null, -q)}var v=d("POST",m),M=null,G=false;this.abort=function(){if(v!=null){v.onreadystatechange=new Function;G=true;v.abort();v=null}};_$_CLOSE_CONNECTION_$_&&v.setRequestHeader("Connection","close");if(u>0)M=setTimeout(z,u);v.onreadystatechange=y;try{v.onload=function(){w(true)};v.onerror=function(){w(false)}}catch(E){}v.send(o)}var m=a;this.responseReceived=function(){};this.sendUpdate=function(o,q,t,u){return new h(o,q,t,u)};this.setUrl=function(o){m=o}}):new (function(){function h(q,t,u){function w(){b(1, -null,t);y.parentNode.removeChild(y)}this.userData=t;var y=this.script=document.createElement("script");y.id="script"+u;y.setAttribute("src",m+"&"+q);y.onerror=w;document.getElementsByTagName("head")[0].appendChild(y);this.abort=function(){y.parentNode.removeChild(y)}}var m=a,o=null;this.responseReceived=function(){if(o!=null){var q=o;o.script.parentNode.removeChild(o.script);o=null;b(0,"",q.userData)}};this.sendUpdate=function(q,t,u,w){return o=new h(q,t,u,w)};this.setUrl=function(q){m=q}})};this.setHtml= -function(a,b,d){function k(m,o){var q,t,u;switch(m.nodeType){case 1:q=m.namespaceURI===null?document.createElement(m.nodeName):document.createElementNS(m.namespaceURI,m.nodeName);if(m.attributes&&m.attributes.length>0){t=0;for(u=m.attributes.length;t0){t=0;for(u=m.childNodes.length;t0)M=setTimeout(z,u);v.onreadystatechange=y;try{v.onload=function(){w(true)};v.onerror=function(){w(false)}}catch(E){}v.send(n)}var m=a;this.responseReceived=function(){};this.sendUpdate=function(n,q,t,u){return new h(n,q,t,u)};this.setUrl=function(n){m=n}}):new (function(){function h(q,t,u){function w(){b(1, +null,t);y.parentNode.removeChild(y)}this.userData=t;var y=this.script=document.createElement("script");y.id="script"+u;y.setAttribute("src",m+"&"+q);y.onerror=w;document.getElementsByTagName("head")[0].appendChild(y);this.abort=function(){y.parentNode.removeChild(y)}}var m=a,n=null;this.responseReceived=function(){if(n!=null){var q=n;n.script.parentNode.removeChild(n.script);n=null;b(0,"",q.userData)}};this.sendUpdate=function(q,t,u,w){return n=new h(q,t,u,w)};this.setUrl=function(q){m=q}})};this.setHtml= +function(a,b,d){function k(m,n){var q,t,u;switch(m.nodeType){case 1:q=m.namespaceURI===null?document.createElement(m.nodeName):document.createElementNS(m.namespaceURI,m.nodeName);if(m.attributes&&m.attributes.length>0){t=0;for(u=m.attributes.length;t0){t=0;for(u=m.childNodes.length;t"+b+"","application/xhtml+xml").documentElement;if(h.nodeType!=1)h=h.nextSibling;if(!d){g.saveReparented(a);a.innerHTML=""}b=0;for(d=h.childNodes.length;b -a.parentNode.scrollWidth)d-=a.scrollLeft+a.parentNode.scrollWidth-a.scrollWidth}else d-=a.scrollLeft;k-=a.scrollTop}}while(a!=null&&a!=h)}}return{x:d,y:k}};this.widgetCoordinates=function(a,b){b=g.pageCoordinates(b);a=g.widgetPageCoordinates(a);return{x:b.x-a.x,y:b.y-a.y}};this.pageCoordinates=function(a){if(!a)a=window.event;var b=0,d=0,k=a.target||a.srcElement;if(k&&k.ownerDocument!=document)for(var h=0;h0?1:-1;else if(a.detail)b=a.detail<0?1:-1;return b};this.scrollIntoView=function(a){setTimeout(function(){var b=a.indexOf("#");if(b!=-1)a=a.substr(b+1);var d=document.getElementById(a);if(d){for(b=d.parentNode;b!=document.body;b=b.parentNode)if(b.scrollHeight>b.clientHeight&&g.css(b,"overflow-y")== "auto"){d=g.widgetPageCoordinates(d,b);b.scrollTop+=d.y;return}d.scrollIntoView(true)}},100)};this.getSelectionRange=function(a){if(document.selection)if(g.hasTag(a,"TEXTAREA")){var b=document.selection.createRange(),d=b.duplicate();d.moveToElementText(a);var k=0;if(b.text.length>1){k-=b.text.length;if(k<0)k=0}a=-1+k;for(d.moveStart("character",k);d.inRange(b);){d.moveStart("character");a++}b=b.text.replace(/\r/g,"");return{start:a,end:b.length+a}}else{d=b=-1;if(a=$(a).val()){d=document.selection.createRange().duplicate(); d.moveEnd("character",a.length);b=d.text==""?a.length:a.lastIndexOf(d.text);d=document.selection.createRange().duplicate();d.moveStart("character",-a.length);d=d.text.length}return{start:b,end:d}}else return a.selectionStart||a.selectionStart==0?{start:a.selectionStart,end:a.selectionEnd}:{start:-1,end:-1}};this.setSelectionRange=function(a,b,d){var k=$(a).val();if(typeof b!="number")b=-1;if(typeof d!="number")d=-1;if(b<0)b=0;if(d>k.length)d=k.length;if(dd)b=d;a.focus();if(typeof a.selectionStart!== "undefined"){a.selectionStart=b;a.selectionEnd=d}else if(document.selection){a=a.createTextRange();a.collapse(true);a.moveStart("character",b);a.moveEnd("character",d-b);a.select()}};this.isKeyPress=function(a){if(!a)a=window.event;if(a.altKey||a.ctrlKey||a.metaKey)return false;return(typeof a.charCode!=="undefined"?a.charCode:0)>0||g.isIE?true:g.isOpera?a.keyCode==13||a.keyCode==27||a.keyCode>=32&&a.keyCode<125:a.keyCode==13||a.keyCode==27||a.keyCode==32||a.keyCode>46&&a.keyCode<112};var aa=null, ba=null;this.eventRepeat=function(a,b,d){g.stopRepeat();b=b||500;d=d||50;a();aa=setTimeout(function(){aa=null;a();ba=setInterval(a,d)},b)};this.stopRepeat=function(){if(aa){clearTimeout(aa);aa=null}if(ba){clearInterval(ba);ba=null}};var oa=null,ca=null;this.css=function(a,b){if(a.style[b])return a.style[b];else{if(a!==oa){oa=a;ca=window.getComputedStyle?window.getComputedStyle(a,null):a.currentStyle?a.currentStyle:null}return ca?ca[b]:null}};this.parsePx=function(a){return Q(a,/^\s*(-?\d+(?:\.\d+)?)\s*px\s*$/i, -0)};this.px=function(a,b){return g.parsePx(g.css(a,b))};this.pxself=function(a,b){return g.parsePx(a.style[b])};this.pctself=function(a,b){return F(a.style[b],0)};this.styleAttribute=function(a){function b(q){for(var t=q.search(/-./);t!=-1;){t=q.charAt(t+1).toUpperCase();q=q.replace(/-./,t);t=q.search(/-./)}return q}var d=["","-moz-","-webkit-","-o-","-ms-"],k=document.createElement("div"),h,m;h=0;for(m=d.length;hd?d+1:a.style.styleFloat!=""?b-1:"auto"}else return"auto"}; -this.hide=function(a){g.getElement(a).style.display="none"};this.inline=function(a){g.getElement(a).style.display="inline"};this.block=function(a){g.getElement(a).style.display="block"};this.show=function(a){g.getElement(a).style.display=""};var K=null;this.firedTarget=null;this.target=function(a){try{return g.firedTarget||a.target||a.srcElement}catch(b){return null}};var sa=false;this.capture=function(a){ma();if(!(K&&a)){for(var b=0;b32768){d=document.createElement("style");b.parentNode.insertBefore(d,b);d.styleSheet.cssText=a}else d.styleSheet.cssText+=a}else{a=document.createTextNode(a);b.appendChild(a)}};this.getCssRule=function(a,b){a=a.toLowerCase();if(document.styleSheets)for(var d=0;d +k.deleteRule(h):k.removeRule(h);return true}else return m}catch(n){}++h}while(m)}return false};this.removeCssRule=function(a){return g.getCssRule(a,"delete")};this.addStyleSheet=function(a,b){if(document.createStyleSheet)setTimeout(function(){document.createStyleSheet(a)},15);else{var d=document.createElement("link");d.setAttribute("href",a);d.setAttribute("type","text/css");d.setAttribute("rel","stylesheet");b!=""&&b!="all"&&d.setAttribute("media",b);b=document.getElementsByTagName("link");if(b.length> 0){b=b[b.length-1];b.parentNode.insertBefore(d,b.nextSibling)}else document.body.appendChild(d)}};this.removeStyleSheet=function(a){$('link[rel=stylesheet][href~="'+a+'"]')&&$('link[rel=stylesheet][href~="'+a+'"]').remove();for(var b=document.styleSheets,d=0;du.x){b=w;k=0}else if(b+q>w+u.x){q=z.scrollLeft;if(z==document.body)q=z.clientWidth-u.x;k=k-v.x+q;b=z.clientWidth-(k+g.px(a,"marginRight"));k=1}else{q=z.scrollLeft;if(z==document.body)q=0;b=b-v.x+q;b-=g.px(a,"marginLeft");k=0}if(t>u.y){d=y;h=0}else if(d+t>y+u.y){if(h>y+u.y)h=y+u.y;t=z.scrollTop;if(z==document.body)t=z.clientHeight-u.y;h=h-v.y+t;d=z.clientHeight- -(h+g.px(a,"marginBottom")+g.px(a,"borderBottomWidth"));h=1}else{t=z.scrollTop;if(z==document.body)t=0;d=d-v.y+t;d=d-g.px(a,"marginTop")+g.px(a,"borderTopWidth");h=0}a.style[m[k]]=b+"px";a.style[o[h]]=d+"px"}};this.positionXY=function(a,b,d){a=g.getElement(a);if(!g.isHidden(a)){a.style.display="block";g.fitToWindow(a,b,d,b,d)}};this.Horizontal=1;this.Vertical=2;this.positionAtWidget=function(a,b,d,k){a=g.getElement(a);var h=g.getElement(b);k||(k=0);if(h&&a){var m=g.widgetPageCoordinates(h),o;a.style.position= -"absolute";if(g.css(a,"display")=="none")a.style.display="block";if(d===g.Horizontal){d=m.x+h.offsetWidth;b=m.y+k;o=m.x;k=m.y+h.offsetHeight-k}else{d=m.x;b=m.y+h.offsetHeight;o=m.x+h.offsetWidth;k=m.y}if(!a.wtNoReparent&&!$(a).hasClass("wt-no-reparent")){m=h;var q=$(".Wt-domRoot").get(0);a.parentNode.removeChild(a);for(h=m.parentNode;h!=q;h=h.parentNode){if(h.wtResize){h=m;break}if(g.css(h,"display")!="inline"&&h.clientHeight>100&&(h.scrollHeight>h.clientHeight||h.scrollWidth>h.clientWidth))break; -m=h}m=g.css(h,"position");if(m!="absolute"&&m!="relative")h.style.position="relative";h.appendChild(a);$(a).addClass("wt-reparented")}g.fitToWindow(a,d,b,o,k);a.style.visibility=""}};this.hasFocus=function(a){try{return a===document.activeElement}catch(b){return false}};this.progressed=function(a){var b=document,d=b.body,k=this.getElement("Wt-form");a.style.display=k.style.display;k.parentNode.replaceChild(a,k);d.removeEventListener?d.removeEventListener("click",delayClick,true):d.detachEvent("click", -delayClick);setTimeout(function(){var h,m;h=0;for(m=delayedClicks.length;h=1&&d[d.length-1]=="/"){_$_$if_UGLY_INTERNAL_PATHS_$_();k=true;_$_$endif_$_();_$_$ifnot_UGLY_INTERNAL_PATHS_$_();d=d.substr(0,d.length-1);_$_$endif_$_()}},navigate:function(q,t){g.resolveRelativeAnchors();b=q;var u=ua(q),w=d;if(u.length!=0)w+=(k?"?_=":"")+u;if(k){function y(v){if(v.length>1)v=v.substr(1);var M=v.split("&"),G,E;v="";G=0;for(E=M.length;G100&&(h.scrollHeight>h.clientHeight||h.scrollWidth>h.clientWidth))break; +m=h}m=g.css(h,"position");if(m!="absolute"&&m!="relative")h.style.position="relative";h.appendChild(a);$(a).addClass("wt-reparented")}g.fitToWindow(a,d,b,n,k);a.style.visibility=""}};this.hasFocus=function(a){try{return a===document.activeElement}catch(b){return false}};this.progressed=function(a){var b=document,d=b.body,k=this.getElement("Wt-form");a.style.display=k.style.display;k.parentNode.replaceChild(a,k);d.removeEventListener?d.removeEventListener("click",delayClick,true):d.detachEvent("click", +delayClick);setTimeout(function(){var h,m;h=0;for(m=delayedClicks.length;h=1&&d[d.length-1]=="/"){_$_$if_UGLY_INTERNAL_PATHS_$_();k=true;_$_$endif_$_();_$_$ifnot_UGLY_INTERNAL_PATHS_$_();d=d.substr(0,d.length-1);_$_$endif_$_()}},navigate:function(q,t){g.resolveRelativeAnchors();b=q;var u=ua(q),w=d;if(u.length!=0)w+=(k?"?_=":"")+u;if(k){function y(v){if(v.length>1)v=v.substr(1);var M=v.split("&"),G,E;v="";G=0;for(E=M.length;G1){if(u.length>2&&u[0]=="?"&&u[1]=="&")u=u.substr(1);w+=w.indexOf("?")==-1?"?"+u.substr(1):"&"+u.substr(1)}}else w+=window.location.search;try{window.history.pushState(q?q:"",document.title,w)}catch(z){console.log(z.toString())}g.scrollIntoView(q);t&&h(q)},getCurrentState:function(){return b}}}():g.isIE8?function(){var a=null,b=null,d=window;return{_initialize:function(){},_initTimeout:function(){},register:function(k, h){function m(){if(a!=d.location.hash){a=d.location.hash.substring(1);b(a)}}a=k;b=h;d.onhashchange=m},initialize:function(){},navigate:function(k,h){a=k;d.location.hash=k;g.scrollIntoView(k);h&&b(k)},getCurrentState:function(){return a}}}():function(){function a(){var s,x;x=location.href;s=x.indexOf("#");return s>=0?x.substr(s+1):null}function b(){z.value=E+"|"+r}function d(){var s,x;s=0;for(x=Z.length;s";try{x=y.contentWindow.document;x.open();x.write(s);x.close();return true}catch(C){return false}}function m(){var s,x,C,N;if(!y.contentWindow||!y.contentWindow.document)setTimeout(m,10);else{s=y.contentWindow.document;C=(x=s.getElementById("state"))?x.innerText:null;N=a();setInterval(function(){var U,H;s=y.contentWindow.document;U=(x=s.getElementById("state"))?x.innerText:null;H=a();if(U!==C){C=U;k(C);H=C?C:E;if(location.hash!=H&&location.hash.substring(1)!= -H)location.hash=H;N=H;b()}else if(H!==N){N=H;h(H)}},50);v=true;w!=null&&w()}}function o(){if(!t){var s=a(),x=history.length;M&&clearInterval(M);M=setInterval(function(){var C,N;C=a();N=history.length;if(C!==s){s=C;x=N;k(s);b()}},50)}}function q(){var s;s=z.value.split("|");if(s.length>1){E=s[0];r=s[1]}else E=r="";if(s.length>2)G=s[2].split(",");if(t)m();else{o();v=true;w!=null&&w()}}var t=g.isIElt9,u=false,w=null,y=null,z=null,v=false,M=null,G=[],E,r,Z=[];return{_initialize:function(){z!=null&&q()}, -_initTimeout:function(){o()},register:function(s,x){if(!v)r=E=escape(s);Z.push(x)},initialize:function(s,x){if(!v){if((navigator.vendor||"")!=="KDE")if(typeof window.opera!=="undefined")u=true;if(typeof s==="string")s=document.getElementById(s);if(!(!s||s.tagName.toUpperCase()!=="TEXTAREA"&&(s.tagName.toUpperCase()!=="INPUT"||s.type!=="hidden"&&s.type!=="text"))){z=s;if(t){if(typeof x==="string")x=document.getElementById(x);!x||x.tagName.toUpperCase()!=="IFRAME"||(y=x)}}}},navigate:function(s,x){s= -ua(s);if(v){s=s;if(t)h(s);else if(s.length>0)location.hash=s;x&&d()}},getCurrentState:function(){if(!v)return"";return unescape(r)}}}()});if(window._$_APP_CLASS_$_&&window._$_APP_CLASS_$_._p_)try{window._$_APP_CLASS_$_._p_.quit(null)}catch(e$$28){} +H)location.hash=H;N=H;b()}else if(H!==N){N=H;h(H)}},50);v=true;w!=null&&w()}}function n(){if(!t){var s=a(),x=history.length;M&&clearInterval(M);M=setInterval(function(){var C,N;C=a();N=history.length;if(C!==s){s=C;x=N;k(s);b()}},50)}}function q(){var s;s=z.value.split("|");if(s.length>1){E=s[0];r=s[1]}else E=r="";if(s.length>2)G=s[2].split(",");if(t)m();else{n();v=true;w!=null&&w()}}var t=g.isIElt9,u=false,w=null,y=null,z=null,v=false,M=null,G=[],E,r,Z=[];return{_initialize:function(){z!=null&&q()}, +_initTimeout:function(){n()},register:function(s,x){if(!v)r=E=escape(s);Z.push(x)},initialize:function(s,x){if(!v){if((navigator.vendor||"")!=="KDE")if(typeof window.opera!=="undefined")u=true;if(typeof s==="string")s=document.getElementById(s);if(!(!s||s.tagName.toUpperCase()!=="TEXTAREA"&&(s.tagName.toUpperCase()!=="INPUT"||s.type!=="hidden"&&s.type!=="text"))){z=s;if(t){if(typeof x==="string")x=document.getElementById(x);!x||x.tagName.toUpperCase()!=="IFRAME"||(y=x)}}}},navigate:function(s,x){s= +ua(s);if(v){s=s;if(t)h(s);else if(s.length>0)location.hash=s;x&&d()}},getCurrentState:function(){if(!v)return"";return unescape(r)}}}()});if(window._$_APP_CLASS_$_&&window._$_APP_CLASS_$_._p_)try{window._$_APP_CLASS_$_._p_.quit(null)}catch(e$$30){} window._$_APP_CLASS_$_=new (function(){function P(c){c=r.pageCoordinates(c);Z=c.x;s=c.y}function Q(){var c=_$_WT_CLASS_$_.history.getCurrentState();if(!(c!=null&&c.length>0&&c.substr(0,1)!="/"))if(C!=c){C=c;setTimeout(function(){T(null,"hash",null,true)},1)}}function F(c,e){if(!(C==c||!C&&c=="/")){e||(C=c);r.history.navigate(c,e)}}function J(){document.body.ondragstart=function(){return false}}function X(c,e){if(e.ctrlKey||r.button(e)>1)return true;var f=r.target(e);if(f)if(r.css(f,"display")!=="inline"&& -(f.offsetWidth>f.clientWidth||f.offsetHeight>f.clientHeight)){var l=r.widgetPageCoordinates(f),p=r.pageCoordinates(e),n=p.y-l.y;if(p.x-l.x>f.clientWidth||n>f.clientHeight)return true}f=N;f.object=r.getElement(c.getAttribute("dwid"));if(f.object==null)return true;f.sourceId=c.getAttribute("dsid");f.objectPrevStyle={position:f.object.style.position,display:f.object.style.display,left:f.object.style.left,top:f.object.style.top,className:f.object.className};f.object.parentNode.removeChild(f.object);f.object.style.position= +(f.offsetWidth>f.clientWidth||f.offsetHeight>f.clientHeight)){var l=r.widgetPageCoordinates(f),p=r.pageCoordinates(e),o=p.y-l.y;if(p.x-l.x>f.clientWidth||o>f.clientHeight)return true}f=N;f.object=r.getElement(c.getAttribute("dwid"));if(f.object==null)return true;f.sourceId=c.getAttribute("dsid");f.objectPrevStyle={position:f.object.style.position,display:f.object.style.display,left:f.object.style.left,top:f.object.style.top,className:f.object.className};f.object.parentNode.removeChild(f.object);f.object.style.position= "absolute";f.object.className=f.objectPrevStyle.className+"";f.object.style.zIndex="1000";document.body.appendChild(f.object);r.capture(null);r.capture(f.object);f.object.onmousemove=fa;f.object.onmouseup=la;f.offsetX=-4;f.offsetY=-4;f.dropTarget=null;f.mimeType=c.getAttribute("dmt");f.xy=r.pageCoordinates(e);r.cancelEvent(e,r.CancelPropagate);return false}function fa(c){c=c||window.event;if(N.object!==null){var e=N,f=r.pageCoordinates(c);if(e.object.style.display!==""&&e.xy.x!==f.x&&e.xy.y!==f.y)e.object.style.display= -"";e.object.style.left=f.x-e.offsetX+"px";e.object.style.top=f.y-e.offsetY+"px";f=e.dropTarget;var l=r.target(c);if(l==e.object)if(document.elementFromPoint){e.object.style.display="none";l=document.elementFromPoint(c.clientX,c.clientY);e.object.style.display=""}var p="{"+e.mimeType+":",n=null;for(e.dropTarget=null;l;){n=l.getAttribute("amts");if(n!=null&&n.indexOf(p)!=-1){e.dropTarget=l;break}l=l.parentNode;if(!l.tagName||r.hasTag(l,"HTML"))break}if(e.dropTarget!=f){if(e.dropTarget){l=n.indexOf(p)+ -p.length;var A=n.indexOf("}",l);n=n.substring(l,A);if(n.length!=0){e.dropTarget.setAttribute("dos",e.dropTarget.className);e.dropTarget.className=e.dropTarget.className+" "+n}}else e.object.styleClass="";if(f!=null){f.handleDragDrop&&f.handleDragDrop("end",e.object,c,"",p);n=f.getAttribute("dos");if(n!=null)f.className=n}}if(e.dropTarget)if(e.dropTarget.handleDragDrop)e.dropTarget.handleDragDrop("drag",e.object,c,"",p);else e.object.className=e.objectPrevStyle.className+" Wt-valid-drop";else e.object.className= -e.objectPrevStyle.className+"";return false}return true}function la(c){c=c||window.event;r.capture(null);var e=N;if(e.object){if(e.dropTarget){var f=e.dropTarget.getAttribute("dos");if(f!=null)e.dropTarget.className=f;e.dropTarget.handleDragDrop?e.dropTarget.handleDragDrop("drop",e.object,c,e.sourceId,e.mimeType):o(e.dropTarget,{name:"_drop",eventObject:e.dropTarget,event:c},e.sourceId,e.mimeType)}e.object.style.position=e.objectPrevStyle.position;e.object.style.display=e.objectPrevStyle.display; -e.object.style.left=e.objectPrevStyle.left;e.object.style.top=e.objectPrevStyle.top;e.object.className=e.objectPrevStyle.className;e.object=null}}function ma(c,e,f){var l,p;p=c+"=";c=0;for(l=e.length;c0?"&e"+e:"&";f=e+"signal="+c.signal;if(c.id){f+=e+"id="+c.id+e+"name="+encodeURIComponent(c.name)+e+"an="+c.args.length; -for(var p=0;p0?"&e"+e:"&";f=e+"signal="+c.signal;if(c.id){f+=e+"id="+c.id+e+"name="+encodeURIComponent(c.name)+e+"an="+c.args.length; +for(var p=0;p0&&r.setHtml(c.get(0),"",false)}function na(){r.history._initTimeout();qa==0&&T(null,"none",null,false)}function ga(c){if(!r.isIEMobile)document.title=c}function Y(c){if(!Ba){if(c){if(!window._$_APP_CLASS_$_LoadWidgetTree)return;r.history.initialize("Wt-history-field","Wt-history-iframe",x)}if(!("activeElement"in document)){function e(l){if(l&& l.target)document.activeElement=l.target==document?null:l.target}function f(){document.activeElement=null}document.addEventListener("focus",e,true);document.addEventListener("blur",f,true)}$(document).mousedown(r.mouseDown).mouseup(r.mouseUp);r.history._initialize();J();Ba=true;c&&window._$_APP_CLASS_$_LoadWidgetTree();W||pa||(pa=setInterval(na,_$_KEEP_ALIVE_$_000))}}function ha(c){clearTimeout(c);document.body.style.cursor="auto";if(wa!=null){try{wa()}catch(e){}wa=null}}function ea(){document.body.style.cursor= -"wait";wa=hideLoadingIndicator;showLoadingIndicator()}function aa(c){Ca=c}function ba(){E._p_.autoJavaScript()}function oa(c){if(c){c="(function() {"+c+"})();";window.execScript?window.execScript(c):window.eval(c)}E==window._$_APP_CLASS_$_&&ba()}function ca(c,e,f){if(!W)if(xa)setTimeout(function(){ca(c,e,f)},50);else{if(c==0){r.resolveRelativeAnchors();_$_$if_CATCH_ERROR_$_();try{_$_$endif_$_();oa(e);_$_$if_CATCH_ERROR_$_()}catch(l){var p=l.description||l.message,n={exception_code:l.code,exception_description:p, -exception_js:e};n.stack=l.stack||l.stacktrace;k(n,"Wt internal error; code: "+l.code+", description: "+p);throw l;}_$_$endif_$_();f&&ha(f)}else I=H.concat(I);H=[];if(da){clearTimeout(da);da=null}O=null;if(c>0)++qa;else qa=0;if(!W)if(Ca||I.length>0)if(c==1){p=Math.min(12E4,Math.exp(qa)*500);ia=setTimeout(function(){h()},p)}else h()}}function K(c){ja=c.indexOf("://")!=-1||c[0]=="/"?c:x+c;ra&&ra.setUrl(c)}function sa(){O.abort();da=O=null;W||h()}function T(c,e,f,l){if(!za){za=true;r.checkReleaseCapture(c, -f);_$_$if_STRICTLY_SERIALIZED_EVENTS_$_();if(!O){_$_$endif_$_();var p={},n=I.length;p.object=c;p.signal=e;p.event=window.fakeEvent||f;p.feedback=l;I[n]=ta(p,n);a();oa();_$_$if_STRICTLY_SERIALIZED_EVENTS_$_()}_$_$endif_$_();za=false}}function a(){if(W){if(va){if(confirm(va))document.location=document.location;va=null}}else{_$_$if_WEB_SOCKETS_$_();if(B.state!=2)if(typeof window.WebSocket==="undefined"&&typeof window.MozWebSocket==="undefined")B.state=2;else{var c=B.socket;if(c==null||c.readyState>1)if(c!= +"wait";wa=hideLoadingIndicator;showLoadingIndicator()}function aa(c){Ca=c}function ba(){E._p_.autoJavaScript()}function oa(c){if(c){c="(function() {"+c+"})();";window.execScript?window.execScript(c):window.eval(c)}E==window._$_APP_CLASS_$_&&ba()}function ca(c,e,f){if(!W)if(xa)setTimeout(function(){ca(c,e,f)},50);else{if(c==0){r.resolveRelativeAnchors();_$_$if_CATCH_ERROR_$_();try{_$_$endif_$_();oa(e);_$_$if_CATCH_ERROR_$_()}catch(l){var p=l.description||l.message,o={exception_code:l.code,exception_description:p, +exception_js:e};o.stack=l.stack||l.stacktrace;k(o,"Wt internal error; code: "+l.code+", description: "+p);throw l;}_$_$endif_$_();f&&ha(f)}else I=H.concat(I);H=[];if(da){clearTimeout(da);da=null}O=null;if(c>0)++qa;else qa=0;if(!W)if(Ca||I.length>0)if(c==1){p=Math.min(12E4,Math.exp(qa)*500);ia=setTimeout(function(){h()},p)}else h()}}function K(c){ja=c.indexOf("://")!=-1||c[0]=="/"?c:x+c;ra&&ra.setUrl(c)}function sa(){O.abort();da=O=null;W||h()}function T(c,e,f,l){if(!za){za=true;r.checkReleaseCapture(c, +f);_$_$if_STRICTLY_SERIALIZED_EVENTS_$_();if(!O){_$_$endif_$_();var p={},o=I.length;p.object=c;p.signal=e;p.event=window.fakeEvent||f;p.feedback=l;I[o]=ta(p,o);a();oa();_$_$if_STRICTLY_SERIALIZED_EVENTS_$_()}_$_$endif_$_();za=false}}function a(){if(W){if(va){if(confirm(va))document.location=document.location;va=null}}else{_$_$if_WEB_SOCKETS_$_();if(B.state!=2)if(typeof window.WebSocket==="undefined"&&typeof window.MozWebSocket==="undefined")B.state=2;else{var c=B.socket;if(c==null||c.readyState>1)if(c!= null&&B.state==0)B.state=2;else{function e(){if(!W){++B.reconnectTries;var l=Math.min(12E4,Math.exp(B.reconnectTries)*500);setTimeout(function(){a()},l)}}var f;if(ja.indexOf("://")!=-1)f="ws"+ja.substr(4);else{f=ja.substr(ja.indexOf("?"));f="ws"+location.protocol.substr(4)+"//"+location.host+x+f}f+="&request=ws";B.socket=typeof window.WebSocket!=="undefined"?(c=new WebSocket(f)):(c=new MozWebSocket(f));B.keepAlive&&clearInterval(B.keepAlive);B.keepAlive=null;c.onmessage=function(l){B.reconnectTries= 0;B.state=1;ca(0,l.data,null)};c.onerror=function(){if(B.reconnectTries==3&&B.state==0)B.state=2;e()};c.onclose=function(){if(B.reconnectTries==3&&B.state==0)B.state=2;e()};c.onopen=function(){c.send("&signal=ping");B.keepAlive&&clearInterval(B.keepAlive);B.keepAlive=setInterval(function(){if(c.readyState==1)c.send("&signal=ping");else{clearInterval(B.keepAlive);B.keepAlive=null}},_$_SERVER_PUSH_TIMEOUT_$_)}}if(c.readyState==1){h();return}}_$_$endif_$_();if(O!=null&&da!=null){clearTimeout(da);O.abort(); O=null}if(O==null)if(ia==null){ia=setTimeout(function(){h()},r.updateDelay);Da=(new Date).getTime()}else if(qa){clearTimeout(ia);h()}else if((new Date).getTime()-Da>r.updateDelay){clearTimeout(ia);h()}}}function b(c,e){Aa=e;ya=c;ra.responseReceived(c)}function d(c){Ea=c}function k(c,e){O=ra.sendUpdate("request=jserror&err="+encodeURIComponent(JSON.stringify(c)),false,ya,-1);_$_$if_SHOW_ERROR_$_();alert(e);_$_$endif_$_()}function h(){if(E!=window._$_APP_CLASS_$_)g(null);else if(!O){ia=null;if(!W){var c, e,f;if(I.length>0){c=ua();e=c.feedback?setTimeout(ea,_$_INDICATOR_TIMEOUT_$_):null;f=false}else{c={result:"&signal=poll"};e=null;f=true}c.result+="&ackId="+ya+"&pageId="+Ea;if(Aa){var l="",p=$("#"+Aa).get(0);if(p)for(p=p.parentNode;!r.hasTag(p,"BODY");p=p.parentNode)if(p.id){if(l!="")l+=",";l+=p.id}c.result+="&ackPuzzle="+encodeURIComponent(l)}c.result+="&_$_PARAMS_$_";if(B.socket!=null&&B.socket.readyState==1){O=null;e!=null&&clearTimeout(e);f||B.socket.send(c.result)}else{O=ra.sendUpdate("request=jsupdate"+ -c.result,e,ya,-1);da=f?setTimeout(sa,_$_SERVER_PUSH_TIMEOUT_$_):null}}}}function m(c,e,f){if(e==-1)e=c.offsetWidth;if(f==-1)f=c.offsetHeight;if(typeof c.wtWidth==="undefined"||c.wtWidth!=e||typeof c.wtHeight==="undefined"||c.wtHeight!=f){c.wtWidth=e;c.wtHeight=f;e>=0&&f>=0&&o(c,"resized",e,f)}}function o(c,e){var f={},l=I.length;f.signal="user";f.id=typeof c==="string"?c:c==E?"app":c.id;if(typeof e==="object"){f.name=e.name;f.object=e.eventObject;f.event=e.event}else{f.name=e;f.object=f.event=null}f.args= -[];for(var p=2;p1)w(c,e,V-1);else{V={"error-description":"Fatal error: failed loading "+c};k(V,V["error-description"]);g(null)}}}function p(){if(!n&&!A){n=true;u(c)}}var n=false,A=false;if(e!="")try{n=!eval("typeof "+e+" === 'undefined'")}catch(D){n=false}if(n)u(c);else{var S=document.createElement("script");S.setAttribute("src",c);S.onload=p;S.onerror=l;S.onreadystatechange= +c.result,e,ya,-1);da=f?setTimeout(sa,_$_SERVER_PUSH_TIMEOUT_$_):null}}}}function m(c,e,f){if(e==-1)e=c.offsetWidth;if(f==-1)f=c.offsetHeight;if(typeof c.wtWidth==="undefined"||c.wtWidth!=e||typeof c.wtHeight==="undefined"||c.wtHeight!=f){c.wtWidth=e;c.wtHeight=f;e>=0&&f>=0&&n(c,"resized",e,f)}}function n(c,e){var f={},l=I.length;f.signal="user";f.id=typeof c==="string"?c:c==E?"app":c.id;if(typeof e==="object"){f.name=e.name;f.object=e.eventObject;f.event=e.event}else{f.name=e;f.object=f.event=null}f.args= +[];for(var p=2;p1)w(c,e,V-1);else{V={"error-description":"Fatal error: failed loading "+c};k(V,V["error-description"]);g(null)}}}function p(){if(!o&&!A){o=true;u(c)}}var o=false,A=false;if(e!="")try{o=!eval("typeof "+e+" === 'undefined'")}catch(D){o=false}if(o)u(c);else{var S=document.createElement("script");S.setAttribute("src",c);S.onload=p;S.onerror=l;S.onreadystatechange= function(){var V=S.readyState;if(V=="loaded")r.isOpera||r.isIE?p():l();else V=="complete"&&p()};document.getElementsByTagName("head")[0].appendChild(S)}}function y(c,e){this.callback=e;this.work=c.length;this.images=[];if(c.length==0)e(this.images);else for(e=0;e clients; + + for (unsigned i = 0; i < 1000; ++i) { + Client *client = new Client(); + client->get("http://" + server.address() + "/test"); + clients.push_back(client); + } + + for (;;) { + bool alldone = true; + + for (unsigned i = 0; i < clients.size(); ++i) { + if (!clients[i]->isDone()) { + if (i % 100 == 0) { + clients[i]->abort(); + ++abortedCount; + } + alldone = false; + break; + } + } + + if (!alldone) + server.resource().haveMoreData(); + else + break; + } + + for (unsigned i = 0; i < 1000; ++i) { + delete clients[i]; + } + } +} + #endif // WT_THREADED + + + + + + +