• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

RegressionSM.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include "P_EventSystem.h"
00025 #include "RegressionSM.h"
00026 
00027 #define REGRESSION_SM_RETRY (100*HRTIME_MSECOND)
00028 
00029 void RegressionSM::set_status(int astatus)
00030 {
00031   ink_assert(astatus != REGRESSION_TEST_INPROGRESS);
00032   // INPROGRESS < NOT_RUN < PASSED < FAILED
00033   if (status != REGRESSION_TEST_FAILED) {
00034     if (status == REGRESSION_TEST_PASSED) {
00035       if (astatus != REGRESSION_TEST_NOT_RUN)
00036         status = astatus;
00037     } else {
00038       // INPROGRESS or NOT_RUN
00039       status = astatus;
00040     }
00041   } // else FAILED is FAILED
00042 }
00043 
00044 void RegressionSM::done(int astatus)
00045 {
00046   if (pending_action) {
00047     pending_action->cancel();
00048     pending_action = 0;
00049   }
00050   set_status(astatus);
00051   if (pstatus) *pstatus = status;
00052   if (parent) parent->child_done(status);
00053 }
00054 
00055 void RegressionSM::run(int *apstatus)
00056 {
00057   pstatus = apstatus;
00058   run();
00059 }
00060 
00061 void RegressionSM::xrun(RegressionSM *aparent)
00062 {
00063   parent = aparent;
00064   parent->nwaiting++;
00065   run();
00066 }
00067 
00068 void RegressionSM::run_in(int *apstatus, ink_hrtime t)
00069 {
00070   pstatus = apstatus;
00071   SET_HANDLER(&RegressionSM::regression_sm_start);
00072   eventProcessor.schedule_in(this, t);
00073 }
00074 
00075 void RegressionSM::child_done(int astatus)
00076 {
00077   MUTEX_LOCK(l, mutex, this_ethread());
00078   ink_assert(nwaiting > 0);
00079   --nwaiting;
00080   set_status(astatus);
00081 }
00082 
00083 int RegressionSM::regression_sm_waiting(int /* event ATS_UNUSED */ , void *data)
00084 {
00085   if (!nwaiting) {
00086     done(REGRESSION_TEST_NOT_RUN);
00087     delete this;
00088     return EVENT_DONE;
00089   }
00090   if (par || nwaiting > 1) {
00091     ((Event*)data)->schedule_in(REGRESSION_SM_RETRY);
00092     return EVENT_CONT;
00093   }
00094   run();
00095   return EVENT_DONE;
00096 }
00097 
00098 int RegressionSM::regression_sm_start(int /* event ATS_UNUSED */, void * /* data ATS_UNUSED */)
00099 {
00100   run();
00101   return EVENT_CONT;
00102 }
00103 
00104 RegressionSM *r_sequential(RegressionTest *t, RegressionSM* sm, ...)
00105 {
00106   RegressionSM *new_sm = new RegressionSM(t);
00107   va_list ap;
00108   va_start(ap, sm);
00109   new_sm->par = false;
00110   new_sm->rep = false;
00111   new_sm->ichild = 0;
00112   new_sm->nchildren = 0;
00113   new_sm->nwaiting = 0;
00114   while (0 != sm) {
00115     new_sm->children(new_sm->nchildren++) = sm;
00116     sm = va_arg(ap, RegressionSM*);
00117   }
00118   new_sm->n = new_sm->nchildren;
00119   va_end(ap);
00120   return new_sm;
00121 }
00122 
00123 RegressionSM *r_sequential(RegressionTest *t, int an, RegressionSM *sm)
00124 {
00125   RegressionSM *new_sm = new RegressionSM(t);
00126   new_sm->par = false;
00127   new_sm->rep = true;
00128   new_sm->ichild = 0;
00129   new_sm->nchildren = 1;
00130   new_sm->children(0) = sm;
00131   new_sm->nwaiting = 0;
00132   new_sm->n = an;
00133   return new_sm;
00134 }
00135 
00136 RegressionSM *r_parallel(RegressionTest *t, RegressionSM *sm, ...)
00137 {
00138   RegressionSM *new_sm = new RegressionSM(t);
00139   va_list ap;
00140   va_start(ap, sm);
00141   new_sm->par = true;
00142   new_sm->rep = false;
00143   new_sm->ichild = 0;
00144   new_sm->nchildren = 0;
00145   new_sm->nwaiting = 0;
00146   while (sm) {
00147     new_sm->children(new_sm->nchildren++) = sm;
00148     sm = va_arg(ap, RegressionSM*);
00149   }
00150   new_sm->n = new_sm->nchildren;
00151   va_end(ap);
00152   return new_sm;
00153 }
00154 
00155 RegressionSM *r_parallel(RegressionTest *t, int an, RegressionSM *sm)
00156 {
00157   RegressionSM *new_sm = new RegressionSM(t);
00158   new_sm->par = true;
00159   new_sm->rep = true;
00160   new_sm->ichild = 0;
00161   new_sm->nchildren = 1;
00162   new_sm->children(0) = sm;
00163   new_sm->nwaiting = 0;
00164   new_sm->n = an;
00165   return new_sm;
00166 }
00167 
00168 void RegressionSM::run()
00169 {
00170   // TODO: Why introduce another scope here?
00171   {
00172     MUTEX_TRY_LOCK(l, mutex, this_ethread());
00173     if (!l || nwaiting > 1)
00174       goto Lretry;
00175     RegressionSM *x = 0;
00176     while (ichild < n) {
00177       if (!rep)
00178         x = children[ichild];
00179       else {
00180         if (ichild != n-1)
00181           x = children[(intptr_t)0]->clone();
00182         else
00183           x = children[(intptr_t)0];
00184       }
00185       if (!ichild) nwaiting++;
00186       x->xrun(this);
00187       ichild++;
00188       if (!par && nwaiting > 1)
00189         goto Lretry;
00190     }
00191   }
00192   nwaiting--;
00193   if (!nwaiting) {
00194     done(REGRESSION_TEST_NOT_RUN);
00195     delete this;
00196     return;
00197   }
00198 Lretry:
00199   SET_HANDLER(&RegressionSM::regression_sm_waiting);
00200   pending_action = eventProcessor.schedule_in(this, REGRESSION_SM_RETRY);
00201 }
00202 
00203 RegressionSM::RegressionSM(const RegressionSM &ao)
00204 {
00205   RegressionSM &o = *(RegressionSM*)&ao;
00206   t = o.t;
00207   status = o.status;
00208   pstatus = o.pstatus;
00209   parent = &o;
00210   nwaiting = o.nwaiting;
00211   nchildren = o.nchildren;
00212   for (intptr_t i = 0; i < nchildren; i++)
00213     children(i) = o.children[i]->clone();
00214   n = o.n;
00215   ichild = o.ichild;
00216   par = o.par;
00217   rep = o.rep;
00218   pending_action = o.pending_action;
00219   ink_assert(status == REGRESSION_TEST_INPROGRESS);
00220   ink_assert(nwaiting == 0);
00221   ink_assert(ichild == 0);
00222   mutex = new_ProxyMutex();
00223 }
00224 
00225 struct ReRegressionSM: public RegressionSM
00226 {
00227   virtual void run() {
00228     if (time(NULL) < 1) { // example test
00229       rprintf(t,"impossible");
00230       done(REGRESSION_TEST_FAILED);
00231     } else
00232       done(REGRESSION_TEST_PASSED);
00233   }
00234   ReRegressionSM(RegressionTest *at) : RegressionSM(at) {}
00235   virtual RegressionSM *clone() { return new ReRegressionSM(*this); }
00236   ReRegressionSM(const ReRegressionSM &o) {
00237     t = o.t;
00238   }
00239 };
00240 
00241 REGRESSION_TEST(RegressionSM)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus)
00242 {
00243   RegressionSM *top_sm = r_sequential(t, r_parallel(t, new ReRegressionSM(t), new ReRegressionSM(t), NULL_PTR),
00244                r_sequential(t, new ReRegressionSM(t), new ReRegressionSM(t), NULL_PTR),
00245                r_parallel(t, 3, new ReRegressionSM(t)), r_sequential(t, 3, new ReRegressionSM(t)),
00246                r_parallel(t, r_sequential(t, 2, new ReRegressionSM(t)),
00247                           r_parallel(t, 2, new ReRegressionSM(t)), NULL_PTR),
00248                NULL_PTR);
00249   top_sm->run(pstatus);
00250 }

Generated by  doxygen 1.7.1