libs/ck-libs/liveViz3d/lv3d0_server.C

Go to the documentation of this file.
00001 /*
00002   Implementation of the simplest server portion 
00003   of the liveViz3d library.
00004   
00005   Orion Sky Lawlor, olawlor@acm.org, 2003/9/13
00006 */
00007 #include "lv3d0_server.h"
00008 #include "pup_toNetwork.h"
00009 #include <vector>
00010 #include <map>
00011 #include <algorithm>
00012 #include "stats.h"
00013 #include "LBDatabase.h" /* for set_avail_vector */
00014 
00015 #include "lv3d0.decl.h" //For LV3D0_ViewMsg
00016 void _registerlv3d1(void);
00017 void _registerliveViz(void);
00018 // #include "lv3d1.decl.h" //For LV3D1 registration (for .def file)
00019 
00020 static /* readonly */ CProxy_LV3D0_Manager mgrProxy;
00021 static /* readonly */ int LV3D_dosave_views=0; 
00022 static /* readonly */ int LV3D_disable_ship_prio=0; 
00023 static /* readonly */ int LV3D_disable_ship_replace=0; 
00024 static /* readonly */ int LV3D_disable_ship_throttle=0; 
00025 static /* readonly */ int LV3D_disable_ship=0;  
00026 #define masterProcessor 0
00027 
00033 class LV3D0_ViewMsg : public CMessage_LV3D0_ViewMsg {
00034 public:
00035 // (these fields are all copied from our viewable)
00037         CkViewableID id;
00038         
00041         int prio;
00042         
00044         int pixels;
00045         
00047         int clientID;
00048         
00050         int view_size;
00052         unsigned char *view;
00053         
00055         static LV3D0_ViewMsg *new_(CkView *view);
00056         static void delete_(LV3D0_ViewMsg *m);
00057 };
00058 
00060 LV3D0_ViewMsg *LV3D0_ViewMsg::new_(CkView *vp) {
00061         PUP_toNetwork_sizer ps; ps|vp;
00062         int view_size=ps.size();
00063         
00064         LV3D0_ViewMsg *m=new (view_size,0) LV3D0_ViewMsg;
00065         m->id=vp->id;
00066         m->prio=vp->prio;
00067         m->pixels=vp->pixels;
00068         m->view_size=view_size;
00069         PUP_toNetwork_pack pp(m->view); pp|vp;
00070         return m;
00071 }
00072 void LV3D0_ViewMsg::delete_(LV3D0_ViewMsg *m) {
00073         delete m;
00074 }
00075 
00076 
00077 /********** LV3D0_ClientManager: outgoing images ********/
00078 
00080 class CkViewPrioHolder {
00081 public:
00082         LV3D0_ViewMsg *v;
00083         
00084         CkViewPrioHolder(LV3D0_ViewMsg *v_) :v(v_) {}
00085         
00086         // Comparison operator, used to keep a priority queue.
00087         //  Returns true if we should be processed before this guy.
00088         bool operator<(const CkViewPrioHolder &h) const {
00089                 if (v->prio<h.v->prio) return true;
00090                 if (v->prio>h.v->prio) return false;
00091                 /* else priorities are equal: compare ID's */
00092                 int i;
00093                 for (i=0;i<4;i++) {
00094                         if (v->id.id[i]<h.v->id.id[i]) return true;
00095                         if (v->id.id[i]>h.v->id.id[i]) return false;
00096                 }
00097                 // Woa-- they're *identical*.  Just pick smaller one.
00098                 return v < h.v;
00099         }
00100 };
00101 
00107 class CkViewPrioSorter {
00108 
00109         /*
00110           We generally want to process views in priority order;
00111           but we never want to send an earlier view to a client
00112           when a later view is available.
00113           
00114           This means we need to keep views in a priority queue
00115           (for extraction), but also provide a way to look up 
00116           the view (to prevent duplicates).
00117         */
00118         
00119         // This indexes unsent views by ID:
00120         CkHashtableT<CkViewableID,CkViewPrioHolder> id2view;
00121 
00122         // This indexes unsent views by priority:
00123         //   The "key" is all that's needed here-- the "obj" field is useless.
00124         typedef std::map<CkViewPrioHolder,char> prio2view_t;
00125         prio2view_t prio2view;
00126         
00127 public:
00128         CkViewPrioSorter() 
00129                 :id2view(129,0.2)
00130         {
00131         }
00132         ~CkViewPrioSorter() {
00133                 for (iterator it=begin();it!=end();++it)
00134                         delete (*it).first.v;
00135         }
00136         
00138         bool isEmpty(void) const {return prio2view.size()==0;}
00139         
00141         void add(LV3D0_ViewMsg *v)
00142         {
00143                 if (LV3D_disable_ship_prio) v->prio=0;
00144                 CkViewPrioHolder old=id2view.get(v->id);
00146                 if (old.v!=0 && !LV3D_disable_ship_replace) 
00147                 { /* An old entry from this viewable exists: remove it.
00148                      This is so we always send off the most up-to-date view. */
00149                         // printf("[OUT] Replacing old view for viewable %d\n",v->id.id[0]);
00150                         if (v->prio>old.v->prio)  // keep old priority if it's higher
00151                                 v->prio=old.v->prio;
00152                         prio2view.erase(prio2view.find(old));
00153                         delete old.v;
00154                 }
00155                 else {
00156                         // printf("[OUT] Queueing new view for viewable %d\n",v->id.id[0]);
00157                 }
00158                 id2view.put(v->id)=CkViewPrioHolder(v);
00159                 prio2view.insert(std::make_pair(CkViewPrioHolder(v),(char)1));
00160         }
00161         
00164         typedef prio2view_t::iterator iterator;
00165         iterator begin(void) {return prio2view.begin();}
00166         iterator end(void) {return prio2view.end();}
00167         
00170         LV3D0_ViewMsg *extract(const iterator &doomed) {
00171                 LV3D0_ViewMsg *v=(*doomed).first.v;
00172                 prio2view.erase(doomed);
00173                 id2view.remove(v->id);
00174                 return v;
00175         }
00176 };
00177 
00179 class LV3D0_ClientManager : public CkViewPrioSorter {
00180 public:
00181         virtual ~LV3D0_ClientManager() {}
00182         virtual void add(LV3D0_ViewMsg *v) =0;
00183         virtual void getViews(void) {}
00184         virtual void whenEmptyCallback(const CkCallback &cb) {}
00185 };
00186 
00187 /******************** Shipping views to Master ***************/
00190 int LV3D0_toMaster_bytesPer=100*1024;
00192 int LV3D0_toMaster_bytesMax=2*LV3D0_toMaster_bytesPer;
00193 
00194 static void toMaster_fillBucket(void *ptr,double timer);
00195 
00196 static stats::op_t op_master_count=stats::count_op("master.count","Number of final master impostors","count");
00197 static stats::op_t op_master_bytes=stats::count_op("master.bytes","Number of final master bytes","bytes");
00198 static stats::op_t op_master_pixels=stats::count_op("master.pixels","Number of final master pixels","pixels");
00199 
00206 class LV3D0_ClientManager_toMaster : public LV3D0_ClientManager {
00208         int bucket_bytes;
00209         int cidx;
00210 public:
00211         LV3D0_ClientManager_toMaster() {
00212                 bucket_bytes=LV3D0_toMaster_bytesMax;
00213                 cidx=CcdCallOnConditionKeep(CcdPERIODIC_10ms,toMaster_fillBucket,this);
00214         }
00215         ~LV3D0_ClientManager_toMaster() {
00216                 CcdCancelCallOnConditionKeep(CcdPERIODIC_10ms,cidx);
00217         }
00218         
00220         virtual void add(LV3D0_ViewMsg *v) {
00221                 CkViewPrioSorter::add(v);
00222                 progress();
00223         }
00225         void progress(void) {
00226                 // printf("progress: bucket=%d\n",bucket_bytes);
00227                 if (CmiLongSendQueue(CmiNodeOf(masterProcessor),LV3D0_toMaster_bytesMax))
00228                         return; /* too many outstanding messages already! */
00229                 while ((!isEmpty()) && (bucket_bytes>0 || LV3D_disable_ship_throttle)) 
00230                 {
00231                         LV3D0_ViewMsg *v=extract(begin());
00232                         bucket_bytes-=v->view_size;
00233                         stats::get()->add(1.0,op_master_count);
00234                         stats::get()->add(v->view_size,op_master_bytes);
00235                         stats::get()->add(v->pixels,op_master_pixels);
00236                         mgrProxy[masterProcessor].addView(v);
00237                 }
00238         }
00241         void fillBucket(void) {
00242                 bucket_bytes+=LV3D0_toMaster_bytesPer;
00243                 if (bucket_bytes>LV3D0_toMaster_bytesMax) 
00244                         bucket_bytes=LV3D0_toMaster_bytesMax;
00245                 progress();
00246         }
00247 };
00249 static void toMaster_fillBucket(void *ptr,double timer) {
00250         LV3D0_ClientManager_toMaster *p=(LV3D0_ClientManager_toMaster *)ptr;
00251         p->fillBucket();
00252 }
00253 
00254 /************** Shipping views to Client ***************/
00256 int LV3D0_toClient_bytesPer=100*1024;
00257 
00258 static stats::op_t op_client_pack=stats::time_op("client.pack","Time spent packing final client impostors");
00259 static stats::op_t op_client_count=stats::count_op("client.count","Number of final client impostors","count");
00260 static stats::op_t op_client_bytes=stats::count_op("client.bytes","Number of final client bytes","bytes");
00261 static stats::op_t op_client_pixels=stats::count_op("client.pixels","Final client impostor pixels","pixels");
00262 
00267 class LV3D0_ClientManager_toClient : public LV3D0_ClientManager
00268 {
00269         typedef CkViewPrioSorter super;
00270         bool hasDelayed;
00271         CcsDelayedReply delayedReply;
00272         
00274         CkVec<CkCallback> emptyCallbacks;
00275         void checkEmpty(void) {
00276                 if (isEmpty()) { /* no views left-- send all empty callbacks */
00277                         for (int i=0;i<emptyCallbacks.size();i++)
00278                                 emptyCallbacks[i].send();
00279                         emptyCallbacks.resize(0);
00280                 }
00281         }
00282         
00284         void sendReply(CcsDelayedReply repl) {
00285                 stats::op_sentry stats_sentry(op_client_pack);
00286                 
00287         // Figure out how many views we can afford to send at once:
00288                 int len=4; /* leave room for the "length" field */
00289                 int n=0;
00290                 iterator it=begin();
00291                 while (it!=end() && (len<LV3D0_toClient_bytesPer || LV3D_disable_ship_throttle)) {
00292                         LV3D0_ViewMsg *v=(*it++).first.v;
00293                         len+=v->view_size;
00294                         n++;
00295                 }
00296         
00297         // Pack the views into a network buffer:
00298                 // CmiPrintf("[OUT] Sending off %d new views (%d bytes)\n",n,len);
00299                 
00300                 // FIXME: special case this when n==1.
00301                 char *retMsg=new char[len];
00302                 PUP_toNetwork_pack pp(retMsg);
00303                 pp|n;
00304                 for (int i=0;i<n;i++) {
00305                         LV3D0_ViewMsg *v=extract(begin());
00306                         pp(v->view,v->view_size);
00307                         stats::get()->add(v->pixels,op_client_pixels);
00308                         delete v;
00309                 }
00310                 
00311                 if (len!=pp.size()) {
00312                         CkError("Sizing pup was %d bytes; packing pup was %d!\n",
00313                                 len,pp.size());
00314                         CkAbort("Pup size mismatch (logic error) in LV3D0_!\n");
00315                 }
00316 
00317                 stats::get()->add(1.0,op_client_count);
00318                 stats::get()->add(len,op_client_bytes);
00319                 CcsSendDelayedReply(repl,len,retMsg);
00320                 delete[] retMsg;
00321                 
00322                 // CmiPrintf("[OUT] Done sending off %d views\n",n);
00323                 checkEmpty();
00324         }
00325         
00326 public:
00327         LV3D0_ClientManager_toClient() 
00328         {
00329                 hasDelayed=false;
00330         }
00331         
00334         virtual void add(LV3D0_ViewMsg *v) {
00335                 super::add(v);
00336                 
00337                 if (hasDelayed) { //There's already somebody waiting
00338                         hasDelayed=false;
00339                         sendReply(delayedReply);
00340                 }
00341         }
00342         
00345         virtual void getViews(void) {
00346                 if (isEmpty()) { //Nothing to send yet-- wait for it
00347                         // printf("[OUT] Views requested, but none available\n");
00348                         hasDelayed=true;
00349                         delayedReply=CcsDelayReply();
00350                 }
00351                 else 
00352                 {
00353                         sendReply(CcsDelayReply());
00354                 }       
00355         }
00356         
00358         virtual void whenEmptyCallback(const CkCallback &cb) {
00359                 emptyCallbacks.push_back(cb);
00360                 checkEmpty();
00361         }
00362 };
00363 
00368 class LV3D0_Manager : public CBase_LV3D0_Manager {
00370         CkHashtableT<CkHashtableAdaptorT<int>,LV3D0_ClientManager *> clientTable;
00371         
00373         int nextClientID;
00374 public:
00375         LV3D0_Manager(void);
00376         
00379         int newClient(void);
00380         
00382         LV3D0_ClientManager *getClient(int clientID);
00383         
00387         void getViews(int clientID) {
00388                 getClient(clientID)->getViews();
00389         }
00390         
00392         inline void addView(LV3D0_ViewMsg *m) {
00393                 getClient(m->clientID)->add(m);
00394         }
00395 };
00396 
00397 
00398 LV3D0_Manager::LV3D0_Manager(void)
00399 {
00400         mgrProxy=thisgroup;
00401         nextClientID=1;
00402 }
00403 
00404 int LV3D0_Manager::newClient(void)
00405 {
00406         return nextClientID++;
00407 }
00408 
00410 LV3D0_ClientManager *LV3D0_Manager::getClient(int clientID)
00411 {
00412         LV3D0_ClientManager *m=clientTable.get(clientID);
00413         if (m==NULL) {
00414                 if (CkMyPe()==masterProcessor) 
00415                         m=new LV3D0_ClientManager_toClient;
00416                 else
00417                         m=new LV3D0_ClientManager_toMaster;
00418                 clientTable.put(clientID)=m;
00419         }
00420         return m;
00421 }
00422 
00423 static stats::op_t op_deposit_views=stats::count_op("deposit.views","CkView count","CkViews");
00424 static stats::op_t op_deposit_bytes=stats::count_op("deposit.bytes","CkView sizes","bytes");
00425 static stats::op_t op_deposit_pixels=stats::count_op("deposit.pixels","CkView pixels","pixels");
00426 
00427 /***** Saving Views to File ********/
00429 CkpvStaticDeclare(FILE *,LV3D_save_views);
00430 static double LV3D_save_viewStart=0; 
00431 static char *LV3D_copy_view_src=0, *LV3D_copy_view_dest=0;
00432 static stats::op_t op_save=stats::time_op("save.time","Time spent saving views to disk");
00433 
00434 static void LV3D_save_init(void) {
00435         if (LV3D_copy_view_src==0) return;
00436         if (CkpvAccess(LV3D_save_views)) { /* file already open: close and re-open */
00437                 fclose(CkpvAccess(LV3D_save_views));
00438         }
00439         
00440         char fName[1024];
00441         sprintf(fName,LV3D_copy_view_src,CkMyPe());
00442         FILE *f=fopen(fName,"wb");
00443         if (f==NULL) CmiAbort("Couldn't create save view file!\n");
00444         CkpvAccess(LV3D_save_views)=f;
00445         CkPrintf("Created views file %s\n",fName);
00446 }
00447 
00448 static void LV3D_save_start(void)
00449 {
00450         if (!LV3D_dosave_views) return;
00451         LV3D_save_init();
00452         LV3D_save_viewStart=CkWallTimer(); //< HACK!
00453 }
00454 
00455 struct savedViewRecord {
00456 public:
00457         double t; /* Time view was rendered */
00458         int view_size; /* size, in bytes, of view buffer */
00459         void pup(PUP::er &p) {
00460                 p|t;
00461                 p|view_size;
00462         }
00463 };
00464 
00465 static int LV3D_save_view(LV3D0_ViewMsg *v) {
00466         if (!LV3D_dosave_views) return 0;
00467         if (!CkpvAccess(LV3D_save_views)) return 0;
00468         stats::op_sentry stats_sentry(op_save);
00469         savedViewRecord rec;
00470         rec.t=CkWallTimer()-LV3D_save_viewStart;
00471         rec.view_size=v->view_size;
00472         enum {bufLen=sizeof(rec)};
00473         char buf[bufLen];
00474         PUP_toNetwork_pack p(buf); p|rec;
00475         FILE *f=CkpvAccess(LV3D_save_views);
00476         if (1!=fwrite(buf,p.size(),1,f)) CmiAbort("Can't write header to saved view file!\n");
00477         if (1!=fwrite(v->view,v->view_size,1,f)) CmiAbort("Can't write view to saved view file!\n");
00478         delete v;
00479         return 1;
00480 }
00481 
00482 static void LV3D_save_finish(void) {
00483         if (!LV3D_dosave_views) return;
00484         if (!CkpvAccess(LV3D_save_views)) return;
00485         fclose(CkpvAccess(LV3D_save_views));
00486         CkpvAccess(LV3D_save_views)=0;
00487         if (LV3D_copy_view_dest) { /* Copy view file to dest directory */
00488                 char fSrc[1024], fDest[1024], cmd[2048];
00489                 sprintf(fSrc,LV3D_copy_view_src,CkMyPe());
00490                 sprintf(fDest,LV3D_copy_view_dest,CkMyPe());
00491                 sprintf(cmd,"cp '%s' '%s' && rm '%s'", fSrc,fDest, fSrc);
00492                 CkPrintf("Copying views file from %s to %s\n",fSrc,fDest);
00493                 system(cmd);
00494                 CkPrintf("Views file copied.\n");
00495         }
00496 }
00497 
00498 
00503 void LV3D0_Deposit(CkView *v,int clientID) {
00504         stats::stats *s=stats::get();
00505         s->add(1.0,op_deposit_views);
00506         s->add(v->pixels,op_deposit_pixels);
00507         LV3D0_ViewMsg *vm=LV3D0_ViewMsg::new_(v);
00508         if (LV3D_save_view(vm)) return;
00509         s->add(vm->view_size,op_deposit_bytes);
00510         if (LV3D_disable_ship) {delete vm; return;}
00511         vm->clientID=clientID;
00512         mgrProxy.ckLocalBranch()->addView(vm);
00513 }
00514 
00515 
00516 /**************** Performance collection ***************/
00517 
00518 static stats::op_t op_pes=stats::count_op("cmi.pes","Processors","pes");
00519 static stats::op_t op_time=stats::time_op("cmi.time","Elapsed wall-clock time");
00520 static stats::op_t op_unknown=stats::time_op("cmi.unknown","Unaccounted-for time");
00521 static stats::op_t op_idle=stats::time_op("cmi.idle","Time spent waiting for data");
00522 
00523 
00524 static CcsDelayedReply statsReply;
00525 
00527 static void printStats(void *rednMsg) {
00528         CkReductionMsg *m=(CkReductionMsg *)rednMsg;
00529         
00530         // FIXME: make stats::print return a std::string, instead
00531         //  of this horrible "print to a file and read it back" business.
00532         
00533         char tmpFileName[100];
00534         sprintf(tmpFileName,"/tmp/stats.%d.%d",CkMyPe(),(int)getpid());
00535         FILE *f=fopen(tmpFileName,"w");
00536         int len=0; void *buf=0;
00537         if (f!=NULL) {
00538                 /* write stats to temp file */
00539                 const stats::stats *s=(const stats::stats *)m->getData();
00540                 s->print(f,"total",1.0);
00541                 s->print(f,"per_second",1.0/s->get(op_time));
00542                 s->print(f,"per_pe-second",1.0/(CkNumPes()*s->get(op_time)));
00543                 fclose(f);
00544                 
00545                 /* Read stats back */
00546                 f=fopen(tmpFileName,"r");
00547                 fseek(f,0,SEEK_END);
00548                 len=ftell(f);
00549                 buf=malloc(len);
00550                 fseek(f,0,SEEK_SET);
00551                 fread(buf,1,len,f);
00552                 fclose(f);
00553                 
00554                 /* print to screen */
00555                 write(1,buf,len);
00556                 printf("\n");
00557         
00558         }
00559         unlink(tmpFileName);
00560         CcsSendDelayedReply(statsReply,len,buf);
00561         free(buf);
00562         delete m;
00563 }
00564 
00566 static void perfmanager_stats_idle(void *ptr,double timer)
00567 {
00568         stats::swap(op_idle);
00569 }
00570 
00571 class LV3D_PerfManager : public CBase_LV3D_PerfManager {
00572         double startTime;
00573 public:
00574         LV3D_PerfManager(void) {
00575                 zero();
00576                 CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,perfmanager_stats_idle,0);
00577                 CcdCallOnConditionKeep(CcdPROCESSOR_END_IDLE,perfmanager_stats_idle,0);
00578                 
00579                 /* Don't let the load balancer move stuff onto node 0: */
00580                 char *bitmap=new char[CkNumPes()];
00581                 for (int i=0;i<CkNumPes();i++)
00582                         bitmap[i]=(i!=masterProcessor);
00583                 set_avail_vector(bitmap);
00584         }
00587         void zero(void) { 
00588                 stats::stats *s=stats::get();
00589                 stats::swap(op_unknown); // so unknown gets zerod out
00590                 s->zero();
00591                 s->add(1.0,op_pes);
00592                 startTime=stats::time();
00593                 stats::swap(op_unknown);
00594                 LV3D_save_start();
00595         }
00598         void collect(void) { 
00599                 stats::stats *s=stats::get();
00600                 if (CkMyPe()==0) s->set(stats::time()-startTime,op_time);
00601                 else s->set(0,op_time);
00602                 stats::swap(op_unknown);
00603                 contribute(sizeof(double)*stats::op_len,&s->t[0],CkReduction::sum_double,
00604                         CkCallback(printStats));
00605                 LV3D_save_finish();
00606                 zero();
00607         }
00608         void traceOn(void) {
00609                 traceBegin();
00610         }
00611         void startBalance(void) {
00612                 LBClearLoads();
00613                 LBTurnInstrumentOn();
00614         }
00615         void doneBalance(void) {
00616                 LBTurnInstrumentOff();
00617         }
00618         void throttle(int throttleOn) { LV3D_disable_ship_throttle=!throttleOn; }
00619 };
00620 
00621 
00622 /*************** CCS Interface ***************/
00623 //This only ever gets set on processor 0 (FIXME: checkpointing)
00624 static LV3D_Universe *theUniverse=0;
00625 static LV3D_ServerMgr *theMgr=0;
00626 static CProxy_LV3D_PerfManager perfMgr;
00627 
00628 LV3D_ServerMgr::~LV3D_ServerMgr() {}
00629 
00637 extern "C" void LV3D0_setup(char *msg) {
00638         CmiFree(msg);
00639         int clientID=mgrProxy.ckLocalBranch()->newClient();
00640         PUP_toNetwork_sizer sp;
00641         sp|clientID;
00642         sp|theUniverse;
00643         unsigned char *buf=new unsigned char[sp.size()];
00644         PUP_toNetwork_pack pp(buf);
00645         pp|clientID;
00646         pp|theUniverse;
00647         CcsSendReply(sp.size(),buf);
00648         theMgr->newClient(clientID);
00649         CmiPrintf("Registered (client %d)\n",clientID);
00650         delete[] buf;
00651         perfMgr.zero(); // New client implicitly zeros out stats.
00652 }
00653 
00654 
00655 static stats::op_t op_view_count=stats::count_op("client.views","New viewpoints","Views");
00656 
00665 extern "C" void LV3D0_newViewpoint(char *msg) {
00666         PUP_toNetwork_unpack p(&msg[CmiMsgHeaderSizeBytes]);
00667         LV3D_ViewpointMsg *m=new LV3D_ViewpointMsg;
00668         p|m->clientID;
00669         p|m->frameID;
00670         m->viewpoint.pup(p);
00671         // CmiPrintf("New user viewpoint (client %d, frame %d)\n",clientID,frameID);
00672         theMgr->newViewpoint(m);
00673         stats::get()->add(1.0,op_view_count);
00674 }
00675 
00686 extern "C" void LV3D0_getViews(char *msg) {
00687         PUP_toNetwork_unpack p(&msg[CmiMsgHeaderSizeBytes]);
00688         int clientID; p|clientID; CmiFree(msg);
00689         mgrProxy.ckLocalBranch()->getViews(clientID);
00690 }
00691 
00692 /*
00693 "lv3d_qd" CCS handler:
00694         Sent by the client to wait until all views have been
00695 updated and sent back.  No input or output data: control flow only.
00696 */
00697 struct lv3d_qdState {
00699         int clientID;
00700         
00702         CcsDelayedReply reply;
00703 };
00704 
00705 static void qdDoneFn(void *param,void *msg);
00706 static void emptyDoneFn(void *param,void *msg);
00707 
00708 extern "C" void LV3D0_qd(char *msg) /* stage 1 */
00709 {
00710         lv3d_qdState *s=new lv3d_qdState;
00711         PUP_toNetwork_unpack p(&msg[CmiMsgHeaderSizeBytes]);
00712         p|s->clientID;
00713         s->reply=CcsDelayReply();
00714         CmiFree(msg);
00715         CkCallback cb(qdDoneFn,s);
00716         CkStartQD(cb); /* finish CCS reply after quiescence */
00717 }
00718 static void qdDoneFn(void *param,void *msg)  /* stage 2 */
00719 {
00720         lv3d_qdState *s=(lv3d_qdState *)param;
00721         mgrProxy.ckLocalBranch()->getClient(s->clientID)->whenEmptyCallback(
00722                 CkCallback(emptyDoneFn,s));
00723 }
00724 static void emptyDoneFn(void *param,void *msg) /* stage 3 */
00725 {
00726         lv3d_qdState *s=(lv3d_qdState *)param;
00727         CcsSendDelayedReply(s->reply,0,0);
00728         delete s;
00729 }
00730 
00737 extern "C" void LV3D0_flush(char *msg) {
00738         int clientID;
00739         PUP_toNetwork_unpack p(&msg[CmiMsgHeaderSizeBytes]);
00740         p|clientID;
00741         CmiFree(msg);
00742         theMgr->newClient(clientID);
00743 }
00744 
00745 /*
00746 "lv3d_startbal" CCS handler:
00747         Begin a load balancing phase.  Normally followed by 
00748         some rendering, then an endbalance.
00749 */
00750 extern "C" void LV3D0_startbalance(char *msg) 
00751 {
00752         CkPrintf("CCS call to LV3D0_startbalance\n");
00753         perfMgr.startBalance();
00754         CmiFree(msg);
00755 }
00756 /*
00757 "lv3d_endbal" CCS handler:
00758         Go to sync.  Exactly one end must follow 
00759         each startbalance call.
00760 */
00761 extern "C" void LV3D0_endbalance(char *msg) 
00762 {
00763         CkPrintf("CCS call to LV3D0_endbalance\n");
00764         theMgr->doBalance();
00765         perfMgr.doneBalance();
00766         LV3D0_qd(msg); /* wait for quiescence */
00767 }
00768 
00769 /*
00770 "lv3d_quit" CCS handler:
00771         Shut down the program.
00772 */
00773 extern "C" void LV3D0_quit(char *msg) 
00774 {
00775         CkPrintf("Exiting: CCS call to LV3D0_quit\n");
00776         CcsSendReply(0,0);
00777         CmiFree(msg);
00778         CkExit();
00779 }
00781 extern "C" void LV3D0_zero(char *msg) 
00782 {
00783         CkPrintf("Zeroing statistics\n");
00784         perfMgr.zero();
00785         CmiFree(msg);
00786 }
00788 extern "C" void LV3D0_stats(char *msg) 
00789 {
00790         CkPrintf("Printing statistics\n");
00791         statsReply=CcsDelayReply();
00792         perfMgr.collect();
00793         CmiFree(msg);
00794 }
00796 extern "C" void LV3D0_trace(char *msg) 
00797 {
00798         CkPrintf("Tracing turned on\n");
00799         perfMgr.traceOn();
00800         CmiFree(msg);
00801 }
00802 extern "C" void LV3D0_throttle0(char *msg) { perfMgr.throttle(0); CmiFree(msg); }
00803 extern "C" void LV3D0_throttle1(char *msg) { perfMgr.throttle(1); CmiFree(msg); }
00804 
00809 void LV3D0_Init(LV3D_Universe *clientUniverse,LV3D_ServerMgr *mgr)
00810 {
00811         if (clientUniverse==0)
00812                 clientUniverse=new LV3D_Universe();
00813         theUniverse=clientUniverse;
00814         theMgr=mgr;
00815         CcsRegisterHandler("lv3d_setup",(CmiHandler)LV3D0_setup);
00816         CcsRegisterHandler("lv3d_flush",(CmiHandler)LV3D0_flush);
00817         CcsRegisterHandler("lv3d_newViewpoint",(CmiHandler)LV3D0_newViewpoint);
00818         CcsRegisterHandler("lv3d_getViews",(CmiHandler)LV3D0_getViews);
00819         CcsRegisterHandler("lv3d_qd",(CmiHandler)LV3D0_qd);
00820         CcsRegisterHandler("lv3d_startbal",(CmiHandler)LV3D0_startbalance);
00821         CcsRegisterHandler("lv3d_endbal",(CmiHandler)LV3D0_endbalance);
00822         CcsRegisterHandler("lv3d_quit",(CmiHandler)LV3D0_quit);
00823         CcsRegisterHandler("lv3d_zero",(CmiHandler)LV3D0_zero);
00824         CcsRegisterHandler("lv3d_stats",(CmiHandler)LV3D0_stats);
00825         CcsRegisterHandler("lv3d_trace",(CmiHandler)LV3D0_trace);
00826         CcsRegisterHandler("lv3d_throttle0",(CmiHandler)LV3D0_throttle0);
00827         CcsRegisterHandler("lv3d_throttle1",(CmiHandler)LV3D0_throttle1);
00828         CProxy_LV3D0_Manager::ckNew();
00829         perfMgr=CProxy_LV3D_PerfManager::ckNew();
00830 }
00831 
00835 void LV3D0_ProcInit(void) {
00836         CkpvInitialize(FILE *,LV3D_save_views);
00837         CkpvAccess(LV3D_save_views)=0;
00838         CmiGetArgStringDesc(CkGetArgv(),"+LV3D_save_views",&LV3D_copy_view_src,"Save rendered views to a file with this pattern.  Use like '/tmp/views.%d.pe'");
00839         CmiGetArgStringDesc(CkGetArgv(),"+LV3D_copy_views",&LV3D_copy_view_dest,"Copy view files to this pattern.  Use like 'views.%d.pe'");
00840         LV3D0_toMaster_bytesPer=LV3D0_toMaster_bytesPer/CkNumPes();
00841         LV3D0_toMaster_bytesMax=LV3D0_toMaster_bytesMax/CkNumPes();
00842 }
00843 void LV3D0_NodeInit(void) {
00844         CkViewNodeInit();
00845 }
00846 
00847 
00848 #include "lv3d0.def.h"
00849 #include "liveViz3d.def.h"
00850 

Generated on Sun Jun 29 13:29:21 2008 for Charm++ by  doxygen 1.5.1